2
0
Эх сурвалжийг харах

Improve Colorpicker presets

Hendrik Brucker 3 жил өмнө
parent
commit
365486543d

+ 8 - 0
editor/editor_themes.cpp

@@ -1279,6 +1279,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 
 	theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
 
+	// ColorPresetButton
+	Ref<StyleBoxFlat> preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2);
+
+	preset_sb->set_anti_aliased(false);
+	theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb);
+	theme->set_icon("preset_bg_icon", "ColorPresetButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
+	theme->set_icon("overbright_indicator", "ColorPresetButton", theme->get_icon("OverbrightIndicator", "EditorIcons"));
+
 	// Information on 3D viewport
 	Ref<StyleBoxFlat> style_info_3d_viewport = style_default->duplicate();
 	style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5));

+ 121 - 65
scene/gui/color_picker.cpp

@@ -46,13 +46,13 @@ void ColorPicker::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
 			btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
-			bt_add_preset->set_icon(get_icon("add_preset"));
-
+			btn_add_preset->set_icon(get_icon("add_preset"));
+			_update_presets();
 			_update_controls();
 		} break;
 		case NOTIFICATION_ENTER_TREE: {
 			btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
-			bt_add_preset->set_icon(get_icon("add_preset"));
+			btn_add_preset->set_icon(get_icon("add_preset"));
 
 			_update_controls();
 			_update_color();
@@ -69,7 +69,6 @@ void ColorPicker::_notification(int p_what) {
 				for (int i = 0; i < preset_cache.size(); i++) {
 					presets.push_back(preset_cache[i]);
 				}
-				preset->update();
 			}
 #endif
 		} break;
