diff --git a/plugins/builtin/source/content/tools_entries.cpp b/plugins/builtin/source/content/tools_entries.cpp index 324623453..bc1fe1a5d 100644 --- a/plugins/builtin/source/content/tools_entries.cpp +++ b/plugins/builtin/source/content/tools_entries.cpp @@ -124,9 +124,169 @@ namespace hex::plugin::builtin { void drawColorPicker() { static std::array pickedColor = { 0 }; + static std::string rgba8; - ImGui::SetNextItemWidth(300_scaled); - ImGui::ColorPicker4("hex.builtin.tools.color"_lang, pickedColor.data(), ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex); + struct BitValue { + int bits; + float color; + float saturationMultiplier; + char name; + u8 index; + }; + + static std::array bitValues = { + BitValue{ 8, 0.00F, 1.0F, 'R', 0 }, + BitValue{ 8, 0.33F, 1.0F, 'G', 1 }, + BitValue{ 8, 0.66F, 1.0F, 'B', 2 }, + BitValue{ 8, 0.00F, 0.0F, 'A', 3 } + }; + + if (ImGui::BeginTable("##color_picker_table", 3)) { + ImGui::TableSetupColumn("##picker", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, 300_scaled); + ImGui::TableSetupColumn("##sliders", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, 80_scaled); + ImGui::TableSetupColumn("##output", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_NoResize); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + // Draw main color picker widget + ImVec2 startCursor, endCursor; + { + ImGui::PushItemWidth(-1); + startCursor = ImGui::GetCursorPos(); + ImGui::ColorPicker4("hex.builtin.tools.color"_lang, pickedColor.data(), ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex); + endCursor = ImGui::GetCursorPos(); + ImGui::ColorButton("##color_button", ImColor(pickedColor[0], pickedColor[1], pickedColor[2], pickedColor[3]), ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(300_scaled, 0)); + ImGui::PopItemWidth(); + } + + ImGui::TableNextColumn(); + + const auto colorName = hex::format("{}{}{}{}", bitValues[0].name, bitValues[1].name, bitValues[2].name, bitValues[3].name); + + // Draw color bit count sliders + { + static auto drawBitsSlider = [&](BitValue *bitValue) { + // Change slider color + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(bitValue->color, 0.5f * bitValue->saturationMultiplier, 0.5f).Value); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(bitValue->color, 0.6f * bitValue->saturationMultiplier, 0.5f).Value); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(bitValue->color, 0.7f * bitValue->saturationMultiplier, 0.5f).Value); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(bitValue->color, 0.9f * bitValue->saturationMultiplier, 0.9f).Value); + + // Draw slider + ImGui::PushID(&bitValue->bits); + auto format = hex::format("%d\n{}", bitValue->name); + ImGui::VSliderInt("##slider", ImVec2(18_scaled, (endCursor - startCursor).y - 3_scaled), &bitValue->bits, 0, 16, format.c_str(), ImGuiSliderFlags_AlwaysClamp); + ImGui::PopID(); + + ImGui::PopStyleColor(4); + }; + + // Force sliders closer together + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 4)); + + // Draw a slider for each color component + for (u32 index = 0; auto &bitValue : bitValues) { + // Draw slider + drawBitsSlider(&bitValue); + + // Configure drag and drop source and target + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + // Set the current slider index as the payload + ImGui::SetDragDropPayload("BIT_VALUE", &index, sizeof(u32)); + + // Draw a color button to show the color being dragged + ImGui::ColorButton("##color_button", ImColor::HSV(bitValue.color, 0.5f * bitValue.saturationMultiplier, 0.5f).Value); + + ImGui::EndDragDropSource(); + } + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("BIT_VALUE"); payload != nullptr) { + auto otherIndex = *static_cast(payload->Data); + + // Swap the currently hovered slider with the one being dragged + std::swap(bitValues[index], bitValues[otherIndex]); + } + ImGui::EndDragDropTarget(); + } + + ImGui::SameLine(); + + index += 1; + } + + ImGui::NewLine(); + + // Draw color name below sliders + ImGui::TextFormatted("{}", colorName); + + ImGui::PopStyleVar(); + } + + ImGui::TableNextColumn(); + + // Draw encoded color values + { + // Calculate int and float representations of the selected color + std::array intColor = {}; + std::array floatColor = {}; + for (u32 index = 0; auto &bitValue : bitValues) { + intColor[index] = u64(std::round(static_cast(pickedColor[bitValue.index]) * std::numeric_limits::max())) >> (32 - bitValue.bits); + floatColor[index] = pickedColor[bitValue.index]; + + index += 1; + } + + // Draw a table with the color values + if (ImGui::BeginTable("##value_table", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 0))) { + const static auto drawValue = [](const char *name, auto formatter) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + // Draw name of the formatting + ImGui::TextUnformatted(name); + + ImGui::TableNextColumn(); + + // Draw value + ImGui::PushID(name); + ImGui::TextFormattedSelectable("{}", formatter()); + ImGui::PopID(); + }; + + const u32 bitCount = bitValues[0].bits + bitValues[1].bits + bitValues[2].bits + bitValues[3].bits; + + // Draw the different representations + + drawValue("HEX", [&] { + u64 hexValue = 0; + for (u32 index = 0; auto &bitValue : bitValues) { + hexValue <<= bitValue.bits; + hexValue |= u64(intColor[index]) & hex::bitmask(bitValue.bits); + index += 1; + } + + return hex::format("#{0:0{1}X}", hexValue, bitCount / 4); + }); + + drawValue(colorName.c_str(), [&] { + return hex::format("{}({}, {}, {}, {})", colorName, intColor[0], intColor[1], intColor[2], intColor[3]); + }); + + drawValue("Vector4f", [&] { + return hex::format("{{ {:.2}F, {:.2}F, {:.2}F, {:.2}F }}", floatColor[0], floatColor[1], floatColor[2], floatColor[3]); + }); + + drawValue("Percentage", [&] { + return hex::format("{{ {}%, {}%, {}%, {}% }}", u32(floatColor[0] * 100), u32(floatColor[1] * 100), u32(floatColor[2] * 100), u32(floatColor[3] * 100)); + }); + + ImGui::EndTable(); + } + } + + ImGui::EndTable(); + } } void drawMathEvaluator() {