1 | /**************************************************************************/ |
2 | /* color_picker.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef COLOR_PICKER_H |
32 | #define COLOR_PICKER_H |
33 | |
34 | #include "scene/gui/aspect_ratio_container.h" |
35 | #include "scene/gui/box_container.h" |
36 | #include "scene/gui/button.h" |
37 | #include "scene/gui/control.h" |
38 | #include "scene/gui/grid_container.h" |
39 | #include "scene/gui/label.h" |
40 | #include "scene/gui/line_edit.h" |
41 | #include "scene/gui/menu_button.h" |
42 | #include "scene/gui/option_button.h" |
43 | #include "scene/gui/panel.h" |
44 | #include "scene/gui/popup.h" |
45 | #include "scene/gui/separator.h" |
46 | #include "scene/gui/slider.h" |
47 | #include "scene/gui/spin_box.h" |
48 | #include "scene/gui/texture_rect.h" |
49 | #include "scene/resources/style_box_flat.h" |
50 | |
51 | class ColorMode; |
52 | class ColorModeRGB; |
53 | class ColorModeHSV; |
54 | class ColorModeRAW; |
55 | class ColorModeOKHSL; |
56 | |
57 | class ColorPresetButton : public BaseButton { |
58 | GDCLASS(ColorPresetButton, BaseButton); |
59 | |
60 | Color preset_color; |
61 | |
62 | struct ThemeCache { |
63 | Ref<StyleBox> foreground_style; |
64 | |
65 | Ref<Texture2D> background_icon; |
66 | Ref<Texture2D> overbright_indicator; |
67 | } theme_cache; |
68 | |
69 | protected: |
70 | void _notification(int); |
71 | static void _bind_methods(); |
72 | |
73 | public: |
74 | void set_preset_color(const Color &p_color); |
75 | Color get_preset_color() const; |
76 | |
77 | ColorPresetButton(Color p_color, int p_size); |
78 | ~ColorPresetButton(); |
79 | }; |
80 | |
81 | class ColorPicker : public VBoxContainer { |
82 | GDCLASS(ColorPicker, VBoxContainer); |
83 | |
84 | // These classes poke into theme items for their internal logic. |
85 | friend class ColorModeRGB; |
86 | friend class ColorModeHSV; |
87 | friend class ColorModeRAW; |
88 | friend class ColorModeOKHSL; |
89 | |
90 | public: |
91 | enum ColorModeType { |
92 | MODE_RGB, |
93 | MODE_HSV, |
94 | MODE_RAW, |
95 | MODE_OKHSL, |
96 | |
97 | MODE_MAX |
98 | }; |
99 | |
100 | enum PickerShapeType { |
101 | SHAPE_HSV_RECTANGLE, |
102 | SHAPE_HSV_WHEEL, |
103 | SHAPE_VHS_CIRCLE, |
104 | SHAPE_OKHSL_CIRCLE, |
105 | SHAPE_NONE, |
106 | |
107 | SHAPE_MAX |
108 | }; |
109 | |
110 | static const int SLIDER_COUNT = 4; |
111 | |
112 | private: |
113 | static Ref<Shader> wheel_shader; |
114 | static Ref<Shader> circle_shader; |
115 | static Ref<Shader> circle_ok_color_shader; |
116 | static List<Color> preset_cache; |
117 | static List<Color> recent_preset_cache; |
118 | |
119 | #ifdef TOOLS_ENABLED |
120 | Object *editor_settings = nullptr; |
121 | #endif |
122 | |
123 | int current_slider_count = SLIDER_COUNT; |
124 | static const int MODE_BUTTON_COUNT = 3; |
125 | |
126 | bool slider_theme_modified = true; |
127 | |
128 | Vector<ColorMode *> modes; |
129 | |
130 | Popup *picker_window = nullptr; |
131 | // Legacy color picking. |
132 | TextureRect *picker_texture_rect = nullptr; |
133 | Panel *picker_preview = nullptr; |
134 | Label *picker_preview_label = nullptr; |
135 | Ref<StyleBoxFlat> picker_preview_style_box; |
136 | Color picker_color; |
137 | |
138 | MarginContainer *internal_margin = nullptr; |
139 | Control *uv_edit = nullptr; |
140 | Control *w_edit = nullptr; |
141 | AspectRatioContainer *wheel_edit = nullptr; |
142 | MarginContainer *wheel_margin = nullptr; |
143 | Ref<ShaderMaterial> wheel_mat; |
144 | Ref<ShaderMaterial> circle_mat; |
145 | Control *wheel = nullptr; |
146 | Control *wheel_uv = nullptr; |
147 | TextureRect *sample = nullptr; |
148 | GridContainer *preset_container = nullptr; |
149 | HBoxContainer *recent_preset_hbc = nullptr; |
150 | Button *btn_add_preset = nullptr; |
151 | Button *btn_pick = nullptr; |
152 | Button *btn_preset = nullptr; |
153 | Button *btn_recent_preset = nullptr; |
154 | PopupMenu * = nullptr; |
155 | PopupMenu * = nullptr; |
156 | MenuButton *btn_shape = nullptr; |
157 | HBoxContainer *mode_hbc = nullptr; |
158 | HBoxContainer *sample_hbc = nullptr; |
159 | GridContainer *slider_gc = nullptr; |
160 | HBoxContainer *hex_hbc = nullptr; |
161 | MenuButton *btn_mode = nullptr; |
162 | Button *mode_btns[MODE_BUTTON_COUNT]; |
163 | Ref<ButtonGroup> mode_group = nullptr; |
164 | ColorPresetButton *selected_recent_preset = nullptr; |
165 | Ref<ButtonGroup> preset_group; |
166 | Ref<ButtonGroup> recent_preset_group; |
167 | |
168 | OptionButton *mode_option_button = nullptr; |
169 | |
170 | HSlider *sliders[SLIDER_COUNT]; |
171 | SpinBox *values[SLIDER_COUNT]; |
172 | Label *labels[SLIDER_COUNT]; |
173 | Button *text_type = nullptr; |
174 | LineEdit *c_text = nullptr; |
175 | |
176 | HSlider *alpha_slider = nullptr; |
177 | SpinBox *alpha_value = nullptr; |
178 | Label *alpha_label = nullptr; |
179 | |
180 | bool edit_alpha = true; |
181 | Size2i ms; |
182 | bool text_is_constructor = false; |
183 | PickerShapeType current_shape = SHAPE_HSV_RECTANGLE; |
184 | ColorModeType current_mode = MODE_RGB; |
185 | bool colorize_sliders = true; |
186 | |
187 | const int PRESET_COLUMN_COUNT = 9; |
188 | int prev_preset_size = 0; |
189 | int prev_rencet_preset_size = 0; |
190 | List<Color> presets; |
191 | List<Color> recent_presets; |
192 | |
193 | Color color; |
194 | Color old_color; |
195 | bool is_picking_color = false; |
196 | |
197 | bool display_old_color = false; |
198 | bool deferred_mode_enabled = false; |
199 | bool updating = true; |
200 | bool changing_color = false; |
201 | bool spinning = false; |
202 | bool can_add_swatches = true; |
203 | bool presets_visible = true; |
204 | bool color_modes_visible = true; |
205 | bool sampler_visible = true; |
206 | bool sliders_visible = true; |
207 | bool hex_visible = true; |
208 | bool line_edit_mouse_release = false; |
209 | bool text_changed = false; |
210 | |
211 | float h = 0.0; |
212 | float s = 0.0; |
213 | float v = 0.0; |
214 | Color last_color; |
215 | |
216 | struct ThemeCache { |
217 | float base_scale = 1.0; |
218 | |
219 | int content_margin = 0; |
220 | int label_width = 0; |
221 | |
222 | int sv_height = 0; |
223 | int sv_width = 0; |
224 | int h_width = 0; |
225 | |
226 | bool center_slider_grabbers = true; |
227 | |
228 | Ref<Texture2D> screen_picker; |
229 | Ref<Texture2D> expanded_arrow; |
230 | Ref<Texture2D> folded_arrow; |
231 | Ref<Texture2D> add_preset; |
232 | |
233 | Ref<Texture2D> shape_rect; |
234 | Ref<Texture2D> shape_rect_wheel; |
235 | Ref<Texture2D> shape_circle; |
236 | |
237 | Ref<Texture2D> bar_arrow; |
238 | Ref<Texture2D> sample_bg; |
239 | Ref<Texture2D> overbright_indicator; |
240 | Ref<Texture2D> picker_cursor; |
241 | Ref<Texture2D> color_hue; |
242 | Ref<Texture2D> color_okhsl_hue; |
243 | |
244 | /* Mode buttons */ |
245 | Ref<StyleBox> mode_button_normal; |
246 | Ref<StyleBox> mode_button_pressed; |
247 | Ref<StyleBox> mode_button_hover; |
248 | } theme_cache; |
249 | |
250 | void _copy_color_to_hsv(); |
251 | void _copy_hsv_to_color(); |
252 | |
253 | PickerShapeType _get_actual_shape() const; |
254 | void create_slider(GridContainer *gc, int idx); |
255 | void _reset_sliders_theme(); |
256 | void _html_submitted(const String &p_html); |
257 | void _value_changed(double); |
258 | void _update_controls(); |
259 | void _update_color(bool p_update_sliders = true); |
260 | void _update_text_value(); |
261 | void _text_type_toggled(); |
262 | void _sample_input(const Ref<InputEvent> &p_event); |
263 | void _sample_draw(); |
264 | void _hsv_draw(int p_which, Control *c); |
265 | void _slider_draw(int p_which); |
266 | |
267 | void _uv_input(const Ref<InputEvent> &p_event, Control *c); |
268 | void _w_input(const Ref<InputEvent> &p_event); |
269 | void _slider_or_spin_input(const Ref<InputEvent> &p_event); |
270 | void _line_edit_input(const Ref<InputEvent> &p_event); |
271 | void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color); |
272 | void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset); |
273 | void _text_changed(const String &p_new_text); |
274 | void _add_preset_pressed(); |
275 | void _html_focus_exit(); |
276 | void _pick_button_pressed(); |
277 | void _pick_finished(); |
278 | // Legacy color picking. |
279 | void _pick_button_pressed_legacy(); |
280 | void _picker_texture_input(const Ref<InputEvent> &p_event); |
281 | |
282 | inline int _get_preset_size(); |
283 | void _add_preset_button(int p_size, const Color &p_color); |
284 | void _add_recent_preset_button(int p_size, const Color &p_color); |
285 | |
286 | void _show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_preset, Container *p_preset_container); |
287 | void _update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset); |
288 | |
289 | void (ColorModeType p_mode); |
290 | |
291 | Variant _get_drag_data_fw(const Point2 &p_point, Control *p_from_control); |
292 | bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const; |
293 | void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control); |
294 | |
295 | protected: |
296 | virtual void _update_theme_item_cache() override; |
297 | |
298 | void _notification(int); |
299 | static void _bind_methods(); |
300 | |
301 | public: |
302 | #ifdef TOOLS_ENABLED |
303 | void set_editor_settings(Object *p_editor_settings); |
304 | #endif |
305 | HSlider *get_slider(int idx); |
306 | Vector<float> get_active_slider_values(); |
307 | |
308 | static void init_shaders(); |
309 | static void finish_shaders(); |
310 | |
311 | void add_mode(ColorMode *p_mode); |
312 | |
313 | void set_edit_alpha(bool p_show); |
314 | bool is_editing_alpha() const; |
315 | |
316 | int get_preset_size(); |
317 | |
318 | void _set_pick_color(const Color &p_color, bool p_update_sliders); |
319 | void set_pick_color(const Color &p_color); |
320 | Color get_pick_color() const; |
321 | void set_old_color(const Color &p_color); |
322 | |
323 | void set_display_old_color(bool p_enabled); |
324 | bool is_displaying_old_color() const; |
325 | |
326 | void set_picker_shape(PickerShapeType p_shape); |
327 | PickerShapeType get_picker_shape() const; |
328 | |
329 | void add_preset(const Color &p_color); |
330 | void add_recent_preset(const Color &p_color); |
331 | void erase_preset(const Color &p_color); |
332 | void erase_recent_preset(const Color &p_color); |
333 | PackedColorArray get_presets() const; |
334 | PackedColorArray get_recent_presets() const; |
335 | void _update_presets(); |
336 | void _update_recent_presets(); |
337 | |
338 | void _select_from_preset_container(const Color &p_color); |
339 | bool _select_from_recent_preset_hbc(const Color &p_color); |
340 | |
341 | void set_color_mode(ColorModeType p_mode); |
342 | ColorModeType get_color_mode() const; |
343 | |
344 | void set_colorize_sliders(bool p_colorize_sliders); |
345 | bool is_colorizing_sliders() const; |
346 | |
347 | void set_deferred_mode(bool p_enabled); |
348 | bool is_deferred_mode() const; |
349 | |
350 | void set_can_add_swatches(bool p_enabled); |
351 | bool are_swatches_enabled() const; |
352 | |
353 | void set_presets_visible(bool p_visible); |
354 | bool are_presets_visible() const; |
355 | |
356 | void set_modes_visible(bool p_visible); |
357 | bool are_modes_visible() const; |
358 | |
359 | void set_sampler_visible(bool p_visible); |
360 | bool is_sampler_visible() const; |
361 | |
362 | void set_sliders_visible(bool p_visible); |
363 | bool are_sliders_visible() const; |
364 | |
365 | void set_hex_visible(bool p_visible); |
366 | bool is_hex_visible() const; |
367 | |
368 | void set_focus_on_line_edit(); |
369 | |
370 | ColorPicker(); |
371 | ~ColorPicker(); |
372 | }; |
373 | |
374 | class ColorPickerButton : public Button { |
375 | GDCLASS(ColorPickerButton, Button); |
376 | |
377 | // Initialization is now done deferred, |
378 | // this improves performance in the inspector as the color picker |
379 | // can be expensive to initialize. |
380 | |
381 | PopupPanel * = nullptr; |
382 | ColorPicker *picker = nullptr; |
383 | Color color; |
384 | bool edit_alpha = true; |
385 | |
386 | struct ThemeCache { |
387 | Ref<StyleBox> normal_style; |
388 | Ref<Texture2D> background_icon; |
389 | |
390 | Ref<Texture2D> overbright_indicator; |
391 | } theme_cache; |
392 | |
393 | void (); |
394 | void _color_changed(const Color &p_color); |
395 | void _modal_closed(); |
396 | |
397 | virtual void pressed() override; |
398 | |
399 | void _update_picker(); |
400 | |
401 | protected: |
402 | void _notification(int); |
403 | static void _bind_methods(); |
404 | |
405 | public: |
406 | void set_pick_color(const Color &p_color); |
407 | Color get_pick_color() const; |
408 | |
409 | void set_edit_alpha(bool p_show); |
410 | bool is_editing_alpha() const; |
411 | |
412 | ColorPicker *get_picker(); |
413 | PopupPanel *(); |
414 | |
415 | ColorPickerButton(const String &p_text = String()); |
416 | }; |
417 | |
418 | VARIANT_ENUM_CAST(ColorPicker::PickerShapeType); |
419 | VARIANT_ENUM_CAST(ColorPicker::ColorModeType); |
420 | |
421 | #endif // COLOR_PICKER_H |
422 | |