Added ColorPicker3/ColorPicker4, refactoring ColorEdit3/ColorEdit4 adding a bunch of flags and access to picker (wip #346)

Still pretty much experimenting so may break API
This commit is contained in:
ocornut 2016-02-21 23:23:30 +01:00
parent ab97b42935
commit f8fede1d8b
4 changed files with 291 additions and 127 deletions

375
imgui.cpp
View File

@ -149,6 +149,8 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details. Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions
- replaced ColorEdit4() third parameter 'bool show_alpha=true' to 'ImGuiColorEditFlags flags=0x01' where ImGuiColorEditFlags_Alpha=0x01 for dodgy compatibility
- 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
- 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
- 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
@ -4025,7 +4027,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->DC.TextWrapPosStack.resize(0); window->DC.TextWrapPosStack.resize(0);
window->DC.AllowKeyboardFocusStack.resize(0); window->DC.AllowKeyboardFocusStack.resize(0);
window->DC.ButtonRepeatStack.resize(0); window->DC.ButtonRepeatStack.resize(0);
window->DC.ColorEditMode = ImGuiColorEditMode_UserSelect;
window->DC.ColumnsCurrent = 0; window->DC.ColumnsCurrent = 0;
window->DC.ColumnsCount = 1; window->DC.ColumnsCount = 1;
window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsStartPosY = window->DC.CursorPos.y;
@ -8501,23 +8502,18 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde
return pressed; return pressed;
} }
bool ImGui::ColorEdit3(const char* label, float col[3]) bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
{ {
float col4[4]; float col4[4] = { col[0], col[1], col[2], 1.0f };
col4[0] = col[0]; if (!ColorEdit4(label, col4, flags & ~ImGuiColorEditFlags_Alpha))
col4[1] = col[1]; return false;
col4[2] = col[2]; col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
col4[3] = 1.0f; return true;
const bool value_changed = ImGui::ColorEdit4(label, col4, false);
col[0] = col4[0];
col[1] = col4[1];
col[2] = col4[2];
return value_changed;
} }
// Edit colors components (each component in 0.0f..1.0f range // Edit colors components (each component in 0.0f..1.0f range)
// Use CTRL-Click to input value and TAB to go to next item. // Click on colored square to open a color picker (unless ImGuiColorEditFlags_NoPicker is set). Use CTRL-Click to input value and TAB to go to next item.
bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -8527,123 +8523,151 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
const float w_full = CalcItemWidth(); const float w_full = CalcItemWidth();
const float square_sz = (g.FontSize + style.FramePadding.y * 2.0f); const float square_sz_with_spacing = (flags & ImGuiColorEditFlags_NoColorSquare) ? 0.0f : (g.FontSize + style.FramePadding.y * 2.0f + style.ItemInnerSpacing.x);
ImGuiColorEditMode edit_mode = window->DC.ColorEditMode; // If no mode is specified default to RGB
if (edit_mode == ImGuiColorEditMode_UserSelect || edit_mode == ImGuiColorEditMode_UserSelectShowButton) if (!(flags & ImGuiColorEditFlags_ModeMask_))
edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3; flags |= ImGuiColorEditFlags_RGB;
// Read back edit mode from persistent storage
if (!(flags & ImGuiColorEditFlags_NoOptions))
flags = (flags & (~ImGuiColorEditFlags_ModeMask_)) | (g.ColorEditModeStorage.GetInt(id, (flags & ImGuiColorEditFlags_ModeMask_)) & ImGuiColorEditFlags_ModeMask_);
IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags_ModeMask_))); // Check that exactly one of RGB/HSV/HEX is set
float f[4] = { col[0], col[1], col[2], col[3] }; float f[4] = { col[0], col[1], col[2], col[3] };
if (edit_mode == ImGuiColorEditMode_HSV) if (flags & ImGuiColorEditFlags_HSV)
ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
int i[4] = { IM_F32_TO_INT8(f[0]), IM_F32_TO_INT8(f[1]), IM_F32_TO_INT8(f[2]), IM_F32_TO_INT8(f[3]) }; int i[4] = { IM_F32_TO_INT8(f[0]), IM_F32_TO_INT8(f[1]), IM_F32_TO_INT8(f[2]), IM_F32_TO_INT8(f[3]) };
int components = alpha ? 4 : 3; bool alpha = (flags & ImGuiColorEditFlags_Alpha) != 0;
bool value_changed = false; bool value_changed = false;
int components = alpha ? 4 : 3;
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushID(label); ImGui::PushID(label);
const bool hsv = (edit_mode == 1); if (flags & (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV))
switch (edit_mode)
{ {
case ImGuiColorEditMode_RGB: // RGB/HSV 0..255 Sliders
case ImGuiColorEditMode_HSV: const float w_items_all = w_full - square_sz_with_spacing;
{ const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
// RGB/HSV 0..255 Sliders const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x);
const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x);
const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
const char* fmt_table[3][4] = const char* fmt_table[3][4] =
{
{ "%3.0f", "%3.0f", "%3.0f", "%3.0f" },
{ "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" },
{ "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" }
};
const char** fmt = hide_prefix ? fmt_table[0] : hsv ? fmt_table[2] : fmt_table[1];
ImGui::PushItemWidth(w_item_one);
for (int n = 0; n < components; n++)
{
if (n > 0)
ImGui::SameLine(0, style.ItemInnerSpacing.x);
if (n + 1 == components)
ImGui::PushItemWidth(w_item_last);
value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]);
}
ImGui::PopItemWidth();
ImGui::PopItemWidth();
}
break;
case ImGuiColorEditMode_HEX:
{ {
// RGB Hexadecimal Input { "%3.0f", "%3.0f", "%3.0f", "%3.0f" }, // Short display
const float w_slider_all = w_full - square_sz; { "R:%3.0f", "G:%3.0f", "B:%3.0f", "A:%3.0f" }, // Long display for RGBA
char buf[64]; { "H:%3.0f", "S:%3.0f", "V:%3.0f", "A:%3.0f" } // Long display for HSVV
if (alpha) };
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]); const char** fmt = hide_prefix ? fmt_table[0] : (flags & ImGuiColorEditFlags_HSV) ? fmt_table[2] : fmt_table[1];
else
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); ImGui::PushItemWidth(w_item_one);
ImGui::PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); for (int n = 0; n < components; n++)
if (ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) {
{ if (n > 0)
value_changed |= true; ImGui::SameLine(0, style.ItemInnerSpacing.x);
char* p = buf; if (n + 1 == components)
while (*p == '#' || ImCharIsSpace(*p)) ImGui::PushItemWidth(w_item_last);
p++; value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]);
i[0] = i[1] = i[2] = i[3] = 0;
if (alpha)
sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
else
sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
}
ImGui::PopItemWidth();
} }
break; ImGui::PopItemWidth();
ImGui::PopItemWidth();
} }
else if (flags & ImGuiColorEditFlags_HEX)
ImGui::SameLine(0, style.ItemInnerSpacing.x);
const ImVec4 col_display(col[0], col[1], col[2], 1.0f);
if (ImGui::ColorButton(col_display))
g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away!
// Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3]));
if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton)
{ {
ImGui::SameLine(0, style.ItemInnerSpacing.x); // RGB Hexadecimal Input
const char* button_titles[3] = { "RGB", "HSV", "HEX" }; const float w_slider_all = w_full - square_sz_with_spacing;
if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups)) char buf[64];
g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! if (alpha)
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", i[0], i[1], i[2], i[3]);
else
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]);
ImGui::PushItemWidth(w_slider_all);
if (ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
{
value_changed |= true;
char* p = buf;
while (*p == '#' || ImCharIsSpace(*p))
p++;
i[0] = i[1] = i[2] = i[3] = 0;
if (alpha)
sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
else
sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
}
ImGui::PopItemWidth();
} }
const char* label_display_end = FindTextDisplayEnd(label); const char* label_display_end = FindTextDisplayEnd(label);
bool picker_active = false;
if (!(flags & ImGuiColorEditFlags_NoColorSquare))
{
ImGui::SameLine(0, style.ItemInnerSpacing.x);
const ImVec4 col_display(col[0], col[1], col[2], 1.0f);
if (ImGui::ColorButton(col_display))
{
if (!(flags & ImGuiColorEditFlags_NoPicker))
{
ImGui::OpenPopup("picker");
ImGui::SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));
}
}
else if (!(flags & ImGuiColorEditFlags_NoOptions) && ImGui::IsItemHovered() && ImGui::IsMouseClicked(1))
{
ImGui::OpenPopup("context");
}
if (ImGui::BeginPopup("picker"))
{
picker_active = true;
if (label != label_display_end)
ImGui::TextUnformatted(label, label_display_end);
ImGui::PushItemWidth(256.0f + (alpha ? 2 : 1) * (style.ItemInnerSpacing.x));
value_changed |= ImGui::ColorPicker4("##picker", col, (flags & ImGuiColorEditFlags_Alpha) | (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_HEX));
ImGui::PopItemWidth();
ImGui::EndPopup();
}
if (!(flags & ImGuiColorEditFlags_NoOptions) && ImGui::BeginPopup("context"))
{
// FIXME-LOCALIZATION
if (ImGui::MenuItem("Edit as RGB", NULL, (flags & ImGuiColorEditFlags_RGB)?1:0)) g.ColorEditModeStorage.SetInt(id, (int)(ImGuiColorEditFlags_RGB));
if (ImGui::MenuItem("Edit as HSV", NULL, (flags & ImGuiColorEditFlags_HSV)?1:0)) g.ColorEditModeStorage.SetInt(id, (int)(ImGuiColorEditFlags_HSV));
if (ImGui::MenuItem("Edit as Hexadecimal", NULL, (flags & ImGuiColorEditFlags_HEX)?1:0)) g.ColorEditModeStorage.SetInt(id, (int)(ImGuiColorEditFlags_HEX));
ImGui::EndPopup();
}
// Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3]));
}
if (label != label_display_end) if (label != label_display_end)
{ {
ImGui::SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); ImGui::SameLine(0, style.ItemInnerSpacing.x);
ImGui::TextUnformatted(label, label_display_end); ImGui::TextUnformatted(label, label_display_end);
} }
// Convert back // Convert back
for (int n = 0; n < 4; n++) if (!picker_active)
f[n] = i[n] / 255.0f;
if (edit_mode == 1)
ImGui::ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
if (value_changed)
{ {
col[0] = f[0]; for (int n = 0; n < 4; n++)
col[1] = f[1]; f[n] = i[n] / 255.0f;
col[2] = f[2]; if (flags & ImGuiColorEditFlags_HSV)
if (alpha) ImGui::ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
col[3] = f[3]; if (value_changed)
{
col[0] = f[0];
col[1] = f[1];
col[2] = f[2];
if (alpha)
col[3] = f[3];
}
} }
ImGui::PopID(); ImGui::PopID();
@ -8652,10 +8676,147 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
return value_changed; return value_changed;
} }
void ImGui::ColorEditMode(ImGuiColorEditMode mode) bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); float col4[4] = { col[0], col[1], col[2], 1.0f };
window->DC.ColorEditMode = mode; if (!ColorPicker4(label, col4, flags & ~ImGuiColorEditFlags_Alpha))
return false;
col[0] = col4[1]; col[1] = col4[1]; col[2] = col4[2];
return true;
}
// ColorPicker v2.50 WIP
// see https://github.com/ocornut/imgui/issues/346
// TODO: Missing color square
// TODO: English strings in context menu (see FIXME-LOCALIZATION)
bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags)
{
ImGuiIO& io = ImGui::GetIO();
ImGuiStyle& style = ImGui::GetStyle();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Setup
bool alpha = (flags & ImGuiColorEditFlags_Alpha) != 0;
ImVec2 picker_pos = ImGui::GetCursorScreenPos();
float bars_width = ImGui::GetWindowFontSize() * 1.0f; // Arbitrary smallish width of Hue/Alpha picking bars
float sv_picker_size = ImMax(bars_width * 2, ImGui::CalcItemWidth() - (alpha ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
float H,S,V;
ImGui::ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);
// Color matrix logic
bool value_changed = false, hsv_changed = false;
ImGui::BeginGroup();
ImGui::InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
if (ImGui::IsItemActive())
{
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
value_changed = hsv_changed = true;
}
// Hue bar logic
ImGui::SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
ImGui::InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
if (ImGui::IsItemActive())
{
H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
value_changed = hsv_changed = true;
}
// Alpha bar logic
if (alpha)
{
ImGui::SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
ImGui::InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
if (ImGui::IsItemActive())
{
col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
value_changed = true;
}
}
const char* label_display_end = FindTextDisplayEnd(label);
if (label != label_display_end)
{
ImGui::SameLine(0, style.ItemInnerSpacing.x);
ImGui::TextUnformatted(label, label_display_end);
}
// Convert back color to RGB
if (hsv_changed)
ImGui::ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
// R,G,B and H,S,V slider color editor
if (!(flags & ImGuiColorEditFlags_NoSliders))
{
if ((flags & ImGuiColorEditFlags_ModeMask_) == 0)
flags = ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_HEX;
ImGui::PushItemWidth((alpha ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
ImGuiColorEditFlags sub_flags = (alpha ? ImGuiColorEditFlags_Alpha : 0) | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoColorSquare;
if (flags & ImGuiColorEditFlags_RGB)
value_changed |= ImGui::ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB);
if (flags & ImGuiColorEditFlags_HSV)
value_changed |= ImGui::ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_HSV);
if (flags & ImGuiColorEditFlags_HEX)
value_changed |= ImGui::ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_HEX);
ImGui::PopItemWidth();
}
// Try to cancel hue wrap (after ColorEdit), if any
if (value_changed)
{
float new_H, new_S, new_V;
ImGui::ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
if (new_H <= 0 && H > 0)
{
if (new_V <= 0 && V != new_V)
ImGui::ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
else if (new_S <= 0)
ImGui::ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
}
}
// Render hue bar
ImVec4 hue_color_f(1, 1, 1, 1);
ImGui::ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
ImU32 hue_colors[] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) };
for (int i = 0; i < 6; ++i)
{
draw_list->AddRectFilledMultiColor(
ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)),
ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)),
hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);
}
float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);
draw_list->AddLine(ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bar0_pos_x + bars_width + 1, bar0_line_y), IM_COL32_WHITE);
// Render alpha bar
if (alpha)
{
float alpha = ImSaturate(col[3]);
float bar1_line_y = (float)(int)(picker_pos.y + (1.0f-alpha) * sv_picker_size + 0.5f);
draw_list->AddRectFilledMultiColor(ImVec2(bar1_pos_x, picker_pos.y), ImVec2(bar1_pos_x + bars_width, picker_pos.y + sv_picker_size), IM_COL32_WHITE, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32_BLACK);
draw_list->AddLine(ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bar1_pos_x + bars_width + 1, bar1_line_y), IM_COL32_WHITE);
}
// Render color matrix
ImU32 hue_color32 = ImGui::ColorConvertFloat4ToU32(hue_color_f);
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
// Render cross-hair
const float CROSSHAIR_SIZE = 7.0f;
ImVec2 p((float)(int)(picker_pos.x + S * sv_picker_size + 0.5f), (float)(int)(picker_pos.y + (1 - V) * sv_picker_size + 0.5f));
draw_list->AddLine(ImVec2(p.x - CROSSHAIR_SIZE, p.y), ImVec2(p.x - 2, p.y), IM_COL32_WHITE);
draw_list->AddLine(ImVec2(p.x + CROSSHAIR_SIZE, p.y), ImVec2(p.x + 2, p.y), IM_COL32_WHITE);
draw_list->AddLine(ImVec2(p.x, p.y + CROSSHAIR_SIZE), ImVec2(p.x, p.y + 2), IM_COL32_WHITE);
draw_list->AddLine(ImVec2(p.x, p.y - CROSSHAIR_SIZE), ImVec2(p.x, p.y - 2), IM_COL32_WHITE);
ImGui::EndGroup();
return value_changed;
} }
// Horizontal separating line. // Horizontal separating line.