@@ -255,19 +254,15 @@ void ColorPicker::_update_color(bool p_update_sliders) {
 }
 
 void ColorPicker::_update_presets() {
-	presets_per_row = 10;
-	Size2 size = bt_add_preset->get_size();
-	Size2 preset_size = Size2(MIN(size.width * presets.size(), presets_per_row * size.width), size.height * (Math::ceil((float)presets.size() / presets_per_row)));
-	preset->set_custom_minimum_size(preset_size);
-	preset_container->set_custom_minimum_size(preset_size);
-	preset->draw_rect(Rect2(Point2(), preset_size), Color(1, 1, 1, 0));
-
-	for (int i = 0; i < presets.size(); i++) {
-		int x = (i % presets_per_row) * size.width;
-		int y = (Math::floor((float)i / presets_per_row)) * size.height;
-		preset->draw_rect(Rect2(Point2(x, y), size), presets[i]);
+	// Only load preset buttons when the only child is the add-preset button.
+	int preset_size = _get_preset_size();
+	btn_add_preset->set_custom_minimum_size(Size2(preset_size, preset_size));
+	if (preset_container->get_child_count() == 1) {
+		for (int i = 0; i < preset_cache.size(); i++) {
+			_add_preset_button(preset_size, preset_cache[i]);
+		}
+		_notification(NOTIFICATION_VISIBILITY_CHANGED);
 	}
-	_notification(NOTIFICATION_VISIBILITY_CHANGED);
 }
 
 void ColorPicker::_text_type_toggled() {
@@ -290,14 +285,38 @@ Color ColorPicker::get_pick_color() const {
 	return color;
 }
 
+inline int ColorPicker::_get_preset_size() {
+	return (int(get_size().width) - (preset_container->get_constant("hseparation") * (preset_column_count - 1))) / preset_column_count;
+}
+
+void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
+	ColorPresetButton *btn_preset = memnew(ColorPresetButton(p_color));
+	btn_preset->set_preset_color(p_color);
+	btn_preset->set_custom_minimum_size(Size2(p_size, p_size));
+	btn_preset->connect("gui_input", this, "_preset_input", varray(p_color));
+	btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
+	preset_container->add_child(btn_preset);
+}
+
 void ColorPicker::add_preset(const Color &p_color) {
 	if (presets.find(p_color)) {
 		presets.move_to_back(presets.find(p_color));
+
+		// Find button to move to the end.
+		for (int i = 1; i < preset_container->get_child_count(); i++) {
+			ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
+			if (current_btn && p_color == current_btn->get_preset_color()) {
+				preset_container->move_child(current_btn, preset_container->get_child_count() - 1);
+				break;
+			}
+		}
 	} else {
 		presets.push_back(p_color);
 		preset_cache.push_back(p_color);
+
+		_add_preset_button(_get_preset_size(), p_color);
+		_notification(NOTIFICATION_VISIBILITY_CHANGED);
 	}
-	preset->update();
 
 #ifdef TOOLS_ENABLED
 	if (Engine::get_singleton()->is_editor_hint()) {
@@ -311,7 +330,15 @@ void ColorPicker::erase_preset(const Color &p_color) {
 	if (presets.find(p_color)) {
 		presets.erase(presets.find(p_color));
 		preset_cache.erase(preset_cache.find(p_color));
-		preset->update();
+
+		// Find preset button to remove.
+		for (int i = 1; i < preset_container->get_child_count(); i++) {
+			ColorPresetButton *current_btn = Object::cast_to<ColorPresetButton>(preset_container->get_child(i));
+			if (current_btn && p_color == current_btn->get_preset_color()) {
+				current_btn->queue_delete();
+				break;
+			}
+		}
 
 #ifdef TOOLS_ENABLED
 		if (Engine::get_singleton()->is_editor_hint()) {
@@ -585,42 +612,18 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
 	}
 }
 
-void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
+void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_color) {
 	Ref<InputEventMouseButton> bev = p_event;
 
 	if (bev.is_valid()) {
-		int index = 0;
 		if (bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) {
-			for (int i = 0; i < presets.size(); i++) {
-				int x = (i % presets_per_row) * bt_add_preset->get_size().x;
-				int y = (Math::floor((float)i / presets_per_row)) * bt_add_preset->get_size().y;
-				if (bev->get_position().x > x && bev->get_position().x < x + preset->get_size().x && bev->get_position().y > y && bev->get_position().y < y + preset->get_size().y) {
-					index = i;
-				}
-			}
-			set_pick_color(presets[index]);
+			set_pick_color(p_color);
 			_update_color();
-			emit_signal("color_changed", color);
+			emit_signal("color_changed", p_color);
 		} else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT && presets_enabled) {
-			index = bev->get_position().x / (preset->get_size().x / presets.size());
-			Color clicked_preset = presets[index];
-			erase_preset(clicked_preset);
-			emit_signal("preset_removed", clicked_preset);
-			bt_add_preset->show();
-		}
-	}
-
-	Ref<InputEventMouseMotion> mev = p_event;
-
-	if (mev.is_valid()) {
-		int index = mev->get_position().x * presets.size();
-		if (preset->get_size().x != 0) {
-			index /= preset->get_size().x;
+			erase_preset(p_color);
+			emit_signal("preset_removed", p_color);
 		}
-		if (index < 0 || index >= presets.size()) {
-			return;
-		}
-		preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Set color\nRMB: Remove preset"), presets[index].to_html(presets[index].a < 1)));
 	}
 }
 
@@ -715,11 +718,11 @@ void ColorPicker::_html_focus_exit() {
 void ColorPicker::set_presets_enabled(bool p_enabled) {
 	presets_enabled = p_enabled;
 	if (!p_enabled) {
-		bt_add_preset->set_disabled(true);
-		bt_add_preset->set_focus_mode(FOCUS_NONE);
+		btn_add_preset->set_disabled(true);
+		btn_add_preset->set_focus_mode(FOCUS_NONE);
 	} else {
-		bt_add_preset->set_disabled(false);
-		bt_add_preset->set_focus_mode(FOCUS_ALL);
+		btn_add_preset->set_disabled(false);
+		btn_add_preset->set_focus_mode(FOCUS_ALL);
 	}
 }
 
@@ -731,7 +734,6 @@ void ColorPicker::set_presets_visible(bool p_visible) {
 	presets_visible = p_visible;
 	preset_separator->set_visible(p_visible);
 	preset_container->set_visible(p_visible);
-	preset_container2->set_visible(p_visible);
 }
 
 bool ColorPicker::are_presets_visible() const {
@@ -915,22 +917,14 @@ ColorPicker::ColorPicker() :
 	preset_separator = memnew(HSeparator);
 	add_child(preset_separator);
 
-	preset_container = memnew(HBoxContainer);
 	preset_container->set_h_size_flags(SIZE_EXPAND_FILL);
+	preset_container->set_columns(preset_column_count);
 	add_child(preset_container);
 
-	preset = memnew(TextureRect);
-	preset_container->add_child(preset);
-	preset->connect("gui_input", this, "_preset_input");
-	preset->connect("draw", this, "_update_presets");
-
-	preset_container2 = memnew(HBoxContainer);
-	preset_container2->set_h_size_flags(SIZE_EXPAND_FILL);
-	add_child(preset_container2);
-	bt_add_preset = memnew(Button);
-	preset_container2->add_child(bt_add_preset);
-	bt_add_preset->set_tooltip(RTR("Add current color as a preset."));
-	bt_add_preset->connect("pressed", this, "_add_preset_pressed");
+	btn_add_preset = memnew(Button);
+	btn_add_preset->connect("pressed", this, "_add_preset_pressed");
+	btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
+	preset_container->add_child(btn_add_preset);
 }
 
 /////////////////
@@ -954,6 +948,7 @@ void ColorPickerButton::_modal_closed() {
 
 void ColorPickerButton::pressed() {
 	_update_picker();
+	picker->_update_presets();
 	popup->set_position(get_global_position() - picker->get_combined_minimum_size() * get_global_transform().get_scale());
 	popup->set_scale(get_global_transform().get_scale());
 	popup->popup();
@@ -1077,3 +1072,64 @@ 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<StyleBox> sb_raw = get_stylebox("preset_fg", "ColorPresetButton")->duplicate();
+			Ref<StyleBoxFlat> sb_flat = sb_raw;
+			Ref<StyleBoxTexture> sb_texture = sb_raw;
+
+			if (sb_raw->get_class_name() == "StyleBoxFlat") {
+				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_margin(MARGIN_LEFT, -sb_flat->get_margin(MARGIN_LEFT));
+					bg_texture_rect = bg_texture_rect.grow_margin(MARGIN_RIGHT, -sb_flat->get_margin(MARGIN_RIGHT));
+					bg_texture_rect = bg_texture_rect.grow_margin(MARGIN_TOP, -sb_flat->get_margin(MARGIN_TOP));
+					bg_texture_rect = bg_texture_rect.grow_margin(MARGIN_BOTTOM, -sb_flat->get_margin(MARGIN_BOTTOM));
+
+					draw_texture_rect(get_icon("preset_bg_icon", "ColorPresetButton"), 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_raw->get_class_name() == "StyleBoxTexture") {
+				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(get_icon("preset_bg_icon", "ColorPresetButton"), 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 and 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(Control::get_icon("overbright_indicator", "ColorPresetButton"), Vector2(0, 0));
+			}
+
+		} break;
+	}
+}
+
+void ColorPresetButton::set_preset_color(const Color &p_color) {
+	preset_color = p_color;
+}
+
+Color ColorPresetButton::get_preset_color() const {
+	return preset_color;
+}
+
+ColorPresetButton::ColorPresetButton(Color p_color) {
+	preset_color = p_color;
+}
+
+ColorPresetButton::~ColorPresetButton() {
+}

+ 29 - 8
scene/gui/color_picker.h

@@ -34,6 +34,7 @@
 #include "scene/gui/box_container.h"
 #include "scene/gui/button.h"
 #include "scene/gui/check_button.h"
+#include "scene/gui/grid_container.h"
 #include "scene/gui/label.h"
 #include "scene/gui/line_edit.h"
 #include "scene/gui/popup.h"
@@ -43,6 +44,22 @@
 #include "scene/gui/texture_rect.h"
 #include "scene/gui/tool_button.h"
 
+class ColorPresetButton : public BaseButton {
+	GDCLASS(ColorPresetButton, BaseButton);
+
+	Color preset_color;
+
+protected:
+	void _notification(int);
+
+public:
+	void set_preset_color(const Color &p_color);
+	Color get_preset_color() const;
+
+	ColorPresetButton(Color p_color);
+	~ColorPresetButton();
+};
+
 class ColorPicker : public BoxContainer {
 	GDCLASS(ColorPicker, BoxContainer);
 
@@ -52,12 +69,9 @@ private:
 	Control *uv_edit;
 	Control *w_edit;
 	TextureRect *sample;
-	TextureRect *preset;
-	HBoxContainer *preset_container;
-	HBoxContainer *preset_container2;
+	GridContainer *preset_container = memnew(GridContainer);
 	HSeparator *preset_separator;
-	Button *bt_add_preset;
-	List<Color> presets;
+	Button *btn_add_preset;
 	ToolButton *btn_pick;
 	CheckButton *btn_hsv;
 	CheckButton *btn_raw;
@@ -69,10 +83,13 @@ private:
 	bool edit_alpha;
 	Size2i ms;
 	bool text_is_constructor;
-	int presets_per_row;
+
+	const int preset_column_count = 10;
+	List<Color> presets;
 
 	Color color;
 	Color old_color;
+
 	bool display_old_color = false;
 	bool raw_mode_enabled;
 	bool hsv_mode_enabled;
@@ -81,6 +98,7 @@ private:
 	bool changing_color;
 	bool presets_enabled;
 	bool presets_visible;
+
 	float h, s, v;
 	Color last_hsv;
 
@@ -88,7 +106,6 @@ private:
 	void _value_changed(double);
 	void _update_controls();
 	void _update_color(bool p_update_sliders = true);
-	void _update_presets();
 	void _update_text_value();
 	void _text_type_toggled();
 	void _sample_input(const Ref<InputEvent> &p_event);
@@ -97,7 +114,7 @@ private:
 
 	void _uv_input(const Ref<InputEvent> &p_event);
 	void _w_input(const Ref<InputEvent> &p_event);
-	void _preset_input(const Ref<InputEvent> &p_event);
+	void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color);
 	void _screen_input(const Ref<InputEvent> &p_event);
 	void _add_preset_pressed();
 	void _screen_pick_pressed();
@@ -105,6 +122,9 @@ private:
 	void _focus_exit();
 	void _html_focus_exit();
 
+	inline int _get_preset_size();
+	void _add_preset_button(int p_size, const Color &p_color);
+
 protected:
 	void _notification(int);
 	static void _bind_methods();
@@ -124,6 +144,7 @@ public:
 	void add_preset(const Color &p_color);
 	void erase_preset(const Color &p_color);
 	PoolColorArray get_presets() const;
+	void _update_presets();
 
 	void set_hsv_mode(bool p_enabled);
 	bool is_hsv_mode() const;

+ 26 - 18
scene/resources/default_theme/default_theme.cpp

@@ -256,24 +256,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 
 	theme->set_constant("underline_spacing", "LinkButton", 2 * scale);
 
-	// ColorPickerButton
-
-	theme->set_stylebox("normal", "ColorPickerButton", sb_button_normal);
-	theme->set_stylebox("pressed", "ColorPickerButton", sb_button_pressed);
-	theme->set_stylebox("hover", "ColorPickerButton", sb_button_hover);
-	theme->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled);
-	theme->set_stylebox("focus", "ColorPickerButton", sb_button_focus);
-
-	theme->set_font("font", "ColorPickerButton", default_font);
-
-	theme->set_color("font_color", "ColorPickerButton", Color(1, 1, 1, 1));
-	theme->set_color("font_color_pressed", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1));
-	theme->set_color("font_color_hover", "ColorPickerButton", Color(1, 1, 1, 1));
-	theme->set_color("font_color_focus", "ColorPickerButton", Color(1, 1, 1, 1));
-	theme->set_color("font_color_disabled", "ColorPickerButton", Color(0.9, 0.9, 0.9, 0.3));
-
-	theme->set_constant("hseparation", "ColorPickerButton", 2 * scale);
-
 	// ToolButton
 
 	theme->set_stylebox("normal", "ToolButton", make_empty_stylebox(6, 4, 6, 4));
@@ -818,7 +800,33 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 	theme->set_icon("preset_bg", "ColorPicker", make_icon(mini_checkerboard_png));
 	theme->set_icon("overbright_indicator", "ColorPicker", make_icon(overbright_indicator_png));
 
+	// ColorPickerButton
+
 	theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png));
