From 221143e58a1c4183b0ebd902254428ad149c9951 Mon Sep 17 00:00:00 2001 From: Mounir Tohami <53877170+WhalesState@users.noreply.github.com> Date: Thu, 19 Dec 2024 02:48:48 +0200 Subject: [PATCH] Update ColorPicker --- scene/gui/color_mode.cpp | 96 +- scene/gui/color_mode.h | 45 +- scene/gui/color_picker.cpp | 2007 +++++++++++------------------------- scene/gui/color_picker.h | 272 ++--- 4 files changed, 769 insertions(+), 1651 deletions(-) diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp index 7d068a101e64..282ccdab32f7 100644 --- a/scene/gui/color_mode.cpp +++ b/scene/gui/color_mode.cpp @@ -28,9 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +/**************************************************************************/ +/* PIXEL ENGINE */ +/* Copyright (c) 2024-present Pixel Engine contributors (see AUTHORS.md). */ +/**************************************************************************/ +/* NOTICE: */ +/* This file contains modifications and additions specific to the Pixel */ +/* Engine project. While these changes are licensed under the MIT license */ +/* for compatibility, we request proper attribution if reused in any */ +/* derivative works, including meta-forks. */ +/**************************************************************************/ + #include "color_mode.h" #include "core/math/color.h" +#include "scene/gui/color_picker.h" #include "scene/gui/slider.h" #include "thirdparty/misc/ok_color.h" @@ -45,8 +57,7 @@ String ColorModeRGB::get_slider_label(int idx) const { float ColorModeRGB::get_slider_max(int idx) const { ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider max value."); - Color color = color_picker->get_pick_color(); - return next_power_of_2(MAX(255, color.components[idx] * 255.0)) - 1; + return slider_max[idx]; } float ColorModeRGB::get_slider_value(int idx) const { @@ -73,10 +84,9 @@ void ColorModeRGB::slider_draw(int p_which) { Color left_color; Color right_color; Color color = color_picker->get_pick_color(); - const real_t margin = 16 * color_picker->theme_cache.base_scale; if (p_which == ColorPicker::SLIDER_COUNT) { - slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true); + slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(), size), true); left_color = color; left_color.a = 0; @@ -97,10 +107,10 @@ void ColorModeRGB::slider_draw(int p_which) { col.set(1, right_color); col.set(2, right_color); col.set(3, left_color); - pos.set(0, Vector2(0, 0)); + pos.set(0, Vector2()); pos.set(1, Vector2(size.x, 0)); - pos.set(2, Vector2(size.x, margin)); - pos.set(3, Vector2(0, margin)); + pos.set(2, size); + pos.set(3, Vector2(0, size.y)); slider->draw_polygon(pos, col); } @@ -168,10 +178,9 @@ void ColorModeHSV::slider_draw(int p_which) { Color left_color; Color right_color; Color color = color_picker->get_pick_color(); - const real_t margin = 16 * color_picker->theme_cache.base_scale; if (p_which == ColorPicker::SLIDER_COUNT) { - slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true); + slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(), size), true); left_color = color; left_color.a = 0; @@ -196,16 +205,16 @@ void ColorModeHSV::slider_draw(int p_which) { col.set(1, right_color); col.set(2, right_color); col.set(3, left_color); - pos.set(0, Vector2(0, 0)); + pos.set(0, Vector2()); pos.set(1, Vector2(size.x, 0)); - pos.set(2, Vector2(size.x, margin)); - pos.set(3, Vector2(0, margin)); + pos.set(2, size); + pos.set(3, Vector2(0, size.y)); slider->draw_polygon(pos, col); if (p_which == 0) { // H Ref hue = color_picker->theme_cache.color_hue; - slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false, Color::from_hsv(0, 0, color.get_v(), color.get_s())); + slider->draw_texture_rect(hue, Rect2(Vector2(), size), false, Color::from_hsv(0, 0, color.get_v(), color.get_s())); } } @@ -243,39 +252,35 @@ void ColorModeRAW::slider_draw(int p_which) { Color left_color; Color right_color; Color color = color_picker->get_pick_color(); - const real_t margin = 16 * color_picker->theme_cache.base_scale; if (p_which == ColorPicker::SLIDER_COUNT) { - slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true); + slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(), size), true); left_color = color; left_color.a = 0; right_color = color; right_color.a = 1; - - col.set(0, left_color); - col.set(1, right_color); - col.set(2, right_color); - col.set(3, left_color); - pos.set(0, Vector2(0, 0)); - pos.set(1, Vector2(size.x, 0)); - pos.set(2, Vector2(size.x, margin)); - pos.set(3, Vector2(0, margin)); - - slider->draw_polygon(pos, col); + } else { + left_color = Color( + p_which == 0 ? 0 : color.r, + p_which == 1 ? 0 : color.g, + p_which == 2 ? 0 : color.b); + right_color = Color( + p_which == 0 ? 1 : color.r, + p_which == 1 ? 1 : color.g, + p_which == 2 ? 1 : color.b); } -} -bool ColorModeRAW::apply_theme() const { - for (int i = 0; i < 4; i++) { - HSlider *slider = color_picker->get_slider(i); - slider->remove_theme_icon_override("grabber"); - slider->remove_theme_icon_override("grabber_highlight"); - slider->remove_theme_style_override("slider"); - slider->remove_theme_constant_override("grabber_offset"); - } + col.set(0, left_color); + col.set(1, right_color); + col.set(2, right_color); + col.set(3, left_color); + pos.set(0, Vector2()); + pos.set(1, Vector2(size.x, 0)); + pos.set(2, size); + pos.set(3, Vector2(0, size.y)); - return true; + slider->draw_polygon(pos, col); } void ColorModeOKHSL::_value_changed() { @@ -334,7 +339,6 @@ Color ColorModeOKHSL::get_color() const { void ColorModeOKHSL::slider_draw(int p_which) { HSlider *slider = color_picker->get_slider(p_which); Size2 size = slider->get_size(); - const real_t margin = 16 * color_picker->theme_cache.base_scale; Vector pos; Vector col; @@ -359,18 +363,18 @@ void ColorModeOKHSL::slider_draw(int p_which) { col.set(3, right_color); col.set(4, middle_color); col.set(5, left_color); - pos.set(0, Vector2(0, 0)); + pos.set(0, Vector2()); pos.set(1, Vector2(size.x * 0.5, 0)); pos.set(2, Vector2(size.x, 0)); - pos.set(3, Vector2(size.x, margin)); - pos.set(4, Vector2(size.x * 0.5, margin)); - pos.set(5, Vector2(0, margin)); + pos.set(3, size); + pos.set(4, Vector2(size.x * 0.5, size.y)); + pos.set(5, Vector2(0, size.y)); } else { pos.resize(4); col.resize(4); if (p_which == ColorPicker::SLIDER_COUNT) { - slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true); + slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(), size), true); left_color = color; left_color.a = 0; @@ -390,17 +394,17 @@ void ColorModeOKHSL::slider_draw(int p_which) { col.set(1, right_color); col.set(2, right_color); col.set(3, left_color); - pos.set(0, Vector2(0, 0)); + pos.set(0, Vector2()); pos.set(1, Vector2(size.x, 0)); - pos.set(2, Vector2(size.x, margin)); - pos.set(3, Vector2(0, margin)); + pos.set(2, size); + pos.set(3, Vector2(0, size.y)); } slider->draw_polygon(pos, col); if (p_which == 0) { // H Ref hue = color_picker->theme_cache.color_okhsl_hue; - slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false, Color::from_hsv(0, 0, color.get_ok_hsl_l() * 2.0, color.get_ok_hsl_s())); + slider->draw_texture_rect(hue, Rect2(Vector2(), size), false, Color::from_hsv(0, 0, color.get_ok_hsl_l() * 2.0, color.get_ok_hsl_s())); return; } } diff --git a/scene/gui/color_mode.h b/scene/gui/color_mode.h index b762097dc30b..7329d8e377e8 100644 --- a/scene/gui/color_mode.h +++ b/scene/gui/color_mode.h @@ -28,10 +28,24 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +/**************************************************************************/ +/* PIXEL ENGINE */ +/* Copyright (c) 2024-present Pixel Engine contributors (see AUTHORS.md). */ +/**************************************************************************/ +/* NOTICE: */ +/* This file contains modifications and additions specific to the Pixel */ +/* Engine project. While these changes are licensed under the MIT license */ +/* for compatibility, we request proper attribution if reused in any */ +/* derivative works, including meta-forks. */ +/**************************************************************************/ + #ifndef COLOR_MODE_H #define COLOR_MODE_H -#include "scene/gui/color_picker.h" +#include "core/string/ustring.h" + +struct Color; +class ColorPicker; class ColorMode { public: @@ -44,18 +58,17 @@ class ColorMode { virtual float get_spinbox_arrow_step() const { return get_slider_step(); } virtual String get_slider_label(int idx) const = 0; virtual float get_slider_max(int idx) const = 0; + virtual bool can_allow_greater() const { return false; } virtual float get_slider_value(int idx) const = 0; virtual Color get_color() const = 0; - virtual void _value_changed() {} + virtual void _value_changed() {}; virtual void slider_draw(int p_which) = 0; - virtual bool apply_theme() const { return false; } - virtual ColorPicker::PickerShapeType get_shape_override() const { return ColorPicker::SHAPE_MAX; } ColorMode(ColorPicker *p_color_picker); - virtual ~ColorMode() {} + virtual ~ColorMode() {}; }; class ColorModeHSV : public ColorMode { @@ -79,18 +92,20 @@ class ColorModeHSV : public ColorMode { virtual void slider_draw(int p_which) override; ColorModeHSV(ColorPicker *p_color_picker) : - ColorMode(p_color_picker) {} + ColorMode(p_color_picker) {}; }; class ColorModeRGB : public ColorMode { public: String labels[3] = { "R", "G", "B" }; + float slider_max[4] = { 255, 255, 255, 255 }; virtual String get_name() const override { return "RGB"; } virtual float get_slider_step() const override { return 1; } virtual String get_slider_label(int idx) const override; virtual float get_slider_max(int idx) const override; + virtual bool can_allow_greater() const override { return true; } virtual float get_slider_value(int idx) const override; virtual Color get_color() const override; @@ -98,29 +113,28 @@ class ColorModeRGB : public ColorMode { virtual void slider_draw(int p_which) override; ColorModeRGB(ColorPicker *p_color_picker) : - ColorMode(p_color_picker) {} + ColorMode(p_color_picker) {}; }; class ColorModeRAW : public ColorMode { public: String labels[3] = { "R", "G", "B" }; - float slider_max[4] = { 100, 100, 100, 1 }; + float slider_max[4] = { 1, 1, 1, 1 }; virtual String get_name() const override { return "RAW"; } - virtual float get_slider_step() const override { return 0.001; } - virtual float get_spinbox_arrow_step() const override { return 0.01; } + virtual float get_slider_step() const override { return 1.0 / 255.0; } virtual String get_slider_label(int idx) const override; virtual float get_slider_max(int idx) const override; + virtual bool can_allow_greater() const override { return true; } virtual float get_slider_value(int idx) const override; virtual Color get_color() const override; virtual void slider_draw(int p_which) override; - virtual bool apply_theme() const override; ColorModeRAW(ColorPicker *p_color_picker) : - ColorMode(p_color_picker) {} + ColorMode(p_color_picker) {}; }; class ColorModeOKHSL : public ColorMode { @@ -130,7 +144,7 @@ class ColorModeOKHSL : public ColorMode { float cached_hue = 0.0; float cached_saturation = 0.0; - virtual String get_name() const override { return "OKHSL"; } + virtual String get_name() const override { return "HSL"; } virtual float get_slider_step() const override { return 1.0; } virtual String get_slider_label(int idx) const override; @@ -142,12 +156,11 @@ class ColorModeOKHSL : public ColorMode { virtual void _value_changed() override; virtual void slider_draw(int p_which) override; - virtual ColorPicker::PickerShapeType get_shape_override() const override { return ColorPicker::SHAPE_OKHSL_CIRCLE; } ColorModeOKHSL(ColorPicker *p_color_picker) : - ColorMode(p_color_picker) {} + ColorMode(p_color_picker) {}; - ~ColorModeOKHSL() {} + ~ColorModeOKHSL() {}; }; #endif // COLOR_MODE_H diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index eb4cdeb02650..a33af593b450 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -28,30 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +/**************************************************************************/ +/* PIXEL ENGINE */ +/* Copyright (c) 2024-present Pixel Engine contributors (see AUTHORS.md). */ +/**************************************************************************/ +/* NOTICE: */ +/* This file contains modifications and additions specific to the Pixel */ +/* Engine project. While these changes are licensed under the MIT license */ +/* for compatibility, we request proper attribution if reused in any */ +/* derivative works, including meta-forks. */ +/**************************************************************************/ + #include "color_picker.h" -#include "core/io/image.h" #include "scene/gui/aspect_ratio_container.h" +#include "scene/gui/button.h" #include "scene/gui/color_mode.h" -#include "scene/gui/file_dialog.h" +#include "scene/gui/foldable_container.h" #include "scene/gui/grid_container.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/margin_container.h" #include "scene/gui/menu_button.h" -#include "scene/gui/panel.h" +#include "scene/gui/panel_container.h" #include "scene/gui/popup_menu.h" +#include "scene/gui/scroll_container.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" -#include "scene/resources/atlas_texture.h" -#include "scene/resources/color_palette.h" #include "scene/resources/image_texture.h" #include "scene/resources/style_box_flat.h" #include "scene/resources/style_box_texture.h" #include "scene/theme/theme_db.h" +#include "servers/display_server.h" +#include "thirdparty/misc/ok_color.h" #include "thirdparty/misc/ok_color_shader.h" +PackedColorArray ColorPicker::swatches; + void ColorPicker::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -62,61 +76,31 @@ void ColorPicker::_notification(int p_what) { // FIXME: The embedding check is needed to fix a bug in single-window mode (GH-93718). if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SCREEN_CAPTURE) && !get_tree()->get_root()->is_embedding_subwindows()) { btn_pick->set_tooltip_text(ETR("Pick a color from the screen.")); - btn_pick->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_pick_button_pressed)); } else { // On unsupported platforms, use a legacy method for color picking. + is_legacy_picking = true; btn_pick->set_tooltip_text(ETR("Pick a color from the application window.")); - btn_pick->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_pick_button_pressed_legacy)); - } - } break; - - case NOTIFICATION_TRANSLATION_CHANGED: { - List buttons; - preset_group->get_buttons(&buttons); - for (List::Element *E = buttons.front(); E; E = E->next()) { - Color preset_color = ((ColorPresetButton *)E->get())->get_preset_color(); - E->get()->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color\nRMB: Remove preset")), preset_color.to_html(preset_color.a < 1))); - } - - buttons.clear(); - recent_preset_group->get_buttons(&buttons); - for (List::Element *E = buttons.front(); E; E = E->next()) { - Color preset_color = ((ColorPresetButton *)E->get())->get_preset_color(); - E->get()->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color")), preset_color.to_html(preset_color.a < 1))); } + btn_pick->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_pick_button_pressed)); } break; case NOTIFICATION_THEME_CHANGED: { btn_pick->set_button_icon(theme_cache.screen_picker); - _update_drop_down_arrow(btn_preset->is_pressed(), btn_preset); - _update_drop_down_arrow(btn_recent_preset->is_pressed(), btn_recent_preset); - btn_add_preset->set_button_icon(theme_cache.add_preset); - menu_btn->set_button_icon(theme_cache.menu_option); - - btn_pick->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); - btn_shape->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); - btn_mode->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); + // swatcher_foldable_container->set_button_icon(0, theme_cache.add_preset); uv_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height)); w_edit->set_custom_minimum_size(Size2(theme_cache.h_width, 0)); + sample->set_custom_minimum_size(Size2(64, theme_cache.sample_height)); wheel_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height)); - wheel_margin->add_theme_constant_override("margin_bottom", 8 * theme_cache.base_scale); + float char_size = get_theme_font(SceneStringName(font), SNAME("Label"))->get_char_size('W', get_theme_font_size(SceneStringName(font_size), SNAME("Label"))).width; for (int i = 0; i < SLIDER_COUNT; i++) { - labels[i]->set_custom_minimum_size(Size2(theme_cache.label_width, 0)); - sliders[i]->add_theme_constant_override(SNAME("center_grabber"), theme_cache.center_slider_grabbers); - } - alpha_label->set_custom_minimum_size(Size2(theme_cache.label_width, 0)); - alpha_slider->add_theme_constant_override(SNAME("center_grabber"), theme_cache.center_slider_grabbers); - - for (int i = 0; i < MODE_BUTTON_COUNT; i++) { - mode_btns[i]->begin_bulk_theme_override(); - mode_btns[i]->add_theme_style_override(SceneStringName(pressed), theme_cache.mode_button_pressed); - mode_btns[i]->add_theme_style_override(CoreStringName(normal), theme_cache.mode_button_normal); - mode_btns[i]->add_theme_style_override(SceneStringName(hover), theme_cache.mode_button_hover); - mode_btns[i]->end_bulk_theme_override(); + labels[i]->set_custom_minimum_size(Size2(char_size, 0)); + sliders[i]->queue_redraw(); } + alpha_label->set_custom_minimum_size(Size2(char_size, 0)); + alpha_slider->queue_redraw(); shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_RECTANGLE), theme_cache.shape_rect); shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_WHEEL), theme_cache.shape_rect_wheel); @@ -127,22 +111,21 @@ void ColorPicker::_notification(int p_what) { btn_shape->set_button_icon(shape_popup->get_item_icon(current_shape)); } - internal_margin->begin_bulk_theme_override(); - internal_margin->add_theme_constant_override(SNAME("margin_bottom"), theme_cache.content_margin); - internal_margin->add_theme_constant_override(SNAME("margin_left"), theme_cache.content_margin); - internal_margin->add_theme_constant_override(SNAME("margin_right"), theme_cache.content_margin); - internal_margin->add_theme_constant_override(SNAME("margin_top"), theme_cache.content_margin); - internal_margin->end_bulk_theme_override(); + if (text_is_constructor) { + text_type->set_button_icon(theme_cache.hex_code_icon); + } else { + text_type->set_button_icon(theme_cache.hex_icon); + } - _reset_sliders_theme(); + Control::SizeFlags hb_size_flag = theme_cache.expand_shape > 0 ? SIZE_EXPAND_FILL : SIZE_FILL; + hb_edit->set_v_size_flags(hb_size_flag); - if (Engine::get_singleton()->is_editor_hint()) { - // Adjust for the width of the "Script" icon. - text_type->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); + swatches_foldable->set_button_icon(0, theme_cache.add_preset); + + for (int i = 0; i < swatches_hbc->get_child_count(); i++) { + Object::cast_to(swatches_hbc->get_child(i))->set_custom_minimum_size(Size2(theme_cache.swatch_size, theme_cache.swatch_size)); } - _update_presets(); - _update_recent_presets(); _update_controls(); } break; @@ -153,32 +136,33 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (!is_picking_color) { - return; + if (is_legacy_picking) { + Ref img = picker_texture_rect->get_texture()->get_image(); + if (img.is_valid() && !img->is_empty()) { + Point2 mpos = get_tree()->get_root()->get_mouse_position(); + if (mpos.x < 0 || mpos.x >= img->get_size().width || mpos.y < 0 || mpos.y >= img->get_size().height) { + return; + } + set_pick_color(img->get_pixelv(mpos)); + } + } else { + if (Rect2(hb_edit->get_position(), hb_edit->get_size()).has_point(get_local_mouse_position())) { + return; + } + set_pick_color(DisplayServer::get_singleton()->screen_get_pixel(DisplayServer::get_singleton()->mouse_get_position())); } - DisplayServer *ds = DisplayServer::get_singleton(); - Vector2 ofs = ds->mouse_get_position(); - picker_window->set_position(ofs - Vector2(28, 28)); - - Color c = DisplayServer::get_singleton()->screen_get_pixel(DisplayServer::get_singleton()->mouse_get_position()); - - picker_preview_style_box_color->set_bg_color(c); - picker_preview_style_box->set_bg_color(c.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); - - Ref zoom_preview_img = ds->screen_get_image_rect(Rect2i(ofs.x - 8, ofs.y - 8, 17, 17)); - picker_texture_zoom->set_texture(ImageTexture::create_from_image(zoom_preview_img)); - - set_pick_color(c); - } + } break; } } void ColorPicker::_update_theme_item_cache() { VBoxContainer::_update_theme_item_cache(); - - theme_cache.base_scale = get_theme_default_base_scale(); } +Ref ColorPicker::wheel_shader; +Ref ColorPicker::circle_shader; +Ref ColorPicker::circle_ok_color_shader; + void ColorPicker::init_shaders() { wheel_shader.instantiate(); wheel_shader->set_code(R"( @@ -186,19 +170,21 @@ void ColorPicker::init_shaders() { shader_type canvas_item; +uniform float wheel_radius = 0.4; + void fragment() { float x = UV.x - 0.5; float y = UV.y - 0.5; float a = atan(y, x); x += 0.001; y += 0.001; - float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42); + float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > wheel_radius); x -= 0.002; - float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42); + float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > wheel_radius); y -= 0.002; - float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42); + float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > wheel_radius); x += 0.002; - float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42); + float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > wheel_radius); COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00); } @@ -233,14 +219,14 @@ void fragment() { circle_ok_color_shader->set_code(OK_COLOR_SHADER + R"( // ColorPicker ok color hsv circle shader. -uniform float ok_hsl_l = 1.0; +uniform float v = 1.0; void fragment() { float x = UV.x - 0.5; float y = UV.y - 0.5; float h = atan(y, x) / (2.0 * M_PI); float s = sqrt(x * x + y * y) * 2.0; - vec3 col = okhsl_to_srgb(vec3(h, s, ok_hsl_l)); + vec3 col = okhsl_to_srgb(vec3(h, s, v)); x += 0.001; y += 0.001; float b = float(sqrt(x * x + y * y) < 0.5); @@ -282,64 +268,31 @@ void ColorPicker::_update_controls() { for (int i = 0; i < current_slider_count; i++) { labels[i]->set_text(modes[current_mode]->get_slider_label(i)); } - alpha_label->set_text("A"); - - slider_theme_modified = modes[current_mode]->apply_theme(); - if (edit_alpha) { - alpha_value->show(); - alpha_slider->show(); - alpha_label->show(); - } else { - alpha_value->hide(); - alpha_slider->hide(); - alpha_label->hide(); - } - - switch (_get_actual_shape()) { - case SHAPE_HSV_RECTANGLE: - wheel_edit->hide(); - w_edit->show(); - uv_edit->show(); - btn_shape->show(); - break; - case SHAPE_HSV_WHEEL: - wheel_edit->show(); - w_edit->hide(); - uv_edit->hide(); - btn_shape->show(); - wheel->set_material(wheel_mat); - break; - case SHAPE_VHS_CIRCLE: - wheel_edit->show(); - w_edit->show(); - uv_edit->hide(); - btn_shape->show(); - wheel->set_material(circle_mat); - circle_mat->set_shader(circle_shader); - break; - case SHAPE_OKHSL_CIRCLE: - wheel_edit->show(); - w_edit->show(); - uv_edit->hide(); - btn_shape->show(); - wheel->set_material(circle_mat); - circle_mat->set_shader(circle_ok_color_shader); - break; - case SHAPE_NONE: - wheel_edit->hide(); - w_edit->hide(); - uv_edit->hide(); - btn_shape->hide(); - break; - default: { + alpha_value->set_visible(edit_alpha); + alpha_slider->set_visible(edit_alpha); + alpha_label->set_visible(edit_alpha); + + bool has_shape = current_shape != SHAPE_NONE; + hb_edit->set_visible(has_shape); + btn_shape->set_visible(has_shape); + if (has_shape) { + bool is_hsv_rect = current_shape == SHAPE_HSV_RECTANGLE; + bool is_hsv_wheel = current_shape == SHAPE_HSV_WHEEL; + wheel_edit->set_visible(!is_hsv_rect); + w_edit->set_visible(!is_hsv_wheel); + uv_edit->set_visible(is_hsv_rect); + if (!is_hsv_rect) { + wheel->set_material(is_hsv_wheel ? wheel_mat : circle_mat); + if (!is_hsv_wheel) { + circle_mat->set_shader(current_shape == SHAPE_VHS_CIRCLE ? circle_shader : circle_ok_color_shader); + } } } } void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) { if (text_changed) { - add_recent_preset(color); text_changed = false; } @@ -354,6 +307,7 @@ void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) { } _update_color(p_update_sliders); + _update_selected_swatch(); } void ColorPicker::set_pick_color(const Color &p_color) { @@ -403,21 +357,10 @@ void ColorPicker::_slider_value_changed() { color = modes[current_mode]->get_color(); modes[current_mode]->_value_changed(); - if (current_mode == MODE_HSV) { + if (current_mode == MODE_HSV || current_mode == MODE_OKHSL) { h = sliders[0]->get_value() / 360.0; s = sliders[1]->get_value() / 100.0; v = sliders[2]->get_value() / 100.0; - ok_hsl_h = color.get_ok_hsl_h(); - ok_hsl_s = color.get_ok_hsl_s(); - ok_hsl_l = color.get_ok_hsl_l(); - last_color = color; - } else if (current_mode == MODE_OKHSL) { - ok_hsl_h = sliders[0]->get_value() / 360.0; - ok_hsl_s = sliders[1]->get_value() / 100.0; - ok_hsl_l = sliders[2]->get_value() / 100.0; - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); last_color = color; } @@ -438,91 +381,6 @@ void ColorPicker::add_mode(ColorMode *p_mode) { modes.push_back(p_mode); } -void ColorPicker::create_slider(GridContainer *gc, int idx) { - Label *lbl = memnew(Label); - lbl->set_v_size_flags(SIZE_SHRINK_CENTER); - lbl->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - gc->add_child(lbl); - - HSlider *slider = memnew(HSlider); - slider->set_v_size_flags(SIZE_SHRINK_CENTER); - slider->set_focus_mode(FOCUS_NONE); - gc->add_child(slider); - - SpinBox *val = memnew(SpinBox); - slider->share(val); - val->set_select_all_on_focus(true); - gc->add_child(val); - - LineEdit *vle = val->get_line_edit(); - vle->connect(SceneStringName(text_changed), callable_mp(this, &ColorPicker::_text_changed)); - vle->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_line_edit_input)); - vle->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); - - val->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input)); - - slider->set_h_size_flags(SIZE_EXPAND_FILL); - - slider->connect("drag_started", callable_mp(this, &ColorPicker::_slider_drag_started)); - slider->connect(SceneStringName(value_changed), callable_mp(this, &ColorPicker::_slider_value_changed).unbind(1)); - slider->connect("drag_ended", callable_mp(this, &ColorPicker::_slider_drag_ended).unbind(1)); - slider->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_slider_draw).bind(idx)); - slider->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input)); - - if (idx < SLIDER_COUNT) { - sliders[idx] = slider; - values[idx] = val; - labels[idx] = lbl; - } else { - alpha_slider = slider; - alpha_value = val; - alpha_label = lbl; - } -} - -#ifdef TOOLS_ENABLED -void ColorPicker::set_editor_settings(Object *p_editor_settings) { - if (editor_settings) { - return; - } - editor_settings = p_editor_settings; - - if (preset_cache.is_empty()) { - PackedColorArray saved_presets = editor_settings->call(SNAME("get_project_metadata"), "color_picker", "presets", PackedColorArray()); - for (int i = 0; i < saved_presets.size(); i++) { - preset_cache.push_back(saved_presets[i]); - } - } - - for (const Color &preset : preset_cache) { - presets.push_back(preset); - } - - if (recent_preset_cache.is_empty()) { - PackedColorArray saved_recent_presets = editor_settings->call(SNAME("get_project_metadata"), "color_picker", "recent_presets", PackedColorArray()); - for (int i = 0; i < saved_recent_presets.size(); i++) { - recent_preset_cache.push_back(saved_recent_presets[i]); - } - } - - for (const Color &preset : recent_preset_cache) { - recent_presets.push_back(preset); - } - - _update_presets(); - _update_recent_presets(); -} - -void ColorPicker::set_quick_open_callback(const Callable &p_file_selected) { - quick_open_callback = p_file_selected; -} - -void ColorPicker::set_palette_saved_callback(const Callable &p_palette_saved) { - palette_saved_callback = p_palette_saved; -} - -#endif - HSlider *ColorPicker::get_slider(int p_idx) { if (p_idx < SLIDER_COUNT) { return sliders[p_idx]; @@ -540,77 +398,25 @@ Vector ColorPicker::get_active_slider_values() { } void ColorPicker::_copy_color_to_hsv() { - ok_hsl_h = color.get_ok_hsl_h(); - ok_hsl_s = color.get_ok_hsl_s(); - ok_hsl_l = color.get_ok_hsl_l(); - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); + if (current_shape == SHAPE_OKHSL_CIRCLE) { + h = color.get_ok_hsl_h(); + s = color.get_ok_hsl_s(); + v = color.get_ok_hsl_l(); + } else { + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); + } } void ColorPicker::_copy_hsv_to_color() { - if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(ok_hsl_h, ok_hsl_s, ok_hsl_l, color.a); + if (current_shape == SHAPE_OKHSL_CIRCLE) { + color.set_ok_hsl(h, s, v, color.a); } else { color.set_hsv(h, s, v, color.a); } } -void ColorPicker::_select_from_preset_container(const Color &p_color) { - if (preset_group->get_pressed_button()) { - preset_group->get_pressed_button()->set_pressed(false); - } - - for (int i = 1; i < preset_container->get_child_count(); i++) { - ColorPresetButton *current_btn = Object::cast_to(preset_container->get_child(i)); - if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->set_pressed(true); - break; - } - } -} - -bool ColorPicker::_select_from_recent_preset_hbc(const Color &p_color) { - for (int i = 0; i < recent_preset_hbc->get_child_count(); i++) { - ColorPresetButton *current_btn = Object::cast_to(recent_preset_hbc->get_child(i)); - if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->set_pressed(true); - return true; - } - } - return false; -} - -ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const { - return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape; -} - -void ColorPicker::_reset_sliders_theme() { - Ref style_box_flat(memnew(StyleBoxFlat)); - style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale); - style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp()); - - for (int i = 0; i < SLIDER_COUNT; i++) { - sliders[i]->begin_bulk_theme_override(); - sliders[i]->add_theme_icon_override("grabber", theme_cache.bar_arrow); - sliders[i]->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow); - sliders[i]->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale); - if (!colorize_sliders) { - sliders[i]->add_theme_style_override("slider", style_box_flat); - } - sliders[i]->end_bulk_theme_override(); - } - - alpha_slider->begin_bulk_theme_override(); - alpha_slider->add_theme_icon_override("grabber", theme_cache.bar_arrow); - alpha_slider->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow); - alpha_slider->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale); - if (!colorize_sliders) { - alpha_slider->add_theme_style_override("slider", style_box_flat); - } - alpha_slider->end_bulk_theme_override(); -} - void ColorPicker::_html_submitted(const String &p_html) { if (updating || text_is_constructor || !c_text->is_visible()) { return; @@ -661,6 +467,7 @@ void ColorPicker::_update_color(bool p_update_sliders) { float spinbox_arrow_step = modes[current_mode]->get_spinbox_arrow_step(); for (int i = 0; i < current_slider_count; i++) { sliders[i]->set_max(modes[current_mode]->get_slider_max(i)); + sliders[i]->set_allow_greater(modes[current_mode]->can_allow_greater()); sliders[i]->set_step(step); values[i]->set_custom_arrow_step(spinbox_arrow_step); sliders[i]->set_value(modes[current_mode]->get_slider_value(i)); @@ -684,86 +491,15 @@ void ColorPicker::_update_color(bool p_update_sliders) { updating = false; } -void ColorPicker::_update_presets() { - int preset_size = _get_preset_size(); - // Only update the preset button size if it has changed. - if (preset_size != prev_preset_size) { - prev_preset_size = preset_size; - btn_add_preset->set_custom_minimum_size(Size2(preset_size, preset_size)); - for (int i = 1; i < preset_container->get_child_count(); i++) { - ColorPresetButton *cpb = Object::cast_to(preset_container->get_child(i)); - cpb->set_custom_minimum_size(Size2(preset_size, preset_size)); - } - } - -#ifdef TOOLS_ENABLED - if (editor_settings) { - String cached_name = editor_settings->call(SNAME("get_project_metadata"), "color_picker", "palette_name", String()); - palette_path = editor_settings->call(SNAME("get_project_metadata"), "color_picker", "palette_path", String()); - bool palette_edited = editor_settings->call(SNAME("get_project_metadata"), "color_picker", "palette_edited", false); - if (!cached_name.is_empty()) { - palette_name->set_text(cached_name); - if (btn_preset->is_pressed() && !presets.is_empty()) { - palette_name->show(); - } - - if (palette_edited) { - palette_name->set_text(vformat("%s*", palette_name->get_text().replace("*", ""))); - palette_name->set_tooltip_text(ETR("The changes to this palette have not been saved to a file.")); - } - } - } -#endif - - // Rebuild swatch color buttons, keeping the add-preset button in the first position. - for (int i = 1; i < preset_container->get_child_count(); i++) { - preset_container->get_child(i)->queue_free(); - } - - presets = preset_cache; - for (const Color &preset : preset_cache) { - _add_preset_button(preset_size, preset); - } - - _notification(NOTIFICATION_VISIBILITY_CHANGED); -} - -void ColorPicker::_update_recent_presets() { -#ifdef TOOLS_ENABLED - if (editor_settings) { - int recent_preset_count = recent_preset_hbc->get_child_count(); - for (int i = 0; i < recent_preset_count; i++) { - memdelete(recent_preset_hbc->get_child(0)); - } - - recent_presets.clear(); - for (const Color &preset : recent_preset_cache) { - recent_presets.push_back(preset); - } - - int preset_size = _get_preset_size(); - for (const Color &preset : recent_presets) { - _add_recent_preset_button(preset_size, preset); - } - - _notification(NOTIFICATION_VISIBILITY_CHANGED); - } -#endif -} - void ColorPicker::_text_type_toggled() { text_is_constructor = !text_is_constructor; if (text_is_constructor) { - text_type->set_text(""); -#ifdef TOOLS_ENABLED - text_type->set_button_icon(get_editor_theme_icon(SNAME("Script"))); -#endif + text_type->set_button_icon(theme_cache.hex_code_icon); c_text->set_editable(false); c_text->set_tooltip_text(RTR("Copy this constructor in a script.")); } else { - text_type->set_text("#"); - text_type->set_button_icon(nullptr); + text_type->set_button_icon(theme_cache.hex_icon); c_text->set_editable(true); c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\").")); @@ -794,12 +530,6 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) { current_shape = p_shape; -#ifdef TOOLS_ENABLED - if (editor_settings) { - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "picker_shape", current_shape); - } -#endif - _copy_color_to_hsv(); _update_controls(); @@ -810,333 +540,22 @@ ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const { return current_shape; } -inline int ColorPicker::_get_preset_size() { - return (int(get_minimum_size().width) - (preset_container->get_h_separation() * (PRESET_COLUMN_COUNT - 1))) / PRESET_COLUMN_COUNT; -} - -void ColorPicker::_add_preset_button(int p_size, const Color &p_color) { - ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size)); - btn_preset_new->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color\nRMB: Remove preset")), p_color.to_html(p_color.a < 1))); - SET_DRAG_FORWARDING_GCDU(btn_preset_new, ColorPicker); - btn_preset_new->set_button_group(preset_group); - preset_container->add_child(btn_preset_new); - btn_preset_new->set_pressed(true); - btn_preset_new->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_preset_input).bind(p_color)); -} - -void ColorPicker::_add_recent_preset_button(int p_size, const Color &p_color) { - ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size)); - btn_preset_new->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color")), p_color.to_html(p_color.a < 1))); - btn_preset_new->set_button_group(recent_preset_group); - recent_preset_hbc->add_child(btn_preset_new); - recent_preset_hbc->move_child(btn_preset_new, 0); - btn_preset_new->set_pressed(true); - btn_preset_new->connect(SceneStringName(toggled), callable_mp(this, &ColorPicker::_recent_preset_pressed).bind(btn_preset_new)); -} - -void ColorPicker::_load_palette() { - List extensions; - ResourceLoader::get_recognized_extensions_for_type("ColorPalette", &extensions); - - file_dialog->set_title(RTR("Load Color Palette")); - file_dialog->clear_filters(); - for (const String &K : extensions) { - file_dialog->add_filter("*." + K); - } - - file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); - file_dialog->set_current_file(""); - file_dialog->popup_centered_ratio(); -} - -void ColorPicker::_save_palette(bool p_is_save_as) { - if (!p_is_save_as && !palette_path.is_empty()) { - file_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE); - _palette_file_selected(palette_path); - return; - } else { - List extensions; - ResourceLoader::get_recognized_extensions_for_type("ColorPalette", &extensions); - - file_dialog->set_title(RTR("Save Color Palette")); - file_dialog->clear_filters(); - for (const String &K : extensions) { - file_dialog->add_filter("*." + K); - } - - file_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE); - file_dialog->set_current_file("new_palette.tres"); - file_dialog->popup_centered_ratio(); - } -} - -void ColorPicker::_quick_open_palette_file_selected(const String &p_path) { - if (!file_dialog) { - file_dialog = memnew(FileDialog); - add_child(file_dialog, false, INTERNAL_MODE_FRONT); - file_dialog->force_parent_owned(); - file_dialog->connect("file_selected", callable_mp(this, &ColorPicker::_palette_file_selected)); - file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); - file_dialog->set_current_dir(Engine::get_singleton()->is_editor_hint() ? "res://" : "user://"); - } - file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); - _palette_file_selected(p_path); -} - -void ColorPicker::_palette_file_selected(const String &p_path) { - switch (file_dialog->get_file_mode()) { - case FileDialog::FileMode::FILE_MODE_OPEN_FILE: { - Ref palette = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); - ERR_FAIL_COND_MSG(palette.is_null(), vformat("Cannot open color palette file for reading at: %s", p_path)); - preset_cache.clear(); - presets.clear(); - - PackedColorArray saved_presets = palette->get_colors(); - for (const Color &saved_preset : saved_presets) { - preset_cache.push_back(saved_preset); - presets.push_back(saved_preset); - } - -#ifdef TOOLS_ENABLED - if (editor_settings) { - const StringName set_project_metadata = SNAME("set_project_metadata"); - editor_settings->call(set_project_metadata, "color_picker", "presets", saved_presets); - editor_settings->call(set_project_metadata, "color_picker", "palette_edited", false); - } -#endif - } break; - case FileDialog::FileMode::FILE_MODE_SAVE_FILE: { - ColorPalette *palette = memnew(ColorPalette); - palette->set_colors(get_presets()); - Error error = ResourceSaver::save(palette, p_path); - ERR_FAIL_COND_MSG(error != Error::OK, vformat("Cannot open color palette file for writing at: %s", p_path)); -#ifdef TOOLS_ENABLED - if (palette_saved_callback.is_valid()) { - palette_saved_callback.call_deferred(p_path); - } -#endif // TOOLS_ENABLED - } break; - default: - break; - } - - palette_name->set_text(p_path.get_file().get_basename()); - palette_name->set_tooltip_text(""); - palette_name->show(); - palette_path = p_path; - btn_preset->set_pressed(true); -#ifdef TOOLS_ENABLED - if (editor_settings) { - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_name", palette_name->get_text()); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_path", palette_path); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_edited", false); - } -#endif - _update_presets(); -} - -void ColorPicker::_show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_preset, Container *p_preset_container) { - if (p_is_btn_pressed) { - p_preset_container->show(); - } else { - p_preset_container->hide(); - } - _update_drop_down_arrow(p_is_btn_pressed, p_btn_preset); - - palette_name->hide(); - if (btn_preset->is_pressed() && !palette_name->get_text().is_empty()) { - palette_name->show(); - } -} - -void ColorPicker::_update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset) { - if (p_is_btn_pressed) { - p_btn_preset->set_button_icon(theme_cache.expanded_arrow); - } else { - p_btn_preset->set_button_icon(theme_cache.folded_arrow); - } -} - -void ColorPicker::_set_mode_popup_value(ColorModeType p_mode) { - ERR_FAIL_INDEX(p_mode, MODE_MAX + 1); - - if (p_mode == MODE_MAX) { - set_colorize_sliders(!colorize_sliders); - } else { - set_color_mode(p_mode); - } -} - -Variant ColorPicker::_get_drag_data_fw(const Point2 &p_point, Control *p_from_control) { - ColorPresetButton *dragged_preset_button = Object::cast_to(p_from_control); - - if (!dragged_preset_button) { - return Variant(); - } - - ColorPresetButton *drag_preview = memnew(ColorPresetButton(dragged_preset_button->get_preset_color(), _get_preset_size())); - set_drag_preview(drag_preview); - - Dictionary drag_data; - drag_data["type"] = "color_preset"; - drag_data["color_preset"] = dragged_preset_button->get_index(); - - return drag_data; -} - -bool ColorPicker::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const { - Dictionary d = p_data; - if (!d.has("type") || String(d["type"]) != "color_preset") { - return false; - } - return true; -} - -void ColorPicker::_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) { - Dictionary d = p_data; - if (!d.has("type")) { +void ColorPicker::set_wheel_radius(float p_wheel_radius) { + if (wheel_radius == p_wheel_radius) { return; } - if (String(d["type"]) == "color_preset") { - int preset_from_id = d["color_preset"]; - int hover_now = p_from_control->get_index(); - - if (preset_from_id == hover_now || hover_now == -1) { - return; - } - preset_container->move_child(preset_container->get_child(preset_from_id), hover_now); - } -} - -void ColorPicker::add_preset(const Color &p_color) { - List::Element *e = presets.find(p_color); - if (e) { - presets.move_to_back(e); - preset_cache.move_to_back(preset_cache.find(p_color)); - - preset_container->move_child(preset_group->get_pressed_button(), preset_container->get_child_count() - 1); - } else { - presets.push_back(p_color); - preset_cache.push_back(p_color); - - _add_preset_button(_get_preset_size(), p_color); - } - - if (!palette_name->get_text().is_empty()) { - palette_name->set_text(vformat("%s*", palette_name->get_text().trim_suffix("*"))); - palette_name->set_tooltip_text(ETR("The changes to this palette have not been saved to a file.")); - } - -#ifdef TOOLS_ENABLED - if (editor_settings) { - PackedColorArray arr_to_save = get_presets(); - const StringName set_project_metadata = SNAME("set_project_metadata"); - editor_settings->call(set_project_metadata, "color_picker", "presets", arr_to_save); - editor_settings->call(set_project_metadata, "color_picker", "palette_edited", true); - } -#endif -} - -void ColorPicker::add_recent_preset(const Color &p_color) { - if (!_select_from_recent_preset_hbc(p_color)) { - if (recent_preset_hbc->get_child_count() >= PRESET_COLUMN_COUNT) { - recent_preset_cache.pop_front(); - recent_presets.pop_front(); - recent_preset_hbc->get_child(PRESET_COLUMN_COUNT - 1)->queue_free(); - } - recent_presets.push_back(p_color); - recent_preset_cache.push_back(p_color); - _add_recent_preset_button(_get_preset_size(), p_color); - } - _select_from_preset_container(p_color); - -#ifdef TOOLS_ENABLED - if (editor_settings) { - PackedColorArray arr_to_save = get_recent_presets(); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "recent_presets", arr_to_save); - } -#endif -} - -void ColorPicker::erase_preset(const Color &p_color) { - List::Element *e = presets.find(p_color); - if (e) { - presets.erase(e); - preset_cache.erase(preset_cache.find(p_color)); - - // Find preset button to remove. - for (int i = 1; i < preset_container->get_child_count(); i++) { - ColorPresetButton *current_btn = Object::cast_to(preset_container->get_child(i)); - if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->queue_free(); - break; - } - } - - palette_name->set_text(vformat("%s*", palette_name->get_text().replace("*", ""))); - palette_name->set_tooltip_text(ETR("The changes to this palette have not been saved to a file.")); - if (presets.is_empty()) { - palette_name->set_text(""); - palette_path = String(); - palette_name->hide(); - } - -#ifdef TOOLS_ENABLED - if (editor_settings) { - PackedColorArray arr_to_save = get_presets(); - const StringName set_project_metadata = SNAME("set_project_metadata"); - editor_settings->call(set_project_metadata, "color_picker", "presets", arr_to_save); - editor_settings->call(set_project_metadata, "color_picker", "palette_edited", true); - editor_settings->call(set_project_metadata, "color_picker", "palette_name", palette_name->get_text()); - editor_settings->call(set_project_metadata, "color_picker", "palette_path", palette_path); - } -#endif - } -} - -void ColorPicker::erase_recent_preset(const Color &p_color) { - List::Element *e = recent_presets.find(p_color); - if (e) { - recent_presets.erase(e); - recent_preset_cache.erase(recent_preset_cache.find(p_color)); - - // Find recent preset button to remove. - for (int i = 1; i < recent_preset_hbc->get_child_count(); i++) { - ColorPresetButton *current_btn = Object::cast_to(recent_preset_hbc->get_child(i)); - if (current_btn && p_color == current_btn->get_preset_color()) { - current_btn->queue_free(); - break; - } - } - -#ifdef TOOLS_ENABLED - if (editor_settings) { - PackedColorArray arr_to_save = get_recent_presets(); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "recent_presets", arr_to_save); - } -#endif - } -} + wheel_radius = p_wheel_radius; + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + wheel_mat->set_shader_parameter("wheel_radius", _radius); -PackedColorArray ColorPicker::get_presets() const { - PackedColorArray arr; - arr.resize(presets.size()); - int i = 0; - for (List::ConstIterator itr = presets.begin(); itr != presets.end(); ++itr, ++i) { - arr.set(i, *itr); + if (current_shape == SHAPE_HSV_WHEEL) { + _update_color(); } - return arr; } -PackedColorArray ColorPicker::get_recent_presets() const { - PackedColorArray arr; - arr.resize(recent_presets.size()); - int i = 0; - for (List::ConstIterator itr = recent_presets.begin(); itr != recent_presets.end(); ++itr, ++i) { - arr.set(i, *itr); - } - return arr; +float ColorPicker::get_wheel_radius() const { + return wheel_radius; } void ColorPicker::set_color_mode(ColorModeType p_mode) { @@ -1146,13 +565,6 @@ void ColorPicker::set_color_mode(ColorModeType p_mode) { return; } - if (slider_theme_modified) { - _reset_sliders_theme(); - } - - mode_popup->set_item_checked(current_mode, false); - mode_popup->set_item_checked(p_mode, true); - if (p_mode < MODE_BUTTON_COUNT) { mode_btns[p_mode]->set_pressed(true); } else if (current_mode < MODE_BUTTON_COUNT) { @@ -1161,12 +573,6 @@ void ColorPicker::set_color_mode(ColorModeType p_mode) { current_mode = p_mode; -#ifdef TOOLS_ENABLED - if (editor_settings) { - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "color_mode", current_mode); - } -#endif - if (!is_inside_tree()) { return; } @@ -1185,28 +591,18 @@ void ColorPicker::set_colorize_sliders(bool p_colorize_sliders) { } colorize_sliders = p_colorize_sliders; - mode_popup->set_item_checked(MODE_MAX + 1, colorize_sliders); if (colorize_sliders) { Ref style_box_empty(memnew(StyleBoxEmpty)); - - if (!slider_theme_modified) { - for (int i = 0; i < SLIDER_COUNT; i++) { - sliders[i]->add_theme_style_override("slider", style_box_empty); - } + for (int i = 0; i < SLIDER_COUNT; i++) { + sliders[i]->add_theme_style_override("slider", style_box_empty); } alpha_slider->add_theme_style_override("slider", style_box_empty); } else { - Ref style_box_flat(memnew(StyleBoxFlat)); - style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale); - style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp()); - - if (!slider_theme_modified) { - for (int i = 0; i < SLIDER_COUNT; i++) { - sliders[i]->add_theme_style_override("slider", style_box_flat); - } + for (int i = 0; i < SLIDER_COUNT; i++) { + sliders[i]->remove_theme_style_override("slider"); } - alpha_slider->add_theme_style_override("slider", style_box_flat); + alpha_slider->remove_theme_style_override("slider"); } } @@ -1245,6 +641,9 @@ void ColorPicker::_update_text_value() { } void ColorPicker::_sample_input(const Ref &p_event) { + if (!display_old_color) { + return; + } const Ref mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); @@ -1297,7 +696,7 @@ void ColorPicker::_sample_draw() { if (color.r > 1 || color.g > 1 || color.b > 1) { // Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview. - sample->draw_texture(theme_cache.overbright_indicator, Point2(uv_edit->get_size().width * 0.5, 0)); + sample->draw_texture(theme_cache.overbright_indicator, Point2(display_old_color ? sample->get_size().width * 0.5 : 0, 0)); } } @@ -1306,103 +705,76 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { return; } - PickerShapeType actual_shape = _get_actual_shape(); if (p_which == 0) { - Vector points; - Vector colors; - Vector colors2; Color col = color; Vector2 center = c->get_size() / 2.0; - switch (actual_shape) { - case SHAPE_HSV_WHEEL: { - points.resize(4); - colors.resize(4); - colors2.resize(4); - real_t ring_radius_x = Math_SQRT12 * c->get_size().width * 0.42; - real_t ring_radius_y = Math_SQRT12 * c->get_size().height * 0.42; - - points.set(0, center - Vector2(ring_radius_x, ring_radius_y)); - points.set(1, center + Vector2(ring_radius_x, -ring_radius_y)); - points.set(2, center + Vector2(ring_radius_x, ring_radius_y)); - points.set(3, center + Vector2(-ring_radius_x, ring_radius_y)); - colors.set(0, Color(1, 1, 1, 1)); - colors.set(1, Color(1, 1, 1, 1)); - colors.set(2, Color(0, 0, 0, 1)); - colors.set(3, Color(0, 0, 0, 1)); - c->draw_polygon(points, colors); - - col.set_hsv(h, 1, 1); - col.a = 0; - colors2.set(0, col); - col.a = 1; - colors2.set(1, col); - col.set_hsv(h, 1, 0); - colors2.set(2, col); - col.a = 0; - colors2.set(3, col); - c->draw_polygon(points, colors2); - break; - } - case SHAPE_HSV_RECTANGLE: { - points.resize(4); - colors.resize(4); - colors2.resize(4); - points.set(0, Vector2()); - points.set(1, Vector2(c->get_size().x, 0)); - points.set(2, c->get_size()); - points.set(3, Vector2(0, c->get_size().y)); - colors.set(0, Color(1, 1, 1, 1)); - colors.set(1, Color(1, 1, 1, 1)); - colors.set(2, Color(0, 0, 0, 1)); - colors.set(3, Color(0, 0, 0, 1)); - c->draw_polygon(points, colors); - col = color; - col.set_hsv(h, 1, 1); - col.a = 0; - colors2.set(0, col); - col.a = 1; - colors2.set(1, col); - col.set_hsv(h, 1, 0); - colors2.set(2, col); - col.a = 0; - colors2.set(3, col); - c->draw_polygon(points, colors2); - break; - } - default: { + if (current_shape == SHAPE_HSV_RECTANGLE || current_shape == SHAPE_HSV_WHEEL) { + Vector points; + Vector colors; + Vector colors2; + if (current_shape == SHAPE_HSV_RECTANGLE) { + points.append(Vector2()); + points.append(Vector2(c->get_size().x, 0)); + points.append(c->get_size()); + points.append(Vector2(0, c->get_size().y)); + } else { + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + real_t ring_radius_x = Math_SQRT12 * c->get_size().width * _radius; + real_t ring_radius_y = Math_SQRT12 * c->get_size().height * _radius; + + points.append(center - Vector2(ring_radius_x, ring_radius_y)); + points.append(center + Vector2(ring_radius_x, -ring_radius_y)); + points.append(center + Vector2(ring_radius_x, ring_radius_y)); + points.append(center + Vector2(-ring_radius_x, ring_radius_y)); } + colors.append(Color(1, 1, 1, 1)); + colors.append(Color(1, 1, 1, 1)); + colors.append(Color(0, 0, 0, 1)); + colors.append(Color(0, 0, 0, 1)); + c->draw_polygon(points, colors); + + col.set_hsv(h, 1, 1); + col.a = 0; + colors2.append(col); + col.a = 1; + colors2.append(col); + col.set_hsv(h, 1, 0); + colors2.append(col); + col.a = 0; + colors2.append(col); + c->draw_polygon(points, colors2); } int x; int y; - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { - x = center.x + (center.x * Math::cos((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); - y = center.y + (center.y * Math::sin((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { + x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); + y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); } else { - real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; - real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * _radius : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * _radius : 0; Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (theme_cache.picker_cursor->get_width() / 2); y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (theme_cache.picker_cursor->get_height() / 2); } - c->draw_texture(theme_cache.picker_cursor, Point2(x, y)); - - col.set_hsv(h, 1, 1); - if (actual_shape == SHAPE_HSV_WHEEL) { - points.resize(4); - double h1 = h - (0.5 / 360); - double h2 = h + (0.5 / 360); - points.set(0, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU)), center.y + (center.y * Math::sin(h1 * Math_TAU)))); - points.set(1, Point2(center.x + (center.x * Math::cos(h1 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h1 * Math_TAU) * 0.84))); - points.set(2, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU)), center.y + (center.y * Math::sin(h2 * Math_TAU)))); - points.set(3, Point2(center.x + (center.x * Math::cos(h2 * Math_TAU) * 0.84), center.y + (center.y * Math::sin(h2 * Math_TAU) * 0.84))); - c->draw_multiline(points, col.inverted()); + Color _col = color; + _col.a = 1.0; + c->draw_texture(theme_cache.picker_cursor_bg, Point2(x, y), _col); + + if (current_shape == SHAPE_HSV_WHEEL) { + float radius = 1.0 - (CLAMP(wheel_radius, 0.1, 0.5) * 0.5); + Point2 pos = center - (theme_cache.picker_cursor->get_size() * 0.5) + Point2(center.x * Math::cos(h * Math_TAU) * radius, center.y * Math::sin(h * Math_TAU) * radius); + _col.set_hsv(_col.get_h(), 1.0, 1.0); + c->draw_texture(theme_cache.picker_cursor_bg, pos, _col); + c->draw_texture(theme_cache.picker_cursor, pos); } + c->draw_texture(theme_cache.picker_cursor, Point2(x, y)); } else if (p_which == 1) { - if (actual_shape == SHAPE_HSV_RECTANGLE) { + if (current_shape == SHAPE_HSV_RECTANGLE) { c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y)); c->draw_texture_rect(theme_cache.color_hue, Rect2(Point2(), Size2(1, 1))); c->draw_set_transform(Point2(), 0, Size2(1, 1)); @@ -1410,15 +782,15 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { Color col; col.set_hsv(h, 1, 1); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); - } else if (actual_shape == SHAPE_OKHSL_CIRCLE) { + } else if (current_shape == SHAPE_OKHSL_CIRCLE) { Vector points; Vector colors; Color col; - col.set_ok_hsl(ok_hsl_h, ok_hsl_s, 1); + col.set_ok_hsl(h, s, 1); Color col2; - col2.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0.5); + col2.set_ok_hsl(h, s, 0.5); Color col3; - col3.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0); + col3.set_ok_hsl(h, s, 0); points.resize(6); colors.resize(6); points.set(0, Vector2(c->get_size().x, 0)); @@ -1434,10 +806,10 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { colors.set(4, col2); colors.set(5, col); c->draw_polygon(points, colors); - int y = c->get_size().y - c->get_size().y * CLAMP(ok_hsl_l, 0, 1); - col.set_ok_hsl(ok_hsl_h, 1, ok_hsl_l); + int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1); + col.set_ok_hsl(h, 1, v); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); - } else if (actual_shape == SHAPE_VHS_CIRCLE) { + } else if (current_shape == SHAPE_VHS_CIRCLE) { Vector points; Vector colors; Color col; @@ -1459,10 +831,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } } else if (p_which == 2) { c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1)); - if (actual_shape == SHAPE_VHS_CIRCLE) { + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { circle_mat->set_shader_parameter("v", v); - } else if (actual_shape == SHAPE_OKHSL_CIRCLE) { - circle_mat->set_shader_parameter("ok_hsl_l", ok_hsl_l); } } } @@ -1475,25 +845,23 @@ void ColorPicker::_slider_draw(int p_which) { void ColorPicker::_uv_input(const Ref &p_event, Control *c) { Ref bev = p_event; - PickerShapeType actual_shape = _get_actual_shape(); if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { Vector2 center = c->get_size() / 2.0; - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { real_t dist = center.distance_to(bev->get_position()); if (dist <= center.x) { real_t rad = center.angle_to_point(bev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); - ok_hsl_h = h; - ok_hsl_s = s; } else { return; } } else { - real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; - real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * _radius : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * _radius : 0; Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); if (bev->get_position().x < corner_x || bev->get_position().x > c->get_size().x - corner_x || @@ -1501,7 +869,7 @@ void ColorPicker::_uv_input(const Ref &p_event, Control *c) { { real_t dist = center.distance_to(bev->get_position()); - if (dist >= center.x * 0.84 && dist <= center.x) { + if (dist >= center.x * (_radius * 2) && dist <= center.x) { real_t rad = center.angle_to_point(bev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; spinning = true; @@ -1533,7 +901,7 @@ void ColorPicker::_uv_input(const Ref &p_event, Control *c) { if (deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } - add_recent_preset(color); + // add_recent_preset(color); changing_color = false; spinning = false; } else { @@ -1550,20 +918,19 @@ void ColorPicker::_uv_input(const Ref &p_event, Control *c) { } Vector2 center = c->get_size() / 2.0; - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { real_t dist = center.distance_to(mev->get_position()); real_t rad = center.angle_to_point(mev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); - ok_hsl_h = h; - ok_hsl_s = s; } else { if (spinning) { real_t rad = center.angle_to_point(mev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; } else { - real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; - real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * _radius : 0; + real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * _radius : 0; Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); real_t x = CLAMP(mev->get_position().x - corner_x, 0, real_size.x); @@ -1586,15 +953,13 @@ void ColorPicker::_uv_input(const Ref &p_event, Control *c) { void ColorPicker::_w_input(const Ref &p_event) { Ref bev = p_event; - PickerShapeType actual_shape = _get_actual_shape(); if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { changing_color = true; float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); - ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } @@ -1607,7 +972,7 @@ void ColorPicker::_w_input(const Ref &p_event) { set_pick_color(color); if (!bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { - add_recent_preset(color); + // add_recent_preset(color); emit_signal(SNAME("color_changed"), color); } else if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); @@ -1621,9 +986,8 @@ void ColorPicker::_w_input(const Ref &p_event) { return; } float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (current_shape == SHAPE_VHS_CIRCLE || current_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); - ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } @@ -1643,10 +1007,6 @@ void ColorPicker::_slider_or_spin_input(const Ref &p_event) { line_edit_mouse_release = false; return; } - Ref bev = p_event; - if (bev.is_valid() && !bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { - add_recent_preset(color); - } } void ColorPicker::_line_edit_input(const Ref &p_event) { @@ -1656,326 +1016,79 @@ void ColorPicker::_line_edit_input(const Ref &p_event) { } } -void ColorPicker::_preset_input(const Ref &p_event, const Color &p_color) { - Ref bev = p_event; - - if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { - set_pick_color(p_color); - add_recent_preset(color); - emit_signal(SNAME("color_changed"), p_color); - } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && can_add_swatches) { - erase_preset(p_color); - emit_signal(SNAME("preset_removed"), p_color); - } - } -} - -void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton *p_preset) { - if (!p_pressed) { - return; - } - set_pick_color(p_preset->get_preset_color()); - - recent_presets.move_to_back(recent_presets.find(p_preset->get_preset_color())); - List::Element *e = recent_preset_cache.find(p_preset->get_preset_color()); - if (e) { - recent_preset_cache.move_to_back(e); - } - - recent_preset_hbc->move_child(p_preset, 0); - emit_signal(SNAME("color_changed"), p_preset->get_preset_color()); -} - -void ColorPicker::_text_changed(const String &) { - text_changed = true; -} - -void ColorPicker::_add_preset_pressed() { - add_preset(color); - emit_signal(SNAME("preset_added"), color); +void ColorPicker::_text_changed(const String &) { + text_changed = true; } void ColorPicker::_pick_button_pressed() { - is_picking_color = true; - if (!picker_window) { picker_window = memnew(Popup); - picker_window->set_size(Vector2i(55, 72)); - picker_window->connect(SceneStringName(visibility_changed), callable_mp(this, &ColorPicker::_pick_finished)); - picker_window->connect(SceneStringName(window_input), callable_mp(this, &ColorPicker::_target_gui_input)); - - picker_window->set_flag(Window::FLAG_EXCLUDE_FROM_CAPTURE, true); - - picker_preview = memnew(Panel); - picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_preview->set_size(Vector2i(55, 72)); - picker_window->add_child(picker_preview); - - picker_preview_color = memnew(Panel); - picker_preview_color->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_preview_color->set_size(Vector2i(51, 15)); - picker_preview_color->set_position(Vector2i(2, 55)); - picker_preview->add_child(picker_preview_color); - - picker_texture_zoom = memnew(TextureRect); - picker_texture_zoom->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_texture_zoom->set_custom_minimum_size(Vector2i(51, 51)); - picker_texture_zoom->set_position(Vector2i(2, 2)); - picker_texture_zoom->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); - picker_preview->add_child(picker_texture_zoom); - - picker_preview_style_box.instantiate(); - picker_preview->add_theme_style_override(SceneStringName(panel), picker_preview_style_box); - - picker_preview_style_box_color.instantiate(); - picker_preview_color->add_theme_style_override(SceneStringName(panel), picker_preview_style_box_color); - - add_child(picker_window, false, INTERNAL_MODE_FRONT); - } - set_process_internal(true); - - picker_window->popup(); -} - -void ColorPicker::_target_gui_input(const Ref &p_event) { - const Ref mouse_event = p_event; - if (mouse_event.is_valid() && mouse_event->is_pressed()) { + picker_window->set_transient(true); + picker_window->set_size(Size2i(1, 1)); picker_window->hide(); - _pick_finished(); - } -} - -void ColorPicker::_pick_finished() { - if (picker_window->is_visible()) { - return; - } - - if (Input::get_singleton()->is_action_just_pressed(SNAME("ui_cancel"))) { - set_pick_color(old_color); - } else { - emit_signal(SNAME("color_changed"), color); - } - is_picking_color = false; - set_process_internal(false); - picker_window->hide(); -} - -void ColorPicker::_update_menu_items() { - if (!options_menu) { - options_menu = memnew(PopupMenu); - add_child(options_menu, false, INTERNAL_MODE_FRONT); - options_menu->force_parent_owned(); - options_menu->connect("id_pressed", callable_mp(this, &ColorPicker::_options_menu_cbk)); - } - - options_menu->clear(); - options_menu->reset_size(); - - if (!presets.is_empty()) { - options_menu->add_icon_item(get_theme_icon(SNAME("save"), SNAME("FileDialog")), RTR("Save"), static_cast(MenuOption::MENU_SAVE)); - options_menu->set_item_tooltip(-1, ETR("Save the current color palette to reuse later.")); - } - if (!palette_path.is_empty()) { - options_menu->add_icon_item(get_theme_icon(SNAME("save"), SNAME("FileDialog")), RTR("Save As"), static_cast(MenuOption::MENU_SAVE_AS)); - options_menu->set_item_tooltip(-1, ETR("Save the current color palette as a new to reuse later.")); - } - options_menu->add_icon_item(get_theme_icon(SNAME("load"), SNAME("FileDialog")), RTR("Load"), static_cast(MenuOption::MENU_LOAD)); - options_menu->set_item_tooltip(-1, ETR("Load existing color palette.")); - - if (Engine::get_singleton()->is_editor_hint()) { - options_menu->add_icon_item(get_theme_icon(SNAME("load"), SNAME("FileDialog")), RTR("Quick Load"), static_cast(MenuOption::MENU_QUICKLOAD)); - options_menu->set_item_tooltip(-1, ETR("Load existing color palette.")); - } - - if (!presets.is_empty()) { - options_menu->add_icon_item(get_theme_icon(SNAME("clear"), SNAME("FileDialog")), RTR("Clear"), static_cast(MenuOption::MENU_CLEAR)); - options_menu->set_item_tooltip(-1, ETR("Clear the currently loaded color palettes in the picker.")); - } -} - -void ColorPicker::_update_menu() { - _update_menu_items(); - Rect2 gt = menu_btn->get_screen_rect(); - menu_btn->reset_size(); - int min_size = menu_btn->get_minimum_size().width; - Vector2 popup_pos = gt.get_end() - Vector2(min_size, 0); - options_menu->set_position(popup_pos); - options_menu->popup(); -} + picker_window->connect("popup_hide", callable_mp(this, &ColorPicker::_picking_finished)); + add_child(picker_window, false, INTERNAL_MODE_FRONT); -void ColorPicker::_options_menu_cbk(int p_which) { - if (!file_dialog) { - file_dialog = memnew(FileDialog); - add_child(file_dialog, false, INTERNAL_MODE_FRONT); - file_dialog->force_parent_owned(); - file_dialog->connect("file_selected", callable_mp(this, &ColorPicker::_palette_file_selected)); - file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM); - file_dialog->set_current_dir(Engine::get_singleton()->is_editor_hint() ? "res://" : "user://"); + if (is_legacy_picking) { + picker_window->set_exclusive(true); + picker_window->set_wrap_controls(false); + picker_texture_rect = memnew(TextureRect); + picker_window->add_child(picker_texture_rect); + } } - MenuOption option = static_cast(p_which); - switch (option) { - case MenuOption::MENU_SAVE: - _save_palette(false); - break; - case MenuOption::MENU_SAVE_AS: - _save_palette(true); - break; - case MenuOption::MENU_LOAD: - _load_palette(); - break; - -#ifdef TOOLS_ENABLED - case MenuOption::MENU_QUICKLOAD: - if (quick_open_callback.is_valid()) { - file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); - quick_open_callback.call_deferred(); - } - break; -#endif // TOOLS_ENABLED - case MenuOption::MENU_CLEAR: { - PackedColorArray colors = get_presets(); - for (Color c : colors) { - erase_preset(c); - } - - palette_name->set_text(""); - palette_name->set_tooltip_text(""); - palette_path = String(); - btn_preset->set_pressed(false); - -#ifdef TOOLS_ENABLED - if (editor_settings) { - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_name", palette_name->get_text()); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_path", palette_path); - editor_settings->call(SNAME("set_project_metadata"), "color_picker", "palette_edited", false); - } -#endif // TOOLS_ENABLED - - } + if (is_legacy_picking) { + Rect2i screen_rect; + if (picker_window->is_embedded()) { + screen_rect = picker_window->get_embedder()->get_visible_rect(); + picker_window->set_position(Point2i()); + picker_texture_rect->set_texture(ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image())); + } else { + screen_rect = picker_window->get_parent_rect(); + picker_window->set_position(screen_rect.position); - break; - default: - break; - } -} + Ref target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8); + DisplayServer *ds = DisplayServer::get_singleton(); -void ColorPicker::_pick_button_pressed_legacy() { - if (!is_inside_tree()) { - return; - } + // Add the Texture of each Window to the Image. + Vector wl = ds->get_window_list(); + // FIXME: sort windows by visibility. + for (int index = 0; index < wl.size(); index++) { + DisplayServer::WindowID wid = wl[index]; + if (wid == DisplayServer::INVALID_WINDOW_ID) { + continue; + } - if (!picker_window) { - picker_window = memnew(Popup); - picker_window->hide(); - picker_window->set_transient(true); - add_child(picker_window, false, INTERNAL_MODE_FRONT); + ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid); + if (woid == ObjectID()) { + continue; + } - picker_texture_rect = memnew(TextureRect); - picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); - picker_texture_rect->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE); - picker_texture_rect->set_default_cursor_shape(Control::CURSOR_CROSS); - picker_window->add_child(picker_texture_rect); - picker_texture_rect->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_picker_texture_input)); - - picker_preview = memnew(Panel); - picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_preview->set_size(Vector2i(55, 72)); - picker_window->add_child(picker_preview); - - picker_preview_color = memnew(Panel); - picker_preview_color->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_preview_color->set_size(Vector2i(51, 15)); - picker_preview_color->set_position(Vector2i(2, 55)); - picker_preview->add_child(picker_preview_color); - - picker_texture_zoom = memnew(TextureRect); - picker_texture_zoom->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_texture_zoom->set_custom_minimum_size(Vector2i(51, 51)); - picker_texture_zoom->set_position(Vector2i(2, 2)); - picker_texture_zoom->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); - picker_preview->add_child(picker_texture_zoom); - - picker_preview_style_box.instantiate(); - picker_preview->add_theme_style_override(SceneStringName(panel), picker_preview_style_box); - - picker_preview_style_box_color.instantiate(); - picker_preview_color->add_theme_style_override(SceneStringName(panel), picker_preview_style_box_color); - } - - Rect2i screen_rect; - if (picker_window->is_embedded()) { - Ref tx = ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image()); - screen_rect = picker_window->get_embedder()->get_visible_rect(); - picker_window->set_position(Point2i()); - picker_texture_rect->set_texture(tx); - - Ref atlas; - atlas.instantiate(); - atlas->set_atlas(tx); - picker_texture_zoom->set_texture(atlas); - } else { - screen_rect = picker_window->get_parent_rect(); - picker_window->set_position(screen_rect.position); - - Ref target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8); - DisplayServer *ds = DisplayServer::get_singleton(); - - // Add the Texture of each Window to the Image. - Vector wl = ds->get_window_list(); - // FIXME: sort windows by visibility. - for (const DisplayServer::WindowID &window_id : wl) { - Window *w = Window::get_from_id(window_id); - if (!w) { - continue; + Window *w = Object::cast_to(ObjectDB::get_instance(woid)); + Ref img = w->get_texture()->get_image(); + if (!img.is_valid() || img->is_empty()) { + continue; + } + img->convert(Image::FORMAT_RGB8); + target_image->blit_rect(img, Rect2i(Point2i(), img->get_size()), w->get_position()); } - Ref img = w->get_texture()->get_image(); - if (!img.is_valid() || img->is_empty()) { - continue; - } - img->convert(Image::FORMAT_RGB8); - target_image->blit_rect(img, Rect2i(Point2i(0, 0), img->get_size()), w->get_position()); + picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image)); } - - picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image)); } - picker_window->set_size(screen_rect.size); + prev_pick_color = color; picker_window->popup(); + set_process_internal(true); } -void ColorPicker::_picker_texture_input(const Ref &p_event) { - if (!is_inside_tree()) { - return; - } - - Ref bev = p_event; - if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) { - set_pick_color(picker_color); +void ColorPicker::_picking_finished() { + if (Input::get_singleton()->is_action_pressed(SNAME("ui_cancel")) || Input::get_singleton()->is_mouse_button_pressed(MouseButton::RIGHT)) { + set_pick_color(prev_pick_color); + } else { emit_signal(SNAME("color_changed"), color); - picker_window->hide(); - } - - Ref mev = p_event; - if (mev.is_valid()) { - Ref img = picker_texture_rect->get_texture()->get_image(); - if (img.is_valid() && !img->is_empty()) { - Vector2 ofs = mev->get_position(); - picker_preview->set_position(ofs - Vector2(28, 28)); - Vector2 scale = picker_texture_rect->get_size() / img->get_size(); - ofs /= scale; - picker_color = img->get_pixel(ofs.x, ofs.y); - picker_preview_style_box_color->set_bg_color(picker_color); - picker_preview_style_box->set_bg_color(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); - - Ref atlas = picker_texture_zoom->get_texture(); - if (atlas.is_valid()) { - atlas->set_region(Rect2i(ofs.x - 8, ofs.y - 8, 17, 17)); - } - } } + set_process_internal(false); } void ColorPicker::_html_focus_exit() { @@ -1990,35 +1103,45 @@ void ColorPicker::_html_focus_exit() { } } -void ColorPicker::set_can_add_swatches(bool p_enabled) { - if (can_add_swatches == p_enabled) { - return; - } - can_add_swatches = p_enabled; - if (!p_enabled) { - btn_add_preset->set_disabled(true); - btn_add_preset->set_focus_mode(FOCUS_NONE); - } else { - btn_add_preset->set_disabled(false); - btn_add_preset->set_focus_mode(FOCUS_ALL); - } +void ColorPicker::_on_swatch_button_right_pressed(int p_index) { + remove_swatch_color_by_index(p_index); + emit_signal(SNAME("swatches_changed")); } -bool ColorPicker::are_swatches_enabled() const { - return can_add_swatches; +void ColorPicker::_on_swatch_button_pressed(const Color &p_color) { + set_pick_color(p_color); + emit_signal(SNAME("color_changed"), p_color); } -void ColorPicker::set_presets_visible(bool p_visible) { - if (presets_visible == p_visible) { - return; +void ColorPicker::_swatches_folding_changed(bool p_folded) { + if (can_add_swatches) { + swatches_foldable->set_button_hidden(0, p_folded); } - presets_visible = p_visible; - btn_preset->set_visible(p_visible); - btn_recent_preset->set_visible(p_visible); } -bool ColorPicker::are_presets_visible() const { - return presets_visible; +void ColorPicker::_add_swatch_button_pressed() { + bool emit_changed = !swatches.has(color); + add_swatch_color(color); + if (emit_changed) { + emit_signal(SNAME("swatches_changed")); + } +} + +void ColorPicker::_update_selected_swatch() { + SwatchButton *cur_button = Object::cast_to(swatches_group->get_pressed_button()); + if (cur_button) { + if (cur_button->get_color() == color) { + return; + } + cur_button->set_pressed_no_signal(false); + } + for (int i = 0; i < swatches_hbc->get_child_count(); i++) { + SwatchButton *button = Object::cast_to(swatches_hbc->get_child(i)); + if (button->get_color() == color) { + button->set_pressed_no_signal(true); + return; + } + } } void ColorPicker::set_modes_visible(bool p_visible) { @@ -2045,12 +1168,23 @@ bool ColorPicker::is_sampler_visible() const { return sampler_visible; } +void ColorPicker::set_can_pick_screen_color(bool p_enabled) { + if (can_pick_screen_color != p_enabled) { + can_pick_screen_color = p_enabled; + btn_pick->set_visible(can_pick_screen_color); + } +} + +bool ColorPicker::get_can_pick_screen_color() const { + return can_pick_screen_color; +} + void ColorPicker::set_sliders_visible(bool p_visible) { if (sliders_visible == p_visible) { return; } sliders_visible = p_visible; - slider_gc->set_visible(p_visible); + sliders_vbc->set_visible(p_visible); } bool ColorPicker::are_sliders_visible() const { @@ -2069,52 +1203,176 @@ bool ColorPicker::is_hex_visible() const { return hex_visible; } +void ColorPicker::set_swatches(const PackedColorArray &p_swatches) { + swatches.clear(); + for (Color col : p_swatches) { + if (!swatches.has(col)) { + swatches.push_back(col); + } + } + update_swatches(); +} + +PackedColorArray ColorPicker::get_swatches() const { + return swatches; +} + +void ColorPicker::set_swatches_visible(bool p_visible) { + if (swatches_visible != p_visible) { + swatches_visible = p_visible; + swatches_foldable->set_visible(swatches_visible); + } +} + +bool ColorPicker::is_swatches_visible() const { + return swatches_visible; +} + +void ColorPicker::set_can_add_swatches(bool p_enabled) { + if (can_add_swatches != p_enabled) { + can_add_swatches = p_enabled; + if (swatches_foldable->is_expanded()) { + swatches_foldable->set_button_hidden(0, !can_add_swatches); + } + } +} + +bool ColorPicker::get_can_add_swatches() const { + return can_add_swatches; +} + +void ColorPicker::add_swatch_color(const Color &p_color) { + if (!swatches.has(p_color)) { + swatches.insert(0, p_color); + SwatchButton *button = memnew(SwatchButton); + button->set_custom_minimum_size(Size2(theme_cache.swatch_size, theme_cache.swatch_size)); + button->set_color(p_color); + button->set_button_group(swatches_group); + SwatchButton *cur_button = Object::cast_to(swatches_group->get_pressed_button()); + if (cur_button) { + cur_button->set_pressed_no_signal(false); + } + button->set_pressed_no_signal(true); + swatches_hbc->add_child(button); + swatches_hbc->move_child(button, 0); + button->connect(SNAME("color_selected"), callable_mp(this, &ColorPicker::_on_swatch_button_pressed)); + button->connect(SNAME("right_click_pressed"), callable_mp(this, &ColorPicker::_on_swatch_button_right_pressed)); + } else { + int idx = swatches.find(p_color); + if (swatches.size() == 1 || idx == 0) { + return; + } + swatches.remove_at(idx); + swatches.insert(0, p_color); + SwatchButton *button = Object::cast_to(swatches_hbc->get_child(idx)); + swatches_hbc->move_child(button, 0); + } +} + +void ColorPicker::remove_swatch_color(const Color &p_color) { + if (swatches.has(p_color)) { + remove_swatch_color_by_index(swatches.find(p_color)); + } +} + +void ColorPicker::remove_swatch_color_by_index(int p_index) { + ERR_FAIL_INDEX(p_index, swatches.size()); + swatches.remove_at(p_index); + SwatchButton *button = Object::cast_to(swatches_hbc->get_child(p_index)); + button->disconnect(SNAME("color_selected"), callable_mp(this, &ColorPicker::_on_swatch_button_pressed)); + button->disconnect(SNAME("right_click_pressed"), callable_mp(this, &ColorPicker::_on_swatch_button_right_pressed)); + swatches_hbc->remove_child(button); + button->queue_free(); +} + +void ColorPicker::clear_swatches() { + if (swatches.size() > 0) { + for (int i = swatches_hbc->get_child_count() - 1; i >= 0; i--) { + remove_swatch_color_by_index(i); + } + } +} + +void ColorPicker::update_swatches() { + for (int i = swatches_hbc->get_child_count() - 1; i >= 0; i--) { + SwatchButton *button = Object::cast_to(swatches_hbc->get_child(i)); + button->disconnect(SNAME("color_selected"), callable_mp(this, &ColorPicker::_on_swatch_button_pressed)); + button->disconnect(SNAME("right_click_pressed"), callable_mp(this, &ColorPicker::_on_swatch_button_right_pressed)); + swatches_hbc->remove_child(button); + button->queue_free(); + } + for (Color col : swatches) { + SwatchButton *button = memnew(SwatchButton); + button->set_custom_minimum_size(Size2(theme_cache.swatch_size, theme_cache.swatch_size)); + button->set_color(col); + button->set_button_group(swatches_group); + swatches_hbc->add_child(button); + if (col == color) { + button->set_pressed_no_signal(true); + } + button->connect("color_selected", callable_mp(this, &ColorPicker::_on_swatch_button_pressed)); + button->connect("right_click_pressed", callable_mp(this, &ColorPicker::_on_swatch_button_right_pressed)); + } +} + void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color); ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color); + ClassDB::bind_method(D_METHOD("set_old_color", "color"), &ColorPicker::set_old_color); + ClassDB::bind_method(D_METHOD("set_display_old_color", "display"), &ColorPicker::set_display_old_color); + ClassDB::bind_method(D_METHOD("is_displaying_old_color"), &ColorPicker::is_displaying_old_color); ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode); ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode); ClassDB::bind_method(D_METHOD("set_color_mode", "color_mode"), &ColorPicker::set_color_mode); ClassDB::bind_method(D_METHOD("get_color_mode"), &ColorPicker::get_color_mode); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha); - ClassDB::bind_method(D_METHOD("set_can_add_swatches", "enabled"), &ColorPicker::set_can_add_swatches); - ClassDB::bind_method(D_METHOD("are_swatches_enabled"), &ColorPicker::are_swatches_enabled); - ClassDB::bind_method(D_METHOD("set_presets_visible", "visible"), &ColorPicker::set_presets_visible); - ClassDB::bind_method(D_METHOD("are_presets_visible"), &ColorPicker::are_presets_visible); ClassDB::bind_method(D_METHOD("set_modes_visible", "visible"), &ColorPicker::set_modes_visible); ClassDB::bind_method(D_METHOD("are_modes_visible"), &ColorPicker::are_modes_visible); ClassDB::bind_method(D_METHOD("set_sampler_visible", "visible"), &ColorPicker::set_sampler_visible); ClassDB::bind_method(D_METHOD("is_sampler_visible"), &ColorPicker::is_sampler_visible); + ClassDB::bind_method(D_METHOD("set_can_pick_screen_color", "enabled"), &ColorPicker::set_can_pick_screen_color); + ClassDB::bind_method(D_METHOD("get_can_pick_screen_color"), &ColorPicker::get_can_pick_screen_color); ClassDB::bind_method(D_METHOD("set_sliders_visible", "visible"), &ColorPicker::set_sliders_visible); ClassDB::bind_method(D_METHOD("are_sliders_visible"), &ColorPicker::are_sliders_visible); ClassDB::bind_method(D_METHOD("set_hex_visible", "visible"), &ColorPicker::set_hex_visible); ClassDB::bind_method(D_METHOD("is_hex_visible"), &ColorPicker::is_hex_visible); - ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset); - ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset); - ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets); - ClassDB::bind_method(D_METHOD("add_recent_preset", "color"), &ColorPicker::add_recent_preset); - ClassDB::bind_method(D_METHOD("erase_recent_preset", "color"), &ColorPicker::erase_recent_preset); - ClassDB::bind_method(D_METHOD("get_recent_presets"), &ColorPicker::get_recent_presets); ClassDB::bind_method(D_METHOD("set_picker_shape", "shape"), &ColorPicker::set_picker_shape); ClassDB::bind_method(D_METHOD("get_picker_shape"), &ColorPicker::get_picker_shape); + ClassDB::bind_method(D_METHOD("set_wheel_radius", "wheel_radius"), &ColorPicker::set_wheel_radius); + ClassDB::bind_method(D_METHOD("get_wheel_radius"), &ColorPicker::get_wheel_radius); + ClassDB::bind_method(D_METHOD("set_colorize_sliders", "colorize_sliders"), &ColorPicker::set_colorize_sliders); + ClassDB::bind_method(D_METHOD("is_colorizing_sliders"), &ColorPicker::is_colorizing_sliders); + ClassDB::bind_method(D_METHOD("set_swatches", "swatches"), &ColorPicker::set_swatches); + ClassDB::bind_method(D_METHOD("get_swatches"), &ColorPicker::get_swatches); + ClassDB::bind_method(D_METHOD("set_swatches_visible", "visible"), &ColorPicker::set_swatches_visible); + ClassDB::bind_method(D_METHOD("is_swatches_visible"), &ColorPicker::is_swatches_visible); + ClassDB::bind_method(D_METHOD("add_swatch_color", "color"), &ColorPicker::add_swatch_color); + ClassDB::bind_method(D_METHOD("remove_swatch_color", "color"), &ColorPicker::remove_swatch_color); + ClassDB::bind_method(D_METHOD("remove_swatch_color_by_index", "index"), &ColorPicker::remove_swatch_color_by_index); + ClassDB::bind_method(D_METHOD("set_can_add_swatches", "enabled"), &ColorPicker::set_can_add_swatches); + ClassDB::bind_method(D_METHOD("get_can_add_swatches"), &ColorPicker::get_can_add_swatches); + ClassDB::bind_method(D_METHOD("clear_swatches"), &ColorPicker::clear_swatches); + ClassDB::bind_method(D_METHOD("update_swatches"), &ColorPicker::update_swatches); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "color_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL"), "set_color_mode", "get_color_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_radius"), "set_wheel_radius", "get_wheel_radius"); ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle,None"), "set_picker_shape", "get_picker_shape"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_add_swatches"), "set_can_add_swatches", "are_swatches_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "color_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL"), "set_color_mode", "get_color_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "colorize_sliders"), "set_colorize_sliders", "is_colorizing_sliders"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_add_swatches"), "set_can_add_swatches", "get_can_add_swatches"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_pick_screen_color"), "set_can_pick_screen_color", "get_can_pick_screen_color"); ADD_GROUP("Customization", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sampler_visible"), "set_sampler_visible", "is_sampler_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "color_modes_visible"), "set_modes_visible", "are_modes_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sliders_visible"), "set_sliders_visible", "are_sliders_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hex_visible"), "set_hex_visible", "is_hex_visible"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "swatches_visible"), "set_swatches_visible", "is_swatches_visible"); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); - ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color"))); - ADD_SIGNAL(MethodInfo("preset_removed", PropertyInfo(Variant::COLOR, "color"))); + ADD_SIGNAL(MethodInfo("swatches_changed")); BIND_ENUM_CONSTANT(MODE_RGB); BIND_ENUM_CONSTANT(MODE_HSV); @@ -2127,16 +1385,13 @@ void ColorPicker::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_OKHSL_CIRCLE); BIND_ENUM_CONSTANT(SHAPE_NONE); - BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ColorPicker, content_margin, "margin"); - BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, label_width); - BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, sv_width); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, sv_height); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, h_width); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, sample_height); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, expand_shape); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, swatch_size); - BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ColorPicker, center_slider_grabbers); - - BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, menu_option); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, screen_picker); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, expanded_arrow); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, folded_arrow); @@ -2146,29 +1401,23 @@ void ColorPicker::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_rect_wheel); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_circle); - BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, bar_arrow); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, sample_bg); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, sample_revert); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, overbright_indicator); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, picker_cursor); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, picker_cursor_bg); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, color_hue); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, color_okhsl_hue); - - BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_normal, "tab_unselected", "TabContainer"); - BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_pressed, "tab_selected", "TabContainer"); - BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_hover, "tab_selected", "TabContainer"); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, hex_icon); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, hex_code_icon); } ColorPicker::ColorPicker() { - internal_margin = memnew(MarginContainer); - add_child(internal_margin, false, INTERNAL_MODE_FRONT); - - VBoxContainer *real_vbox = memnew(VBoxContainer); - internal_margin->add_child(real_vbox); + set_theme_type_variation("ColorPickerVBox"); - HBoxContainer *hb_edit = memnew(HBoxContainer); - real_vbox->add_child(hb_edit); - hb_edit->set_v_size_flags(SIZE_SHRINK_BEGIN); + hb_edit = memnew(HBoxContainer); + hb_edit->set_theme_type_variation("ColorPickerHBox"); + add_child(hb_edit, false, INTERNAL_MODE_FRONT); uv_edit = memnew(Control); hb_edit->add_child(uv_edit); @@ -2179,10 +1428,13 @@ ColorPicker::ColorPicker() { uv_edit->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(0, uv_edit)); sample_hbc = memnew(HBoxContainer); - real_vbox->add_child(sample_hbc); + sample_hbc->set_theme_type_variation("ColorPickerHBox"); + add_child(sample_hbc, false, INTERNAL_MODE_FRONT); btn_pick = memnew(Button); + btn_pick->set_theme_type_variation("PickerButton"); btn_pick->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); + btn_pick->set_size_mode(BaseButton::SIZE_MODE_FIT_HEIGHT); sample_hbc->add_child(btn_pick); sample = memnew(TextureRect); @@ -2192,11 +1444,13 @@ ColorPicker::ColorPicker() { sample->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_sample_draw)); btn_shape = memnew(MenuButton); + btn_shape->set_theme_type_variation("PickerMenuButton"); + btn_shape->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); + btn_shape->set_size_mode(BaseButton::SIZE_MODE_FIT_HEIGHT); btn_shape->set_flat(false); sample_hbc->add_child(btn_shape); btn_shape->set_toggle_mode(true); btn_shape->set_tooltip_text(ETR("Select a picker shape.")); - btn_shape->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); current_shape = SHAPE_HSV_RECTANGLE; @@ -2213,13 +1467,18 @@ ColorPicker::ColorPicker() { add_mode(new ColorModeRAW(this)); add_mode(new ColorModeOKHSL(this)); + sliders_vbc = memnew(VBoxContainer); + sliders_vbc->add_theme_constant_override("separation", 0); + add_child(sliders_vbc, false, INTERNAL_MODE_FRONT); mode_hbc = memnew(HBoxContainer); - real_vbox->add_child(mode_hbc); + mode_hbc->add_theme_constant_override("separation", 0); + sliders_vbc->add_child(mode_hbc); - mode_group.instantiate(); + Ref mode_group(memnew(ButtonGroup)); for (int i = 0; i < MODE_BUTTON_COUNT; i++) { mode_btns[i] = memnew(Button); + mode_btns[i]->set_theme_type_variation("PickerModeButton"); mode_hbc->add_child(mode_btns[i]); mode_btns[i]->set_focus_mode(FOCUS_NONE); mode_btns[i]->set_h_size_flags(SIZE_EXPAND_FILL); @@ -2230,83 +1489,112 @@ ColorPicker::ColorPicker() { } mode_btns[0]->set_pressed(true); - btn_mode = memnew(MenuButton); - btn_mode->set_text("..."); - btn_mode->set_flat(false); - mode_hbc->add_child(btn_mode); - btn_mode->set_toggle_mode(true); - btn_mode->set_tooltip_text(ETR("Select a picker mode.")); - current_mode = MODE_RGB; - mode_popup = btn_mode->get_popup(); - for (int i = 0; i < modes.size(); i++) { - mode_popup->add_radio_check_item(modes[i]->get_name(), i); - } - mode_popup->add_separator(); - mode_popup->add_check_item(ETR("Colorized Sliders"), MODE_MAX); - mode_popup->set_item_checked(current_mode, true); - mode_popup->set_item_checked(MODE_MAX + 1, true); - mode_popup->connect(SceneStringName(id_pressed), callable_mp(this, &ColorPicker::_set_mode_popup_value)); - VBoxContainer *vbl = memnew(VBoxContainer); - real_vbox->add_child(vbl); - - VBoxContainer *vbr = memnew(VBoxContainer); - - real_vbox->add_child(vbr); - vbr->set_h_size_flags(SIZE_EXPAND_FILL); + PanelContainer *sliders_panel = memnew(PanelContainer); + sliders_panel->set_theme_type_variation("PickerSlidersPanel"); + sliders_panel->set_h_size_flags(SIZE_EXPAND_FILL); + sliders_vbc->add_child(sliders_panel); slider_gc = memnew(GridContainer); - - vbr->add_child(slider_gc); - slider_gc->set_h_size_flags(SIZE_EXPAND_FILL); + slider_gc->set_theme_type_variation("ColorPickerGrid"); slider_gc->set_columns(3); + sliders_panel->add_child(slider_gc); + Ref style_box_empty; for (int i = 0; i < SLIDER_COUNT + 1; i++) { - create_slider(slider_gc, i); - } + Label *lbl = memnew(Label); + lbl->set_v_size_flags(SIZE_SHRINK_CENTER); + lbl->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + lbl->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); + slider_gc->add_child(lbl); + + HSlider *slider = memnew(HSlider); + slider->set_theme_type_variation("PickerHSlider"); + slider->set_v_size_flags(SIZE_SHRINK_CENTER); + slider->set_focus_mode(FOCUS_NONE); + slider_gc->add_child(slider); + + if (colorize_sliders) { + if (style_box_empty.is_null()) { + style_box_empty.instantiate(); + } + slider->add_theme_style_override("slider", style_box_empty); + } + + SpinBox *val = memnew(SpinBox); + slider->share(val); + val->set_select_all_on_focus(true); + slider_gc->add_child(val); + + LineEdit *vle = val->get_line_edit(); + vle->set_theme_type_variation("PickerLineEdit"); + vle->connect(SceneStringName(text_changed), callable_mp(this, &ColorPicker::_text_changed)); + vle->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_line_edit_input)); + vle->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); - alpha_label->set_text("A"); + val->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input)); + + slider->set_h_size_flags(SIZE_EXPAND_FILL); + + slider->connect("drag_started", callable_mp(this, &ColorPicker::_slider_drag_started)); + slider->connect(SceneStringName(value_changed), callable_mp(this, &ColorPicker::_slider_value_changed).unbind(1)); + slider->connect("drag_ended", callable_mp(this, &ColorPicker::_slider_drag_ended).unbind(1)); + slider->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_slider_draw).bind(i)); + slider->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_slider_or_spin_input)); + + if (i < SLIDER_COUNT) { + sliders[i] = slider; + values[i] = val; + labels[i] = lbl; + } else { + alpha_slider = slider; + alpha_value = val; + alpha_label = lbl; + alpha_label->set_text("A"); + } + } hex_hbc = memnew(HBoxContainer); + hex_hbc->set_theme_type_variation("ColorPickerHBox"); hex_hbc->set_alignment(ALIGNMENT_BEGIN); - vbr->add_child(hex_hbc); - - hex_hbc->add_child(memnew(Label(ETR("Hex")))); + add_child(hex_hbc, false, INTERNAL_MODE_FRONT); text_type = memnew(Button); + text_type->set_theme_type_variation("PickerButton"); + text_type->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); + text_type->set_size_mode(BaseButton::SIZE_MODE_FIT_HEIGHT); hex_hbc->add_child(text_type); - text_type->set_text("#"); + text_type->set_button_icon(theme_cache.hex_icon); text_type->set_tooltip_text(RTR("Switch between hexadecimal and code values.")); - if (Engine::get_singleton()->is_editor_hint()) { - text_type->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_text_type_toggled)); - } else { - text_type->set_flat(true); - text_type->set_mouse_filter(MOUSE_FILTER_IGNORE); - } + text_type->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_text_type_toggled)); c_text = memnew(LineEdit); + c_text->set_theme_type_variation("PickerLineEdit"); hex_hbc->add_child(c_text); c_text->set_h_size_flags(SIZE_EXPAND_FILL); c_text->set_select_all_on_focus(true); c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\").")); c_text->set_placeholder(ETR("Hex code or named color")); - c_text->connect(SceneStringName(text_submitted), callable_mp(this, &ColorPicker::_html_submitted)); + c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted)); c_text->connect(SceneStringName(text_changed), callable_mp(this, &ColorPicker::_text_changed)); c_text->connect(SceneStringName(focus_exited), callable_mp(this, &ColorPicker::_html_focus_exit)); wheel_edit = memnew(AspectRatioContainer); wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL); - wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL); hb_edit->add_child(wheel_edit); wheel_mat.instantiate(); wheel_mat->set_shader(wheel_shader); + wheel_radius = 0.15; + float _radius = CLAMP((1.0 - wheel_radius) * 0.5, 0.25, 0.45); + wheel_mat->set_shader_parameter("wheel_radius", _radius); + circle_mat.instantiate(); circle_mat->set_shader(circle_shader); wheel_margin = memnew(MarginContainer); - wheel_margin->add_theme_constant_override("margin_bottom", 8); + wheel_margin->set_margin_all(0); wheel_edit->add_child(wheel_margin); wheel = memnew(Control); @@ -2320,76 +1608,43 @@ ColorPicker::ColorPicker() { wheel_uv->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(0, wheel_uv)); w_edit = memnew(Control); + w_edit->set_draw_behind_parent(true); hb_edit->add_child(w_edit); w_edit->set_h_size_flags(SIZE_FILL); w_edit->set_v_size_flags(SIZE_EXPAND_FILL); w_edit->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_w_input)); w_edit->connect(SceneStringName(draw), callable_mp(this, &ColorPicker::_hsv_draw).bind(1, w_edit)); + swatches_foldable = memnew(FoldableContainer(ETR("Swatches"))); + swatches_foldable->set_focus_mode(FOCUS_NONE); + swatches_foldable->set_theme_type_variation("SwatchesFoldableContainer"); + swatches_foldable->set_expanded(false); + swatches_foldable->add_button(theme_cache.add_preset); + swatches_foldable->set_button_hidden(0, true); + swatches_foldable->set_button_tooltip(0, ETR("Add current color as a preset.")); + swatches_foldable->connect("folding_changed", callable_mp(this, &ColorPicker::_swatches_folding_changed)); + swatches_foldable->connect("button_pressed", callable_mp(this, &ColorPicker::_add_swatch_button_pressed).unbind(2)); + + ScrollContainer *swatches_scroll = memnew(ScrollContainer); + swatches_scroll->set_ignore_scroll_bar_min_size(false); + swatches_scroll->add_theme_constant_override("v_separation", 2); + swatches_scroll->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); + swatches_foldable->add_child(swatches_scroll); + + swatches_hbc = memnew(HBoxContainer); + swatches_hbc->set_theme_type_variation("ColorPickerHBox"); + swatches_hbc->set_h_size_flags(SIZE_EXPAND_FILL); + swatches_hbc->set_v_size_flags(SIZE_EXPAND_FILL); + swatches_scroll->add_child(swatches_hbc); + + swatches_group.instantiate(); + add_child(swatches_foldable, false, INTERNAL_MODE_FRONT); + callable_mp(this, &ColorPicker::update_swatches).call_deferred(); + _update_controls(); updating = false; - preset_container = memnew(GridContainer); - preset_container->set_h_size_flags(SIZE_EXPAND_FILL); - preset_container->set_columns(PRESET_COLUMN_COUNT); - preset_container->hide(); - - preset_group.instantiate(); - - HBoxContainer *palette_box = memnew(HBoxContainer); - palette_box->set_h_size_flags(SIZE_EXPAND_FILL); - real_vbox->add_child(palette_box); - - btn_preset = memnew(Button); - btn_preset->set_text("Swatches"); - btn_preset->set_flat(true); - btn_preset->set_toggle_mode(true); - btn_preset->set_focus_mode(FOCUS_NONE); - btn_preset->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT); - btn_preset->connect(SceneStringName(toggled), callable_mp(this, &ColorPicker::_show_hide_preset).bind(btn_preset, preset_container)); - palette_box->add_child(btn_preset); - - HBoxContainer *padding_box = memnew(HBoxContainer); - padding_box->set_h_size_flags(SIZE_EXPAND_FILL); - palette_box->add_child(padding_box); - - menu_btn = memnew(Button); - menu_btn->set_flat(true); - menu_btn->set_tooltip_text(ETR("Show all options available.")); - menu_btn->set_focus_mode(FOCUS_NONE); - menu_btn->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_update_menu)); - palette_box->add_child(menu_btn); - - palette_name = memnew(Label); - palette_name->hide(); - palette_name->set_mouse_filter(MOUSE_FILTER_PASS); - real_vbox->add_child(palette_name); - - real_vbox->add_child(preset_container); - - recent_preset_hbc = memnew(HBoxContainer); - recent_preset_hbc->set_v_size_flags(SIZE_SHRINK_BEGIN); - recent_preset_hbc->hide(); - - recent_preset_group.instantiate(); - - btn_recent_preset = memnew(Button(ETR("Recent Colors"))); - btn_recent_preset->set_flat(true); - btn_recent_preset->set_toggle_mode(true); - btn_recent_preset->set_focus_mode(FOCUS_NONE); - btn_recent_preset->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT); - btn_recent_preset->connect(SceneStringName(toggled), callable_mp(this, &ColorPicker::_show_hide_preset).bind(btn_recent_preset, recent_preset_hbc)); - real_vbox->add_child(btn_recent_preset); - - real_vbox->add_child(recent_preset_hbc); - set_pick_color(Color(1, 1, 1)); - - btn_add_preset = memnew(Button); - btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); - btn_add_preset->set_tooltip_text(ETR("Add current color as a preset.")); - btn_add_preset->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_add_preset_pressed)); - preset_container->add_child(btn_add_preset); } ColorPicker::~ColorPicker() { @@ -2398,7 +1653,7 @@ ColorPicker::~ColorPicker() { } } -///////////////// +///////////////////////////////////////////////////////// void ColorPickerPopupPanel::_input_from_window(const Ref &p_event) { if (p_event->is_action_pressed(SNAME("ui_accept"), false, true)) { @@ -2407,25 +1662,23 @@ void ColorPickerPopupPanel::_input_from_window(const Ref &p_event) { PopupPanel::_input_from_window(p_event); } -///////////////// +///////////////////////////////////////////////////////// void ColorPickerButton::_about_to_popup() { set_pressed(true); if (picker) { - picker->set_old_color(color); + picker->set_old_color(get_color()); } } void ColorPickerButton::_color_changed(const Color &p_color) { - color = p_color; - queue_redraw(); - emit_signal(SNAME("color_changed"), color); + set_color(p_color); } void ColorPickerButton::_modal_closed() { if (Input::get_singleton()->is_action_just_pressed(SNAME("ui_cancel"))) { set_pick_color(picker->get_old_color()); - emit_signal(SNAME("color_changed"), color); + emit_signal(SNAME("color_changed"), get_color()); } emit_signal(SNAME("popup_closed")); set_pressed(false); @@ -2438,8 +1691,6 @@ void ColorPickerButton::pressed() { float viewport_height = get_viewport_rect().size.y; popup->reset_size(); - picker->_update_presets(); - picker->_update_recent_presets(); // Determine in which direction to show the popup. By default popup horizontally centered below the button. // But if the popup doesn't fit below and the button is in the bottom half of the viewport, show above. @@ -2452,52 +1703,18 @@ void ColorPickerButton::pressed() { float v_offset = show_above ? -minsize.y : get_size().y; popup->set_position(get_screen_position() + Vector2(h_offset, v_offset)); popup->popup(); - if (DisplayServer::get_singleton()->has_hardware_keyboard()) { - picker->set_focus_on_line_edit(); - } -} - -void ColorPickerButton::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_DRAW: { - const Rect2 r = Rect2(theme_cache.normal_style->get_offset(), get_size() - theme_cache.normal_style->get_minimum_size()); - draw_texture_rect(theme_cache.background_icon, r, true); - draw_rect(r, color); - - if (color.r > 1 || color.g > 1 || color.b > 1) { - // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - draw_texture(theme_cache.overbright_indicator, theme_cache.normal_style->get_offset()); - } - } break; - - case NOTIFICATION_WM_CLOSE_REQUEST: { - if (popup) { - popup->hide(); - } - } break; - - case NOTIFICATION_VISIBILITY_CHANGED: { - if (popup && !is_visible_in_tree()) { - popup->hide(); - } - } break; - } + picker->set_focus_on_line_edit(); } void ColorPickerButton::set_pick_color(const Color &p_color) { - if (color == p_color) { - return; - } - color = p_color; + set_color_no_signal(p_color); if (picker) { picker->set_pick_color(p_color); } - - queue_redraw(); } Color ColorPickerButton::get_pick_color() const { - return color; + return get_color(); } void ColorPickerButton::set_edit_alpha(bool p_show) { @@ -2527,6 +1744,7 @@ PopupPanel *ColorPickerButton::get_popup() { void ColorPickerButton::_update_picker() { if (!picker) { popup = memnew(ColorPickerPopupPanel); + popup->add_theme_style_override("panel", theme_cache.popup_panel_style); popup->set_wrap_controls(true); picker = memnew(ColorPicker); picker->set_anchors_and_offsets_preset(PRESET_FULL_RECT); @@ -2536,13 +1754,35 @@ void ColorPickerButton::_update_picker() { popup->connect("about_to_popup", callable_mp(this, &ColorPickerButton::_about_to_popup)); popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed)); picker->connect(SceneStringName(minimum_size_changed), callable_mp((Window *)popup, &Window::reset_size)); - picker->set_pick_color(color); + picker->set_pick_color(get_color()); picker->set_edit_alpha(edit_alpha); picker->set_display_old_color(true); emit_signal(SNAME("picker_created")); } } +void ColorPickerButton::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_WM_CLOSE_REQUEST: { + if (popup) { + popup->hide(); + } + } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + if (popup && !is_visible_in_tree()) { + popup->hide(); + } + } break; + + case NOTIFICATION_THEME_CHANGED: { + if (popup) { + popup->add_theme_style_override("panel", theme_cache.popup_panel_style); + } + } break; + } +} + void ColorPickerButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPickerButton::set_pick_color); ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPickerButton::get_pick_color); @@ -2552,94 +1792,37 @@ void ColorPickerButton::_bind_methods() { ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha); ClassDB::bind_method(D_METHOD("_about_to_popup"), &ColorPickerButton::_about_to_popup); - ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); + ADD_SIGNAL(MethodInfo("popup_closed")); ADD_SIGNAL(MethodInfo("picker_created")); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); - BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ColorPickerButton, normal_style, "normal"); - BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPickerButton, background_icon, "bg"); - BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_ICON, ColorPickerButton, overbright_indicator, "overbright_indicator", "ColorPicker"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ColorPickerButton, popup_panel_style, "popup_panel"); } -ColorPickerButton::ColorPickerButton(const String &p_text) : - Button(p_text) { +ColorPickerButton::ColorPickerButton() { set_toggle_mode(true); } -///////////////// - -void ColorPresetButton::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_DRAW: { - const Rect2 r = Rect2(Point2(0, 0), get_size()); - Ref sb_raw = theme_cache.foreground_style->duplicate(); - Ref sb_flat = sb_raw; - Ref sb_texture = sb_raw; - - if (sb_flat.is_valid()) { - sb_flat->set_border_width(SIDE_BOTTOM, 2); - if (get_draw_mode() == DRAW_PRESSED || get_draw_mode() == DRAW_HOVER_PRESSED) { - sb_flat->set_border_color(Color(1, 1, 1, 1)); - } else { - sb_flat->set_border_color(Color(0, 0, 0, 1)); - } - - if (preset_color.a < 1) { - // Draw a background pattern when the color is transparent. - sb_flat->set_bg_color(Color(1, 1, 1)); - sb_flat->draw(get_canvas_item(), r); - - Rect2 bg_texture_rect = r.grow_side(SIDE_LEFT, -sb_flat->get_margin(SIDE_LEFT)); - bg_texture_rect = bg_texture_rect.grow_side(SIDE_RIGHT, -sb_flat->get_margin(SIDE_RIGHT)); - bg_texture_rect = bg_texture_rect.grow_side(SIDE_TOP, -sb_flat->get_margin(SIDE_TOP)); - bg_texture_rect = bg_texture_rect.grow_side(SIDE_BOTTOM, -sb_flat->get_margin(SIDE_BOTTOM)); - - draw_texture_rect(theme_cache.background_icon, bg_texture_rect, true); - sb_flat->set_bg_color(preset_color); - } - sb_flat->set_bg_color(preset_color); - sb_flat->draw(get_canvas_item(), r); - } else if (sb_texture.is_valid()) { - if (preset_color.a < 1) { - // Draw a background pattern when the color is transparent. - bool use_tile_texture = (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE) || (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE_FIT); - draw_texture_rect(theme_cache.background_icon, r, use_tile_texture); - } - sb_texture->set_modulate(preset_color); - sb_texture->draw(get_canvas_item(), r); - } else { - WARN_PRINT("Unsupported StyleBox used for ColorPresetButton. Use StyleBoxFlat or StyleBoxTexture instead."); - } - if (preset_color.r > 1 || preset_color.g > 1 || preset_color.b > 1) { - // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - draw_texture(theme_cache.overbright_indicator, Vector2(0, 0)); - } - - } break; +void SwatchButton::gui_input(const Ref &p_event) { + Ref b = p_event; + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { + emit_signal(SNAME("right_click_pressed"), get_index()); } + BaseButton::gui_input(p_event); } -void ColorPresetButton::set_preset_color(const Color &p_color) { - preset_color = p_color; -} - -Color ColorPresetButton::get_preset_color() const { - return preset_color; +void SwatchButton::toggled(bool p_toggled_on) { + if (p_toggled_on) { + emit_signal(SNAME("color_selected"), get_color()); + } } -void ColorPresetButton::_bind_methods() { - BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ColorPresetButton, foreground_style, "preset_fg"); - BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPresetButton, background_icon, "preset_bg"); - BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPresetButton, overbright_indicator); +void SwatchButton::_bind_methods() { + ADD_SIGNAL(MethodInfo("color_selected", PropertyInfo(Variant::COLOR, "color"))); + ADD_SIGNAL(MethodInfo("right_click_pressed", PropertyInfo(Variant::INT, "index"))); } -ColorPresetButton::ColorPresetButton(Color p_color, int p_size) { - preset_color = p_color; +SwatchButton::SwatchButton() { set_toggle_mode(true); - set_custom_minimum_size(Size2(p_size, p_size)); -} - -ColorPresetButton::~ColorPresetButton() { } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 829263fbf554..f5cae25364fa 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -28,55 +28,46 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +/**************************************************************************/ +/* PIXEL ENGINE */ +/* Copyright (c) 2024-present Pixel Engine contributors (see AUTHORS.md). */ +/**************************************************************************/ +/* NOTICE: */ +/* This file contains modifications and additions specific to the Pixel */ +/* Engine project. While these changes are licensed under the MIT license */ +/* for compatibility, we request proper attribution if reused in any */ +/* derivative works, including meta-forks. */ +/**************************************************************************/ + #ifndef COLOR_PICKER_H #define COLOR_PICKER_H #include "scene/gui/box_container.h" -#include "scene/gui/button.h" +#include "scene/gui/color_button.h" #include "scene/gui/popup.h" class AspectRatioContainer; +class Button; class ColorMode; -class ColorPickerShape; +class ColorModeRGB; +class ColorModeHSV; +class ColorModeRAW; +class ColorModeOKHSL; +class Control; +class FoldableContainer; class GridContainer; class HSlider; class Label; class LineEdit; -class MarginContainer; class MenuButton; -class OptionButton; +class PanelContainer; class PopupMenu; class SpinBox; -class StyleBoxFlat; +class StyleBox; class TextureRect; -class FileDialog; - -class ColorPresetButton : public BaseButton { - GDCLASS(ColorPresetButton, BaseButton); - - Color preset_color; - - struct ThemeCache { - Ref foreground_style; - - Ref background_icon; - Ref overbright_indicator; - } theme_cache; - -protected: - void _notification(int); - static void _bind_methods(); - -public: - void set_preset_color(const Color &p_color); - Color get_preset_color() const; - - ColorPresetButton(Color p_color, int p_size); - ~ColorPresetButton(); -}; class ColorPicker : public VBoxContainer { - GDCLASS(ColorPicker, VBoxContainer); + GDCLASS(ColorPicker, VBoxContainer) // These classes poke into theme items for their internal logic. friend class ColorModeRGB; @@ -104,49 +95,25 @@ class ColorPicker : public VBoxContainer { SHAPE_MAX }; - static const int SLIDER_COUNT = 4; + static const int SLIDER_COUNT = 3; + static PackedColorArray swatches; private: - enum class MenuOption { - MENU_SAVE, - MENU_SAVE_AS, - MENU_LOAD, - MENU_QUICKLOAD, - MENU_CLEAR, - }; - - static inline Ref wheel_shader; - static inline Ref circle_shader; - static inline Ref circle_ok_color_shader; - static inline List preset_cache; - static inline List recent_preset_cache; - -#ifdef TOOLS_ENABLED - Object *editor_settings = nullptr; -#endif + static Ref wheel_shader; + static Ref circle_shader; + static Ref circle_ok_color_shader; int current_slider_count = SLIDER_COUNT; - static const int MODE_BUTTON_COUNT = 3; - - bool slider_theme_modified = true; + static const int MODE_BUTTON_COUNT = 4; Vector modes; Popup *picker_window = nullptr; - TextureRect *picker_texture_zoom = nullptr; - Panel *picker_preview = nullptr; - Panel *picker_preview_color = nullptr; - Ref picker_preview_style_box; - Ref picker_preview_style_box_color; - - // Legacy color picking. + bool is_legacy_picking = false; TextureRect *picker_texture_rect = nullptr; - Color picker_color; - FileDialog *file_dialog = nullptr; - Button *menu_btn = nullptr; - PopupMenu *options_menu = nullptr; + Color prev_pick_color; - MarginContainer *internal_margin = nullptr; + HBoxContainer *hb_edit = nullptr; Control *uv_edit = nullptr; Control *w_edit = nullptr; AspectRatioContainer *wheel_edit = nullptr; @@ -156,14 +123,7 @@ class ColorPicker : public VBoxContainer { Control *wheel = nullptr; Control *wheel_uv = nullptr; TextureRect *sample = nullptr; - GridContainer *preset_container = nullptr; - HBoxContainer *recent_preset_hbc = nullptr; - Button *btn_add_preset = nullptr; Button *btn_pick = nullptr; - Label *palette_name = nullptr; - String palette_path; - Button *btn_preset = nullptr; - Button *btn_recent_preset = nullptr; PopupMenu *shape_popup = nullptr; PopupMenu *mode_popup = nullptr; MenuButton *btn_shape = nullptr; @@ -171,28 +131,19 @@ class ColorPicker : public VBoxContainer { HBoxContainer *sample_hbc = nullptr; GridContainer *slider_gc = nullptr; HBoxContainer *hex_hbc = nullptr; - MenuButton *btn_mode = nullptr; + VBoxContainer *sliders_vbc = nullptr; Button *mode_btns[MODE_BUTTON_COUNT]; - Ref mode_group = nullptr; - ColorPresetButton *selected_recent_preset = nullptr; - Ref preset_group; - Ref recent_preset_group; -#ifdef TOOLS_ENABLED - Callable quick_open_callback; - Callable palette_saved_callback; -#endif // TOOLS_ENABLED - - OptionButton *mode_option_button = nullptr; - HSlider *sliders[SLIDER_COUNT]; SpinBox *values[SLIDER_COUNT]; Label *labels[SLIDER_COUNT]; Button *text_type = nullptr; LineEdit *c_text = nullptr; - HSlider *alpha_slider = nullptr; SpinBox *alpha_value = nullptr; Label *alpha_label = nullptr; + FoldableContainer *swatches_foldable = nullptr; + HBoxContainer *swatches_hbc = nullptr; + Ref swatches_group; bool edit_alpha = true; Size2i ms; @@ -201,27 +152,21 @@ class ColorPicker : public VBoxContainer { ColorModeType current_mode = MODE_RGB; bool colorize_sliders = true; - const int PRESET_COLUMN_COUNT = 9; - int prev_preset_size = 0; - int prev_rencet_preset_size = 0; - List presets; - List recent_presets; - Color color; Color old_color; - bool is_picking_color = false; bool display_old_color = false; bool deferred_mode_enabled = false; bool updating = true; bool changing_color = false; bool spinning = false; - bool can_add_swatches = true; - bool presets_visible = true; bool color_modes_visible = true; bool sampler_visible = true; bool sliders_visible = true; bool hex_visible = true; + bool swatches_visible = true; + bool can_add_swatches = true; + bool can_pick_screen_color = true; bool line_edit_mouse_release = false; bool text_changed = false; bool currently_dragging = false; @@ -229,26 +174,17 @@ class ColorPicker : public VBoxContainer { float h = 0.0; float s = 0.0; float v = 0.0; - - float ok_hsl_h = 0.0; - float ok_hsl_s = 0.0; - float ok_hsl_l = 0.0; - + float wheel_radius = 0.0; Color last_color; struct ThemeCache { - float base_scale = 1.0; - - int content_margin = 0; - int label_width = 0; - int sv_height = 0; int sv_width = 0; int h_width = 0; + int sample_height = 0; + int expand_shape = 0; + int swatch_size = 0; - bool center_slider_grabbers = true; - - Ref menu_option; Ref screen_picker; Ref expanded_arrow; Ref folded_arrow; @@ -258,26 +194,20 @@ class ColorPicker : public VBoxContainer { Ref shape_rect_wheel; Ref shape_circle; - Ref bar_arrow; Ref sample_bg; Ref sample_revert; Ref overbright_indicator; Ref picker_cursor; + Ref picker_cursor_bg; Ref color_hue; Ref color_okhsl_hue; - - /* Mode buttons */ - Ref mode_button_normal; - Ref mode_button_pressed; - Ref mode_button_hover; + Ref hex_icon; + Ref hex_code_icon; } theme_cache; void _copy_color_to_hsv(); void _copy_hsv_to_color(); - PickerShapeType _get_actual_shape() const; - void create_slider(GridContainer *gc, int idx); - void _reset_sliders_theme(); void _html_submitted(const String &p_html); void _slider_drag_started(); void _slider_value_changed(); @@ -295,36 +225,15 @@ class ColorPicker : public VBoxContainer { void _w_input(const Ref &p_event); void _slider_or_spin_input(const Ref &p_event); void _line_edit_input(const Ref &p_event); - void _preset_input(const Ref &p_event, const Color &p_color); - void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset); void _text_changed(const String &p_new_text); - void _add_preset_pressed(); void _html_focus_exit(); void _pick_button_pressed(); - void _target_gui_input(const Ref &p_event); - void _pick_finished(); - void _update_menu_items(); - void _update_menu(); - void _options_menu_cbk(int p_which); - - // Legacy color picking. - void _pick_button_pressed_legacy(); - void _picker_texture_input(const Ref &p_event); - - inline int _get_preset_size(); - void _add_preset_button(int p_size, const Color &p_color); - void _add_recent_preset_button(int p_size, const Color &p_color); - void _save_palette(bool p_is_save_as); - void _load_palette(); - - void _show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_preset, Container *p_preset_container); - void _update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset); - - void _set_mode_popup_value(ColorModeType p_mode); - - Variant _get_drag_data_fw(const Point2 &p_point, Control *p_from_control); - bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const; - void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control); + void _picking_finished(); + void _swatches_folding_changed(bool p_folded); + void _add_swatch_button_pressed(); + void _on_swatch_button_pressed(const Color &p_color); + void _on_swatch_button_right_pressed(int p_index); + void _update_selected_swatch(); protected: virtual void _update_theme_item_cache() override; @@ -333,11 +242,6 @@ class ColorPicker : public VBoxContainer { static void _bind_methods(); public: -#ifdef TOOLS_ENABLED - void set_editor_settings(Object *p_editor_settings); - void set_quick_open_callback(const Callable &p_file_selected); - void set_palette_saved_callback(const Callable &p_palette_saved); -#endif HSlider *get_slider(int idx); Vector get_active_slider_values(); @@ -354,8 +258,9 @@ class ColorPicker : public VBoxContainer { Color get_pick_color() const; void set_old_color(const Color &p_color); Color get_old_color() const; - void _quick_open_palette_file_selected(const String &p_path); - void _palette_file_selected(const String &p_path); + + void set_wheel_radius(float p_wheel_radius); + float get_wheel_radius() const; void set_display_old_color(bool p_enabled); bool is_displaying_old_color() const; @@ -363,18 +268,6 @@ class ColorPicker : public VBoxContainer { void set_picker_shape(PickerShapeType p_shape); PickerShapeType get_picker_shape() const; - void add_preset(const Color &p_color); - void add_recent_preset(const Color &p_color); - void erase_preset(const Color &p_color); - void erase_recent_preset(const Color &p_color); - PackedColorArray get_presets() const; - PackedColorArray get_recent_presets() const; - void _update_presets(); - void _update_recent_presets(); - - void _select_from_preset_container(const Color &p_color); - bool _select_from_recent_preset_hbc(const Color &p_color); - void set_color_mode(ColorModeType p_mode); ColorModeType get_color_mode() const; @@ -384,18 +277,15 @@ class ColorPicker : public VBoxContainer { void set_deferred_mode(bool p_enabled); bool is_deferred_mode() const; - void set_can_add_swatches(bool p_enabled); - bool are_swatches_enabled() const; - - void set_presets_visible(bool p_visible); - bool are_presets_visible() const; - void set_modes_visible(bool p_visible); bool are_modes_visible() const; void set_sampler_visible(bool p_visible); bool is_sampler_visible() const; + void set_can_pick_screen_color(bool p_enabled); + bool get_can_pick_screen_color() const; + void set_sliders_visible(bool p_visible); bool are_sliders_visible() const; @@ -404,16 +294,39 @@ class ColorPicker : public VBoxContainer { void set_focus_on_line_edit(); + void set_swatches(const PackedColorArray &p_swatches); + PackedColorArray get_swatches() const; + + void set_swatches_visible(bool p_visible); + bool is_swatches_visible() const; + + void add_swatch_color(const Color &p_color); + void remove_swatch_color(const Color &p_color); + void remove_swatch_color_by_index(int p_index); + + void set_can_add_swatches(bool p_enabled); + bool get_can_add_swatches() const; + + void clear_swatches(); + void update_swatches(); + ColorPicker(); ~ColorPicker(); }; +VARIANT_ENUM_CAST(ColorPicker::PickerShapeType); +VARIANT_ENUM_CAST(ColorPicker::ColorModeType); + +///////////////////////////////////////////////////////// + class ColorPickerPopupPanel : public PopupPanel { virtual void _input_from_window(const Ref &p_event) override; }; -class ColorPickerButton : public Button { - GDCLASS(ColorPickerButton, Button); +///////////////////////////////////////////////////////// + +class ColorPickerButton : public ColorButton { + GDCLASS(ColorPickerButton, ColorButton) // Initialization is now done deferred, // this improves performance in the inspector as the color picker @@ -421,14 +334,10 @@ class ColorPickerButton : public Button { PopupPanel *popup = nullptr; ColorPicker *picker = nullptr; - Color color; bool edit_alpha = true; struct ThemeCache { - Ref normal_style; - Ref background_icon; - - Ref overbright_indicator; + Ref popup_panel_style; } theme_cache; void _about_to_popup(); @@ -453,10 +362,19 @@ class ColorPickerButton : public Button { ColorPicker *get_picker(); PopupPanel *get_popup(); - ColorPickerButton(const String &p_text = String()); + ColorPickerButton(); }; -VARIANT_ENUM_CAST(ColorPicker::PickerShapeType); -VARIANT_ENUM_CAST(ColorPicker::ColorModeType); +class SwatchButton : public ColorButton { + GDCLASS(SwatchButton, ColorButton) + +protected: + virtual void gui_input(const Ref &p_event) override; + virtual void toggled(bool p_toggled_on) override; + static void _bind_methods(); + +public: + SwatchButton(); +}; #endif // COLOR_PICKER_H