27
imgui.h
View File

@ -64,7 +64,7 @@ typedef int ImGuiCol; // a color identifier for styling // e
typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_
typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_ typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_
typedef int ImGuiAlign; // alignment // enum ImGuiAlign_ typedef int ImGuiAlign; // alignment // enum ImGuiAlign_
typedef int ImGuiColorEditMode; // color edit mode for ColorEdit*() // enum ImGuiColorEditMode_ typedef int ImGuiColorEditFlags; // color edit mode for ColorEdit*() // enum ImGuiColorEditFlags_
typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_ typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_
typedef int ImGuiWindowFlags; // window flags for Begin*() // enum ImGuiWindowFlags_ typedef int ImGuiWindowFlags; // window flags for Begin*() // enum ImGuiWindowFlags_
typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_
@ -256,9 +256,10 @@ namespace ImGui
IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0
IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true); IMGUI_API bool ColorButton(const ImVec4& col, bool small_height = false, bool outline_border = true);
IMGUI_API bool ColorEdit3(const char* label, float col[3]); IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); // click on colored squared to open a color picker, right-click for options
IMGUI_API bool ColorEdit4(const char* label, float col[4], bool show_alpha = true); IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0x01); // 0x01 = ImGuiColorEditFlags_Alpha = very dodgily backward compatible with 'bool show_alpha=true'
IMGUI_API void ColorEditMode(ImGuiColorEditMode mode); // FIXME-OBSOLETE: This is inconsistent with most of the API and should be obsoleted. IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0x01);
IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float));
IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));
IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float));
@ -609,14 +610,18 @@ enum ImGuiAlign_
ImGuiAlign_Default = ImGuiAlign_Left | ImGuiAlign_Top ImGuiAlign_Default = ImGuiAlign_Left | ImGuiAlign_Top
}; };
// Enumeration for ColorEditMode() // Enumeration for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4()
enum ImGuiColorEditMode_ enum ImGuiColorEditFlags_
{ {
ImGuiColorEditMode_UserSelect = -2, ImGuiColorEditFlags_Alpha = 1 << 0, // ColorEdit/ColorPicker: show/edit Alpha component. Must be 0x01 for compatibility with old API taking bool
ImGuiColorEditMode_UserSelectShowButton = -1, ImGuiColorEditFlags_RGB = 1 << 1, // ColorEdit: Choose one among RGB/HSV/HEX. User can still use the options menu to change. ColorPicker: Choose any combination or RGB/HSX/HEX.
ImGuiColorEditMode_RGB = 0, ImGuiColorEditFlags_HSV = 1 << 2,
ImGuiColorEditMode_HSV = 1, ImGuiColorEditFlags_HEX = 1 << 3,
ImGuiColorEditMode_HEX = 2 ImGuiColorEditFlags_NoPicker = 1 << 4, // ColorEdit: Disable picker when clicking on colored square
ImGuiColorEditFlags_NoOptions = 1 << 5, // ColorEdit: Disable toggling options menu when right-clicking colored square
ImGuiColorEditFlags_NoColorSquare = 1 << 6, // ColorEdit: Disable colored square
ImGuiColorEditFlags_NoSliders = 1 << 7, // ColorPicker: Disable RGB/HSV/HEX sliders
ImGuiColorEditFlags_ModeMask_ = ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_HSV|ImGuiColorEditFlags_HEX
}; };
// Enumeration for GetMouseCursor() // Enumeration for GetMouseCursor()

