1
0
mirror of synced 2024-11-13 18:50:53 +01:00

feat: Make color picker tool much more useful

This commit is contained in:
WerWolv 2023-11-11 20:56:50 +01:00
parent 7405219fb8
commit 5a4f31bfa5

View File

@ -124,9 +124,169 @@ namespace hex::plugin::builtin {
void drawColorPicker() {
static std::array<float, 4> 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<const u32 *>(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<u32, 4> intColor = {};
std::array<float, 4> floatColor = {};
for (u32 index = 0; auto &bitValue : bitValues) {
intColor[index] = u64(std::round(static_cast<long double>(pickedColor[bitValue.index]) * std::numeric_limits<u32>::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() {