summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorK. S. Ernest (iFire) Lee <fire@users.noreply.github.com>2022-04-18 11:29:29 -0700
committerK. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>2022-06-07 05:53:27 -0700
commit1b776a6e7a5046d337933f8504699d1c4244289e (patch)
tree24697438d1b8671201b82cadca722b1a7d8c07b1 /scene
parent36bd26dc75465d0b64441113bc4055b2cd06b516 (diff)
Allow picking similar colours using OKHSL.
Diffstat (limited to 'scene')
-rw-r--r--scene/gui/color_picker.cpp173
-rw-r--r--scene/gui/color_picker.h6
2 files changed, 142 insertions, 37 deletions
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 6f7ad94139..5fff1e1df3 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -31,6 +31,7 @@
#include "color_picker.h"
#include "core/input/input.h"
+#include "core/math/color.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "scene/main/window.h"
@@ -39,6 +40,9 @@
#include "editor/editor_settings.h"
#endif
+#include "thirdparty/misc/ok_color.h"
+#include "thirdparty/misc/ok_color_shader.h"
+
List<Color> ColorPicker::preset_cache;
void ColorPicker::_notification(int p_what) {
@@ -102,6 +106,7 @@ void ColorPicker::_notification(int p_what) {
Ref<Shader> ColorPicker::wheel_shader;
Ref<Shader> ColorPicker::circle_shader;
+Ref<Shader> ColorPicker::circle_ok_color_shader;
void ColorPicker::init_shaders() {
wheel_shader.instantiate();
@@ -152,11 +157,36 @@ void fragment() {
COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);
})");
+
+ circle_ok_color_shader.instantiate();
+ circle_ok_color_shader->set_code(OK_COLOR_SHADER + R"(
+// ColorPicker ok color hsv circle shader.
+
+uniform float v = 1.0;
+
+void fragment() {
+ float x = UV.x - 0.5;
+ float y = UV.y - 0.5;
+ x += 0.001;
+ y += 0.001;
+ float b = float(sqrt(x * x + y * y) < 0.5);
+ x -= 0.002;
+ float b2 = float(sqrt(x * x + y * y) < 0.5);
+ y -= 0.002;
+ float b3 = float(sqrt(x * x + y * y) < 0.5);
+ x += 0.002;
+ float b4 = float(sqrt(x * x + y * y) < 0.5);
+ float s = sqrt(x * x + y * y);
+ float h = atan(y, x) / (2.0*M_PI);
+ vec3 col = okhsl_to_srgb(vec3(h, s, v));
+ COLOR = vec4(col, (b + b2 + b3 + b4) / 4.00);
+})");
}
void ColorPicker::finish_shaders() {
wheel_shader.unref();
circle_shader.unref();
+ circle_ok_color_shader.unref();
}
void ColorPicker::set_focus_on_line_edit() {
@@ -166,8 +196,12 @@ void ColorPicker::set_focus_on_line_edit() {
void ColorPicker::_update_controls() {
const char *rgb[3] = { "R", "G", "B" };
const char *hsv[3] = { "H", "S", "V" };
-
- if (hsv_mode_enabled) {
+ const char *hsl[3] = { "H", "S", "L" };
+ if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
+ for (int i = 0; i < 3; i++) {
+ labels[i]->set_text(hsl[i]);
+ }
+ } else if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
for (int i = 0; i < 3; i++) {
labels[i]->set_text(hsv[i]);
}
@@ -176,14 +210,23 @@ void ColorPicker::_update_controls() {
labels[i]->set_text(rgb[i]);
}
}
-
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ btn_hsv->set_text(RTR("OKHSL"));
+ } else {
+ btn_hsv->set_text(RTR("HSV"));
+ }
if (hsv_mode_enabled) {
set_raw_mode(false);
+ set_hsv_mode(true);
btn_raw->set_disabled(true);
} else if (raw_mode_enabled) {
+ set_raw_mode(true);
set_hsv_mode(false);
+ btn_raw->set_disabled(false);
btn_hsv->set_disabled(true);
} else {
+ set_raw_mode(false);
+ set_hsv_mode(false);
btn_raw->set_disabled(false);
btn_hsv->set_disabled(false);
}
@@ -236,8 +279,15 @@ void ColorPicker::_update_controls() {
wheel_edit->show();
w_edit->show();
uv_edit->hide();
-
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();
+ wheel->set_material(circle_mat);
+ circle_mat->set_shader(circle_ok_color_shader);
break;
default: {
}
@@ -246,11 +296,17 @@ void ColorPicker::_update_controls() {
void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) {
color = p_color;
- if (color != last_hsv) {
- h = color.get_h();
- s = color.get_s();
- v = color.get_v();
- last_hsv = color;
+ if (color != last_color) {
+ if (picker_type == 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();
+ }
+ last_color = color;
}
if (!is_inside_tree()) {
@@ -301,10 +357,13 @@ void ColorPicker::_value_changed(double) {
h = scroll[0]->get_value() / 360.0;
s = scroll[1]->get_value() / 100.0;
v = scroll[2]->get_value() / 100.0;
- color.set_hsv(h, s, v, scroll[3]->get_value() / 255.0);
-
- last_hsv = color;
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
+ } else {
+ color.set_hsv(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
+ }
+ last_color = color;
} else {
for (int i = 0; i < 4; i++) {
color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
@@ -342,7 +401,6 @@ void ColorPicker::_update_color(bool p_update_sliders) {
for (int i = 0; i < 4; i++) {
scroll[i]->set_step(1.0);
}
-
scroll[0]->set_max(359);
scroll[0]->set_value(h * 360.0);
scroll[1]->set_max(100);
@@ -350,7 +408,7 @@ void ColorPicker::_update_color(bool p_update_sliders) {
scroll[2]->set_max(100);
scroll[2]->set_value(v * 100.0);
scroll[3]->set_max(255);
- scroll[3]->set_value(color.components[3] * 255.0);
+ scroll[3]->set_value(Math::round(color.components[3] * 255.0));
} else {
for (int i = 0; i < 4; i++) {
if (raw_mode_enabled) {
@@ -362,7 +420,7 @@ void ColorPicker::_update_color(bool p_update_sliders) {
scroll[i]->set_value(color.components[i]);
} else {
scroll[i]->set_step(1);
- const float byte_value = color.components[i] * 255.0;
+ const float byte_value = Math::round(color.components[i] * 255.0);
scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
scroll[i]->set_value(byte_value);
}
@@ -426,7 +484,6 @@ Color ColorPicker::get_pick_color() const {
void ColorPicker::set_picker_shape(PickerShapeType p_picker_type) {
ERR_FAIL_INDEX(p_picker_type, SHAPE_MAX);
picker_type = p_picker_type;
-
_update_controls();
_update_color();
}
@@ -702,7 +759,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
int x;
int y;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2);
y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2);
} else {
@@ -735,6 +792,25 @@ 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 (picker_type == SHAPE_OKHSL_CIRCLE) {
+ Vector<Point2> points;
+ Vector<Color> colors;
+ Color col;
+ col.set_ok_hsl(h, s, 1);
+ points.resize(4);
+ colors.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, col);
+ colors.set(1, col);
+ colors.set(2, Color(0, 0, 0));
+ colors.set(3, Color(0, 0, 0));
+ c->draw_polygon(points, colors);
+ 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 (picker_type == SHAPE_VHS_CIRCLE) {
Vector<Point2> points;
Vector<Color> colors;
@@ -757,7 +833,7 @@ 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 (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
circle_mat->set_shader_param("v", v);
}
}
@@ -793,10 +869,19 @@ void ColorPicker::_slider_draw(int p_which) {
}
Color s_col;
Color v_col;
- s_col.set_hsv(h, 0, v);
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ s_col.set_ok_hsl(h, 0, v);
+ } else {
+ s_col.set_hsv(h, 0, v);
+ }
left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
- s_col.set_hsv(h, 1, v);
- v_col.set_hsv(h, s, 1);
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ s_col.set_ok_hsl(h, 1, v);
+ v_col.set_ok_hsl(h, s, 1);
+ } else {
+ s_col.set_hsv(h, 1, v);
+ v_col.set_hsv(h, s, 1);
+ }
right_color = (p_which == 1) ? s_col : v_col;
} else {
left_color = Color(
@@ -828,9 +913,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
if (bev.is_valid()) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == 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;
@@ -867,8 +951,13 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
}
changing_color = true;
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ } else if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ }
+ last_color = color;
+
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -892,7 +981,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == 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;
@@ -913,9 +1002,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
v = 1.0 - (y - corner_y) / real_size.y;
}
}
-
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -931,7 +1023,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
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 (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
@@ -939,8 +1031,12 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
} else {
changing_color = false;
}
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -957,13 +1053,17 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
return;
}
float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height);
- if (picker_type == SHAPE_VHS_CIRCLE) {
+ if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
}
- color.set_hsv(h, s, v, color.a);
- last_hsv = color;
+ if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
+ color.set_hsv(h, s, v, color.a);
+ } else if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
+ color.set_ok_hsl(h, s, v, color.a);
+ }
+ last_color = color;
set_pick_color(color);
_update_color();
if (!deferred_mode_enabled) {
@@ -1128,7 +1228,7 @@ void ColorPicker::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hsv_mode"), "set_hsv_mode", "is_hsv_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle"), "set_picker_shape", "get_picker_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle"), "set_picker_shape", "get_picker_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible");
@@ -1139,6 +1239,7 @@ void ColorPicker::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_HSV_RECTANGLE);
BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL);
BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
+ BIND_ENUM_CONSTANT(SHAPE_OKHSL_CIRCLE);
}
ColorPicker::ColorPicker() :
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 6f3e16009c..953be032ec 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -68,6 +68,7 @@ public:
SHAPE_HSV_RECTANGLE,
SHAPE_HSV_WHEEL,
SHAPE_VHS_CIRCLE,
+ SHAPE_OKHSL_CIRCLE,
SHAPE_MAX
};
@@ -75,6 +76,7 @@ public:
private:
static Ref<Shader> wheel_shader;
static Ref<Shader> circle_shader;
+ static Ref<Shader> circle_ok_color_shader;
static List<Color> preset_cache;
Control *screen = nullptr;
@@ -124,7 +126,7 @@ private:
float h = 0.0;
float s = 0.0;
float v = 0.0;
- Color last_hsv;
+ Color last_color;
void _html_submitted(const String &p_html);
void _value_changed(double);
@@ -161,6 +163,8 @@ public:
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
+ int get_preset_size();
+
void _set_pick_color(const Color &p_color, bool p_update_sliders);
void set_pick_color(const Color &p_color);
Color get_pick_color() const;