+	theme->set_stylebox("normal", "ColorPickerButton", sb_button_normal);
+	theme->set_stylebox("pressed", "ColorPickerButton", sb_button_pressed);
+	theme->set_stylebox("hover", "ColorPickerButton", sb_button_hover);
+	theme->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled);
+	theme->set_stylebox("focus", "ColorPickerButton", sb_button_focus);
+
+	theme->set_font("font", "ColorPickerButton", default_font);
+
+	theme->set_color("font_color", "ColorPickerButton", Color(1, 1, 1, 1));
+	theme->set_color("font_color_pressed", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1));
+	theme->set_color("font_color_hover", "ColorPickerButton", Color(1, 1, 1, 1));
+	theme->set_color("font_color_focus", "ColorPickerButton", Color(1, 1, 1, 1));
+	theme->set_color("font_color_disabled", "ColorPickerButton", Color(0.9, 0.9, 0.9, 0.3));
+
+	theme->set_constant("hseparation", "ColorPickerButton", 2 * scale);
+
+	// ColorPresetButton
+
+	Ref<StyleBoxFlat> preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2);
+	preset_sb->set_anti_aliased(false);
+
+	theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb);
+	theme->set_icon("preset_bg_icon", "ColorPresetButton", make_icon(mini_checkerboard_png));
+	theme->set_icon("overbright_indicator", "ColorPicker", make_icon(overbright_indicator_png));
 
 	// TooltipPanel