Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/gui/color_picker.h
21635 views
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
#pragma once
32
33
#include "scene/gui/box_container.h"
34
#include "scene/gui/button.h"
35
#include "scene/gui/popup.h"
36
#include "scene/resources/shader.h"
37
38
class AspectRatioContainer;
39
class ColorMode;
40
class ColorPickerShape;
41
class FileDialog;
42
class GridContainer;
43
class HSlider;
44
class Label;
45
class LineEdit;
46
class MarginContainer;
47
class MenuButton;
48
class OptionButton;
49
class PopupMenu;
50
class SpinBox;
51
class StyleBoxFlat;
52
class TextureRect;
53
54
class ColorPresetButton : public BaseButton {
55
GDCLASS(ColorPresetButton, BaseButton);
56
57
Color preset_color;
58
bool recent = false;
59
60
struct ThemeCache {
61
Ref<StyleBox> foreground_style;
62
Ref<StyleBox> focus_style;
63
64
Ref<Texture2D> background_icon;
65
Ref<Texture2D> overbright_indicator;
66
} theme_cache;
67
68
protected:
69
void _notification(int);
70
static void _bind_methods();
71
72
public:
73
void set_preset_color(const Color &p_color);
74
Color get_preset_color() const;
75
76
virtual String get_tooltip(const Point2 &p_pos) const override;
77
78
ColorPresetButton(Color p_color, int p_size, bool p_recent);
79
~ColorPresetButton();
80
};
81
82
class ColorPicker : public VBoxContainer {
83
GDCLASS(ColorPicker, VBoxContainer);
84
85
// These classes poke into theme items for their internal logic.
86
friend class ColorPickerShape;
87
friend class ColorPickerShapeRectangle;
88
friend class ColorPickerShapeWheel;
89
friend class ColorPickerShapeCircle;
90
friend class ColorPickerShapeVHSCircle;
91
friend class ColorPickerShapeOKHSLCircle;
92
friend class ColorPickerShapeOKHSRectangle;
93
friend class ColorPickerShapeOKHLRectangle;
94
95
friend class ColorModeRGB;
96
friend class ColorModeHSV;
97
friend class ColorModeLinear;
98
friend class ColorModeOKHSL;
99
100
public:
101
enum ColorModeType {
102
MODE_RGB,
103
MODE_HSV,
104
#ifndef DISABLE_DEPRECATED
105
MODE_RAW = 2,
106
#endif
107
MODE_LINEAR = 2,
108
MODE_OKHSL,
109
110
MODE_MAX
111
};
112
113
enum PickerShapeType {
114
SHAPE_HSV_RECTANGLE,
115
SHAPE_HSV_WHEEL,
116
SHAPE_VHS_CIRCLE,
117
SHAPE_OKHSL_CIRCLE,
118
SHAPE_NONE,
119
SHAPE_OK_HS_RECTANGLE,
120
SHAPE_OK_HL_RECTANGLE,
121
122
SHAPE_MAX
123
};
124
125
private:
126
// Ideally, `SHAPE_NONE` should be -1 so that we don't need to convert shape type to index.
127
// In order to avoid breaking compatibility, we have to use these methods for conversion.
128
inline int get_current_shape_index() {
129
return shape_to_index(current_shape);
130
}
131
132
static inline int shape_to_index(PickerShapeType p_shape) {
133
if (p_shape == SHAPE_NONE) {
134
return -1;
135
}
136
if (p_shape > SHAPE_NONE) {
137
return p_shape - 1;
138
}
139
return p_shape;
140
}
141
142
static inline PickerShapeType index_to_shape(int p_index) {
143
if (p_index == -1) {
144
return SHAPE_NONE;
145
}
146
if (p_index >= SHAPE_NONE) {
147
return (PickerShapeType)(p_index + 1);
148
}
149
return (PickerShapeType)p_index;
150
}
151
152
public:
153
static const int MODE_SLIDER_COUNT = 3;
154
155
enum SLIDER_EXTRA {
156
SLIDER_INTENSITY = MODE_SLIDER_COUNT,
157
SLIDER_ALPHA,
158
159
SLIDER_MAX
160
};
161
162
enum class MenuOption {
163
MENU_SAVE,
164
MENU_SAVE_AS,
165
MENU_LOAD,
166
MENU_QUICKLOAD,
167
MENU_CLEAR,
168
};
169
170
private:
171
static inline List<Color> preset_cache;
172
static inline List<Color> recent_preset_cache;
173
174
#ifdef TOOLS_ENABLED
175
Object *editor_settings = nullptr;
176
#endif
177
178
int current_slider_count = MODE_SLIDER_COUNT;
179
180
const float DEFAULT_GAMEPAD_EVENT_DELAY_MS = 1.0 / 2;
181
const float GAMEPAD_EVENT_REPEAT_RATE_MS = 1.0 / 30;
182
float gamepad_event_delay_ms = DEFAULT_GAMEPAD_EVENT_DELAY_MS;
183
184
static constexpr int MODE_BUTTON_COUNT = 3;
185
186
bool slider_theme_modified = true;
187
188
LocalVector<ColorMode *> modes;
189
LocalVector<ColorPickerShape *> shapes;
190
191
Popup *picker_window = nullptr;
192
TextureRect *picker_texture_zoom = nullptr;
193
Panel *picker_preview = nullptr;
194
Panel *picker_preview_color = nullptr;
195
Ref<StyleBoxFlat> picker_preview_style_box;
196
Ref<StyleBoxFlat> picker_preview_style_box_color;
197
198
// Legacy color picking.
199
TextureRect *picker_texture_rect = nullptr;
200
Color picker_color;
201
FileDialog *file_dialog = nullptr;
202
MenuButton *menu_btn = nullptr;
203
PopupMenu *options_menu = nullptr;
204
205
MarginContainer *internal_margin = nullptr;
206
HBoxContainer *shape_container = nullptr;
207
TextureRect *sample = nullptr;
208
VBoxContainer *swatches_vbc = nullptr;
209
GridContainer *preset_container = nullptr;
210
HBoxContainer *recent_preset_hbc = nullptr;
211
Button *btn_add_preset = nullptr;
212
Button *btn_pick = nullptr;
213
Label *palette_name = nullptr;
214
String palette_path;
215
bool presets_just_loaded = false;
216
Button *btn_preset = nullptr;
217
Button *btn_recent_preset = nullptr;
218
PopupMenu *shape_popup = nullptr;
219
PopupMenu *mode_popup = nullptr;
220
MenuButton *btn_shape = nullptr;
221
HBoxContainer *mode_hbc = nullptr;
222
HBoxContainer *sample_hbc = nullptr;
223
GridContainer *slider_gc = nullptr;
224
HBoxContainer *hex_hbc = nullptr;
225
Label *hex_label = nullptr;
226
MenuButton *btn_mode = nullptr;
227
Button *mode_btns[MODE_BUTTON_COUNT];
228
Ref<ButtonGroup> mode_group;
229
ColorPresetButton *selected_recent_preset = nullptr;
230
Ref<ButtonGroup> preset_group;
231
Ref<ButtonGroup> recent_preset_group;
232
233
HBoxContainer *perm_hb = nullptr;
234
void _req_permission();
235
236
#ifdef TOOLS_ENABLED
237
Callable quick_open_callback;
238
Callable palette_saved_callback;
239
#endif // TOOLS_ENABLED
240
241
OptionButton *mode_option_button = nullptr;
242
243
HSlider *sliders[SLIDER_MAX];
244
SpinBox *values[SLIDER_MAX];
245
Label *labels[SLIDER_MAX];
246
247
Button *text_type = nullptr;
248
LineEdit *c_text = nullptr;
249
Button *text_copy = nullptr;
250
251
HSlider *alpha_slider = nullptr;
252
SpinBox *alpha_value = nullptr;
253
Label *alpha_label = nullptr;
254
255
bool edit_alpha = true;
256
257
HSlider *intensity_slider = nullptr;
258
SpinBox *intensity_value = nullptr;
259
Label *intensity_label = nullptr;
260
261
bool edit_intensity = true;
262
263
Size2i ms;
264
bool text_is_constructor = false;
265
PickerShapeType current_shape = SHAPE_HSV_RECTANGLE;
266
ColorModeType current_mode = MODE_RGB;
267
bool colorize_sliders = true;
268
269
const int PRESET_COLUMN_COUNT = 9;
270
int prev_preset_size = 0;
271
int prev_rencet_preset_size = 0;
272
List<Color> presets;
273
List<Color> recent_presets;
274
275
Color color;
276
Color color_normalized;
277
Color old_color;
278
Color pre_picking_color;
279
bool is_picking_color = false;
280
281
bool display_old_color = false;
282
bool deferred_mode_enabled = false;
283
bool updating = true;
284
bool changing_color = false;
285
bool spinning = false;
286
bool can_add_swatches = true;
287
bool presets_visible = true;
288
bool color_modes_visible = true;
289
bool sampler_visible = true;
290
bool sliders_visible = true;
291
bool hex_visible = true;
292
bool line_edit_mouse_release = false;
293
bool text_changed = false;
294
bool currently_dragging = false;
295
296
float h = 0.0;
297
float s = 0.0;
298
float v = 0.0;
299
300
float ok_hsl_h = 0.0;
301
float ok_hsl_s = 0.0;
302
float ok_hsl_l = 0.0;
303
304
bool hsv_cached = false;
305
bool okhsl_cached = false;
306
307
float intensity = 0.0;
308
309
struct ThemeCache {
310
float base_scale = 1.0;
311
312
int content_margin = 0;
313
int label_width = 0;
314
315
int sv_height = 0;
316
int sv_width = 0;
317
int h_width = 0;
318
319
bool center_slider_grabbers = true;
320
321
Ref<StyleBox> picker_focus_rectangle;
322
Ref<StyleBox> picker_focus_circle;
323
Color focused_not_editing_cursor_color;
324
Ref<Texture2D> menu_option;
325
Ref<Texture2D> screen_picker;
326
Ref<Texture2D> expanded_arrow;
327
Ref<Texture2D> folded_arrow;
328
Ref<Texture2D> add_preset;
329
330
Ref<Texture2D> shape_rect;
331
Ref<Texture2D> shape_rect_wheel;
332
Ref<Texture2D> shape_circle;
333
334
Ref<Texture2D> bar_arrow;
335
Ref<Texture2D> sample_bg;
336
Ref<Texture2D> sample_revert;
337
Ref<StyleBox> sample_focus;
338
Ref<Texture2D> overbright_indicator;
339
Ref<Texture2D> picker_cursor;
340
Ref<Texture2D> picker_cursor_bg;
341
Ref<Texture2D> color_hue;
342
343
Ref<Texture2D> color_script;
344
Ref<Texture2D> color_copy;
345
346
/* Mode buttons */
347
Ref<StyleBox> mode_button_normal;
348
Ref<StyleBox> mode_button_pressed;
349
Ref<StyleBox> mode_button_hover;
350
Ref<StyleBox> mode_button_hover_pressed;
351
} theme_cache;
352
353
void _copy_normalized_to_hsv_okhsl();
354
void _copy_hsv_okhsl_to_normalized();
355
356
Color _color_apply_intensity(const Color &col) const;
357
void _normalized_apply_intensity_to_color();
358
void _copy_color_to_normalized_and_intensity();
359
360
void create_slider(GridContainer *gc, int idx);
361
void _reset_sliders_theme();
362
void _html_submitted(const String &p_html);
363
void _slider_drag_started();
364
void _slider_value_changed();
365
void _slider_drag_ended();
366
void _update_controls();
367
void _update_color(bool p_update_sliders = true);
368
void _update_text_value();
369
#ifdef TOOLS_ENABLED
370
void _text_type_toggled();
371
#endif // TOOLS_ENABLED
372
void _text_copy_pressed();
373
void _sample_input(const Ref<InputEvent> &p_event);
374
void _sample_draw();
375
void _slider_draw(int p_which);
376
void _alpha_slider_draw();
377
378
void _slider_or_spin_input(const Ref<InputEvent> &p_event);
379
void _line_edit_input(const Ref<InputEvent> &p_event);
380
void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color);
381
void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset);
382
void _text_changed(const String &p_new_text);
383
void _add_preset_pressed();
384
void _html_focus_exit();
385
void _pick_button_pressed();
386
void _target_gui_input(const Ref<InputEvent> &p_event);
387
void _pick_finished();
388
void _update_menu_items();
389
void _options_menu_cbk(int p_which);
390
void _block_input_on_popup_show();
391
void _enable_input_on_popup_hide();
392
393
// Native color picking.
394
void _pick_button_pressed_native();
395
void _native_cb(bool p_status, const Color &p_color);
396
397
// Legacy color picking.
398
void _pick_button_pressed_legacy();
399
void _picker_texture_input(const Ref<InputEvent> &p_event);
400
401
inline int _get_preset_size();
402
void _add_preset_button(int p_size, const Color &p_color);
403
void _add_recent_preset_button(int p_size, const Color &p_color);
404
void _save_palette(bool p_is_save_as);
405
void _load_palette();
406
407
void _show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_preset, Container *p_preset_container);
408
void _update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset);
409
410
void _set_mode_popup_value(ColorModeType p_mode);
411
412
Variant _get_drag_data_fw(const Point2 &p_point, Control *p_from_control);
413
bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const;
414
void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control);
415
416
void _ensure_file_dialog();
417
418
protected:
419
virtual void _update_theme_item_cache() override;
420
421
void _notification(int);
422
static void _bind_methods();
423
424
public:
425
#ifdef TOOLS_ENABLED
426
void set_editor_settings(Object *p_editor_settings);
427
void set_quick_open_callback(const Callable &p_file_selected);
428
void set_palette_saved_callback(const Callable &p_palette_saved);
429
430
void _quick_open_palette_file_selected(const String &p_path);
431
#endif
432
433
GridContainer *get_slider_container();
434
HSlider *get_slider(int idx);
435
Vector<float> get_active_slider_values();
436
437
void add_mode(ColorMode *p_mode);
438
void add_shape(ColorPickerShape *p_shape);
439
440
void set_edit_alpha(bool p_show);
441
bool is_editing_alpha() const;
442
443
void set_edit_intensity(bool p_show);
444
bool is_editing_intensity() const;
445
446
void _set_pick_color(const Color &p_color, bool p_update_sliders, bool p_calc_intensity);
447
void set_pick_color(const Color &p_color);
448
Color get_pick_color() const;
449
void set_old_color(const Color &p_color);
450
Color get_old_color() const;
451
452
void _palette_file_selected(const String &p_path);
453
454
void set_display_old_color(bool p_enabled);
455
bool is_displaying_old_color() const;
456
457
void set_picker_shape(PickerShapeType p_shape);
458
PickerShapeType get_picker_shape() const;
459
460
void add_preset(const Color &p_color);
461
void add_recent_preset(const Color &p_color);
462
void erase_preset(const Color &p_color);
463
void erase_recent_preset(const Color &p_color);
464
PackedColorArray get_presets() const;
465
PackedColorArray get_recent_presets() const;
466
void _update_presets();
467
void _update_recent_presets();
468
469
void _select_from_preset_container(const Color &p_color);
470
bool _select_from_recent_preset_hbc(const Color &p_color);
471
472
void set_color_mode(ColorModeType p_mode);
473
ColorModeType get_color_mode() const;
474
475
void set_colorize_sliders(bool p_colorize_sliders);
476
bool is_colorizing_sliders() const;
477
478
void set_deferred_mode(bool p_enabled);
479
bool is_deferred_mode() const;
480
481
void set_can_add_swatches(bool p_enabled);
482
bool are_swatches_enabled() const;
483
484
void set_presets_visible(bool p_visible);
485
bool are_presets_visible() const;
486
487
void set_modes_visible(bool p_visible);
488
bool are_modes_visible() const;
489
490
void set_sampler_visible(bool p_visible);
491
bool is_sampler_visible() const;
492
493
void set_sliders_visible(bool p_visible);
494
bool are_sliders_visible() const;
495
496
void set_hex_visible(bool p_visible);
497
bool is_hex_visible() const;
498
499
void set_focus_on_line_edit();
500
void set_focus_on_picker_shape();
501
502
ColorPicker();
503
~ColorPicker();
504
};
505
506
class ColorPickerPopupPanel : public PopupPanel {
507
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
508
};
509
510
class ColorPickerButton : public Button {
511
GDCLASS(ColorPickerButton, Button);
512
513
// Initialization is now done deferred,
514
// this improves performance in the inspector as the color picker
515
// can be expensive to initialize.
516
517
PopupPanel *popup = nullptr;
518
ColorPicker *picker = nullptr;
519
Color color;
520
bool edit_alpha = true;
521
bool edit_intensity = true;
522
bool popup_was_open = false;
523
524
struct ThemeCache {
525
Ref<StyleBox> normal_style;
526
Ref<Texture2D> background_icon;
527
528
Ref<Texture2D> overbright_indicator;
529
} theme_cache;
530
531
void _about_to_popup();
532
void _color_changed(const Color &p_color);
533
void _modal_closed();
534
535
virtual void pressed() override;
536
537
void _update_picker();
538
539
protected:
540
void _notification(int);
541
static void _bind_methods();
542
virtual void gui_input(const Ref<InputEvent> &p_event) override;
543
544
public:
545
void set_pick_color(const Color &p_color);
546
Color get_pick_color() const;
547
548
void set_edit_alpha(bool p_show);
549
bool is_editing_alpha() const;
550
551
void set_edit_intensity(bool p_show);
552
bool is_editing_intensity() const;
553
554
ColorPicker *get_picker();
555
PopupPanel *get_popup();
556
557
ColorPickerButton(const String &p_text = String());
558
};
559
560
VARIANT_ENUM_CAST(ColorPicker::PickerShapeType);
561
VARIANT_ENUM_CAST(ColorPicker::ColorModeType);
562
563