ImColor menu_colorpicker_outline_color = ImColor(33, 35, 40, 255);
ImColor menu_colorpicker_background_color = ImColor(55, 60, 69, 255);
class colorpicker
{
const char* title;
const char* tooltip;
int* var;
groupbox* group;
bool inited;
int element_index;
ImVec2 position;
ImVec2 size;
ImVec2 groupbox_position;
ImVec2 groupbox_size;
ImVec2 groupbox_rect;
ImVec2 element_picker_rect_min;
ImVec2 element_picker_rect_max;
bool opened;
bool dragging;
bool dragging_saturation;
bool dragging_alpha;
float saturation;
float alpha;
ImVec2 main_rect_min;
ImVec2 main_rect_max;
ImVec2 picker_rect_min;
ImVec2 picker_rect_max;
ImVec2 saturation_slider_rect_min;
ImVec2 saturation_slider_rect_max;
ImVec2 alpha_slider_rect_min;
ImVec2 alpha_slider_rect_max;
ImVec2 picker_size;
ImVec2 picker_text_position;
public:
bool setup(const char* titl, int* variable, groupbox* grou, const char* tip = "none")
{
ImDrawList* draw_list = ImGui::GetForegroundDrawList();
title = titl;
tooltip = tip;
var = variable;
group = grou;
inited = true;
elements_count++;
element_index = elements_count;
position = group->element_position;
size = ImVec2(225, 175);
bool is_clicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
groupbox_size = group->size;
groupbox_position = group->position;
groupbox_rect = ImVec2(groupbox_position.x + groupbox_size.x, groupbox_position.y + groupbox_size.y);
element_picker_rect_min = ImVec2(groupbox_rect.x - 9 - 24, position.y);
element_picker_rect_max = ImVec2(groupbox_rect.x - 9, position.y + 14);
ImVec2 picker_position = ImVec2(element_picker_rect_max.x - size.x + 5, element_picker_rect_max.y + 11);
main_rect_min = ImVec2(picker_position.x, picker_position.y);
main_rect_max = ImVec2(picker_position.x + size.x, picker_position.y + size.y);
picker_rect_min = ImVec2(picker_position.x + 5, picker_position.y + 5);
picker_rect_max = ImVec2(picker_rect_min.x + 165, picker_rect_min.y + 165);
saturation_slider_rect_min = ImVec2(picker_rect_max.x + 5, picker_rect_min.y);
saturation_slider_rect_max = ImVec2(picker_rect_max.x + 5 + 20, picker_rect_max.y);
alpha_slider_rect_min = ImVec2(picker_rect_max.x + 5 + 20 + 5, picker_rect_min.y);
alpha_slider_rect_max = ImVec2(picker_rect_max.x + 5 + 20 + 5 + 20, picker_rect_max.y);
picker_size = ImVec2(163, 163);
if (!inited)
{
saturation = 1.0f;
alpha = 255.0f;
}
inited = true;
bool is_hovered_main = ImGui::IsMouseHoveringRect(element_picker_rect_min, element_picker_rect_max, false);
bool is_hovered_opened = ImGui::IsMouseHoveringRect(main_rect_min, main_rect_max, false);
bool is_hovered_picker = ImGui::IsMouseHoveringRect(ImVec2(picker_rect_min.x + 1, picker_rect_min.y + 1), ImVec2(picker_rect_min.x + 1 + picker_size.x, picker_rect_min.y + 1 + picker_size.y), false);
if (active_element != -1 && active_element != element_index)
{
is_hovered_main = false;
is_hovered_opened = false;
is_hovered_picker = false;
is_clicked = false;
}
if (opened)
{
if (!dragging && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && is_hovered_picker)
dragging = true;
else if (dragging && ImGui::IsMouseDown(ImGuiMouseButton_Left))
{
for (auto i = 0; i < 360; i++)
{
float add = (picker_size.x / 360.0f);
float total_add = add * i;
ImVec2 min = ImVec2(picker_rect_min.x + 1 + total_add, picker_rect_min.y + 1);
ImVec2 max = ImVec2(picker_rect_min.x + 1 + total_add + add, picker_rect_min.y + 1 + picker_size.y);
ImVec2 extended_min = ImVec2(picker_rect_min.x + 1 + total_add, 0.0f);
ImVec2 extended_max = ImVec2(picker_rect_min.x + 1 + total_add + add, ImGui::GetIO().DisplaySize.y);
ImVec2 picker_min = ImVec2(picker_rect_min.x + 1, picker_rect_min.y + 1);
ImVec2 picker_max = ImVec2(picker_rect_min.x + 1 + picker_size.x, picker_rect_min.y + 1 + picker_size.y);
float dragging_mouse_pos = ImGui::GetMousePos().y;
bool hovering_extended = false;
if (picker_min.y > dragging_mouse_pos)
{
dragging_mouse_pos = picker_min.y;
if (ImGui::IsMouseHoveringRect(extended_min, extended_max, false))
hovering_extended = true;
}
if (picker_max.y < dragging_mouse_pos)
{
dragging_mouse_pos = picker_max.y;
if (ImGui::IsMouseHoveringRect(extended_min, extended_max, false))
hovering_extended = true;
}
int hue = i;
if (picker_min.x > ImGui::GetMousePos().x)
{
hue = 0;
hovering_extended = true;
}
if (picker_max.x < ImGui::GetMousePos().x)
{
hue = 360;
hovering_extended = true;
}
if (ImGui::IsMouseHoveringRect(min, max, false) || hovering_extended)
{
float new_hsv_value = (1.0f / picker_size.y) * (picker_rect_min.y + 1 + picker_size.y - dragging_mouse_pos);
hsv new_hsv = { hue, 1.0f - saturation, new_hsv_value };
rgb new_rgb = hsv2rgb(new_hsv);
int new_value[4] = { new_rgb.r * 255.0f, new_rgb.g * 255.0f, new_rgb.b * 255.0f };
std::memcpy(var, new_value, sizeof(int) * 4);
}
}
}
else if (dragging && !ImGui::IsMouseDown(ImGuiMouseButton_Left))
dragging = false;
}
var[3] = (255.0f - alpha);
picker_text_position = ImVec2(position.x, element_picker_rect_min.y + 6 - segoe_ui_semibold->CalcTextSizeA(element_font_size, FLT_MAX, 0.0f, title).y * 0.5f);
ImVec2 text_rect_max = ImVec2(position.x + segoe_ui_semibold->CalcTextSizeA(element_font_size, FLT_MAX, 0.0f, title).x, element_picker_rect_min.y + 5 + segoe_ui_semibold->CalcTextSizeA(element_font_size, FLT_MAX, 0.0f, title).y * 0.5f);
bool is_hovered_text = ImGui::IsMouseHoveringRect(picker_text_position, text_rect_max, false);
tooltips.push_back( { title, tooltip, is_hovered_text } );
group->element_position = ImVec2(position.x, element_picker_rect_max.y + 8);
group->element_count++;
group->previous_element = COLORPICKER;
if (is_clicked && is_hovered_main && !is_hovered_opened)
{
opened = !opened;
active_element_type = COLORPICKER;
active_element = element_index;
if (!opened)
{
active_element_type = NONE;
active_element = -1;
}
}
else if (is_clicked && !is_hovered_main && !is_hovered_opened)
{
opened = false;
if (active_element_type == COLORPICKER)
{
active_element_type = NONE;
active_element = -1;
}
}
// draw outline
draw_list->AddRectFilled(element_picker_rect_min, element_picker_rect_max, menu_colorpicker_outline_color);
// draw main rect
draw_list->AddRectFilled(ImVec2(element_picker_rect_min.x + 1, element_picker_rect_min.y + 1), ImVec2(element_picker_rect_max.x - 1, element_picker_rect_max.y - 1), ImColor(var[0], var[1], var[2], var[3]));
// draw title
draw_list->AddText(segoe_ui_semibold, element_font_size, picker_text_position, menu_second_text_color, title);
if (is_clicked && is_hovered_main)
return true;
return false;
}
void draw()
{
if (!inited)
return;
ImDrawList* draw_list = ImGui::GetForegroundDrawList();
// draw some stuff if picker opened
if (opened)
{
// draw main rect
draw_list->AddRectFilled(main_rect_min, main_rect_max, ImColor(55, 60, 69), 3.0f);
// draw picker outline
draw_list->AddRectFilled(picker_rect_min, picker_rect_max, menu_colorpicker_outline_color);
// draw sliders
// saturation slider
ImVec2 saturation_slider_min = ImVec2(saturation_slider_rect_min.x + 1, saturation_slider_rect_min.y + 1);
ImVec2 saturation_slider_max = ImVec2(saturation_slider_rect_max.x - 1, saturation_slider_rect_max.y - 1);
draw_list->AddRectFilled(saturation_slider_rect_min, saturation_slider_rect_max, menu_colorpicker_outline_color);
draw_list->AddRectFilledMultiColor(ImVec2(saturation_slider_rect_min.x + 1, saturation_slider_rect_min.y + 1), ImVec2(saturation_slider_rect_max.x - 1, saturation_slider_rect_max.y - 1), menu_colorpicker_outline_color, menu_colorpicker_outline_color, ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 255));
bool is_hovered_saturation = ImGui::IsMouseHoveringRect(saturation_slider_min, saturation_slider_max, false);
if (!dragging_saturation && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && is_hovered_saturation)
dragging_saturation = true;
else if (dragging_saturation && ImGui::IsMouseDown(ImGuiMouseButton_Left))
{
float max_value = float((float)100.0f) / (float)picker_size.y;
float new_value = std::clamp(float(float(saturation_slider_max.y - ImGui::GetIO().MousePos.y) * max_value), 0.0f, 100.0f);
saturation = float(100.0f - new_value) * 0.01f;
}
else if (dragging_saturation && !ImGui::IsMouseDown(ImGuiMouseButton_Left))
dragging_saturation = false;
float slider_value = float(picker_size.y / (float)100.0f) * (saturation * 100.0f);
ImVec2 saturation_slider_active_rect = ImVec2(saturation_slider_min.x, std::clamp(saturation_slider_min.y + slider_value, saturation_slider_min.y, saturation_slider_min.y + slider_value + (saturation > 0.5f ? -3 : 3)));
draw_list->AddRectFilled(ImVec2(saturation_slider_active_rect.x, saturation_slider_active_rect.y), ImVec2(saturation_slider_active_rect.x + 18, saturation_slider_active_rect.y + 3), menu_gradient_right_color);
// alpha slider
ImVec2 alpha_slider_min = ImVec2(alpha_slider_rect_min.x + 1, alpha_slider_rect_min.y + 1);
ImVec2 alpha_slider_max = ImVec2(alpha_slider_rect_max.x - 1, alpha_slider_rect_max.y - 1);
draw_list->AddRectFilled(alpha_slider_rect_min, alpha_slider_rect_max, menu_colorpicker_outline_color);
draw_list->AddRectFilledMultiColor(ImVec2(alpha_slider_rect_min.x + 1, alpha_slider_rect_min.y + 1), ImVec2(alpha_slider_rect_max.x - 1, alpha_slider_rect_max.y - 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 255));
bool is_hovered_alpha = ImGui::IsMouseHoveringRect(alpha_slider_min, alpha_slider_max, false);
if (!dragging_alpha && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && is_hovered_alpha)
dragging_alpha = true;
else if (dragging_alpha && ImGui::IsMouseDown(ImGuiMouseButton_Left))
{
float max_value = float((float)100.0f) / (float)picker_size.y;
float new_value = std::clamp(float(float(alpha_slider_max.y - ImGui::GetIO().MousePos.y) * max_value), 0.0f, 100.0f);
alpha = float(float(100.0f - new_value) * 0.01f) * 255.0f;
}
else if (dragging_alpha && !ImGui::IsMouseDown(ImGuiMouseButton_Left))
dragging_alpha = false;
float alpha_slider_value = float(picker_size.y / (float)100.0f) * (alpha / 255.0f * 100.0f);
ImVec2 alpha_slider_active_rect = ImVec2(alpha_slider_min.x, std::clamp(alpha_slider_min.y + alpha_slider_value, alpha_slider_min.y, alpha_slider_min.y + alpha_slider_value + (alpha > 50.0f ? -3 : 3)));
draw_list->AddRectFilled(ImVec2(alpha_slider_active_rect.x, alpha_slider_active_rect.y), ImVec2(alpha_slider_active_rect.x + 18, alpha_slider_active_rect.y + 3), menu_gradient_right_color);
// sliders end
// draw picker
for (auto i = 0; i < 360; i++)
{
hsv l = { i, 1.0f - saturation, 1.0f };
rgb s = hsv2rgb(l);
float add = (picker_size.x / 360.0f);
float total_add = add * i;
ImVec2 min = ImVec2(picker_rect_min.x + 1 + total_add, picker_rect_min.y + 1);
ImVec2 max = ImVec2(picker_rect_min.x + 1 + total_add + add, picker_rect_min.y + 1 + picker_size.y);
draw_list->AddRectFilledMultiColor(min, max, ImColor(s.r, s.g, s.b), ImColor(s.r, s.g, s.b), ImColor(0, 0, 0), ImColor(0, 0, 0));
}
}
}
};