View File

@ -577,7 +577,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
static float col1[3] = { 1.0f,0.0f,0.2f }; static float col1[3] = { 1.0f,0.0f,0.2f };
static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
ImGui::ColorEdit3("color 1", col1); ImGui::ColorEdit3("color 1", col1);
ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
ImGui::ColorEdit4("color 2", col2); ImGui::ColorEdit4("color 2", col2);
@ -1598,12 +1598,12 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY"); ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY"); ImGui::PopItemWidth();
ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified); ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified);
static ImGuiColorEditMode edit_mode = ImGuiColorEditMode_RGB; static ImGuiColorEditFlags color_edit_flags = ImGuiColorEditFlags_RGB;
ImGui::RadioButton("RGB", &edit_mode, ImGuiColorEditMode_RGB); ImGui::RadioButton("RGB", &color_edit_flags, ImGuiColorEditFlags_RGB);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("HSV", &edit_mode, ImGuiColorEditMode_HSV); ImGui::RadioButton("HSV", &color_edit_flags, ImGuiColorEditFlags_HSV);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX); ImGui::RadioButton("HEX", &color_edit_flags, ImGuiColorEditFlags_HEX);
//ImGui::Text("Tip: Click on colored square to change edit mode."); //ImGui::Text("Tip: Click on colored square to change edit mode.");
static ImGuiTextFilter filter; static ImGuiTextFilter filter;
@ -1611,14 +1611,13 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::BeginChild("#colors", ImVec2(0, 300), true); ImGui::BeginChild("#colors", ImVec2(0, 300), true);
ImGui::PushItemWidth(-160); ImGui::PushItemWidth(-160);
ImGui::ColorEditMode(edit_mode);
for (int i = 0; i < ImGuiCol_COUNT; i++) for (int i = 0; i < ImGuiCol_COUNT; i++)
{ {
const char* name = ImGui::GetStyleColName(i); const char* name = ImGui::GetStyleColName(i);
if (!filter.PassFilter(name)) if (!filter.PassFilter(name))
continue; continue;
ImGui::PushID(i); ImGui::PushID(i);
ImGui::ColorEdit4(name, (float*)&style.Colors[i], true); ImGui::ColorEdit4(name, (float*)&style.Colors[i], color_edit_flags | ImGuiColorEditFlags_Alpha | ImGuiColorEditFlags_NoOptions);
if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0) if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0)
{ {
ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i]; ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i];

View File

@ -92,6 +92,7 @@ IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0);
IMGUI_API void* ImLoadFileToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0); IMGUI_API void* ImLoadFileToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);
IMGUI_API bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c); IMGUI_API bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c);
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
// Helpers: String // Helpers: String
@ -540,7 +541,6 @@ struct IMGUI_API ImGuiDrawContext
ImVector<bool> AllowKeyboardFocusStack; ImVector<bool> AllowKeyboardFocusStack;
ImVector<bool> ButtonRepeatStack; ImVector<bool> ButtonRepeatStack;
ImVector<ImGuiGroupData>GroupStack; ImVector<ImGuiGroupData>GroupStack;
ImGuiColorEditMode ColorEditMode;
int StackSizesBackup[6]; // Store size of various stacks for asserting int StackSizesBackup[6]; // Store size of various stacks for asserting
float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
@ -574,7 +574,6 @@ struct IMGUI_API ImGuiDrawContext
ButtonRepeat = false; ButtonRepeat = false;
AllowKeyboardFocus = true; AllowKeyboardFocus = true;
TextWrapPos = -1.0f; TextWrapPos = -1.0f;
ColorEditMode = ImGuiColorEditMode_RGB;
memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
IndentX = 0.0f; IndentX = 0.0f;