diff options
Diffstat (limited to 'scene/gui/gradient_edit.cpp')
-rw-r--r-- | scene/gui/gradient_edit.cpp | 233 |
1 files changed, 108 insertions, 125 deletions
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 5d024d3be7..0690acbe16 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,6 +39,10 @@ GradientEdit::GradientEdit() { picker = memnew(ColorPicker); popup->add_child(picker); + gradient_cache.instantiate(); + preview_texture.instantiate(); + + preview_texture->set_width(1024); add_child(popup, false, INTERNAL_MODE_FRONT); } @@ -47,7 +51,7 @@ int GradientEdit::_get_point_from_pos(int x) { int total_w = get_size().width - get_size().height - draw_spacing; float min_distance = 1e20; for (int i = 0; i < points.size(); i++) { - //Check if we clicked at point + // Check if we clicked at point. float distance = ABS(x - points[i].offset * total_w); float min = (draw_point_width / 2 * 1.7); //make it easier to grab if (distance <= min && distance < min_distance) { @@ -84,8 +88,8 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && grabbed != -1) { - points.remove(grabbed); + if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && grabbed != -1) { + points.remove_at(grabbed); grabbed = -1; grabbing = false; update(); @@ -94,18 +98,18 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - //Show color picker on double click. - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_double_click() && mb->is_pressed()) { + // Show color picker on double click. + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); _show_color_picker(); accept_event(); } - //Delete point on right click - if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) { + // Delete point on right click. + if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); if (grabbed != -1) { - points.remove(grabbed); + points.remove_at(grabbed); grabbed = -1; grabbing = false; update(); @@ -114,20 +118,20 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } } - //Hold alt key to duplicate selected color - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) { + // Hold alt key to duplicate selected color. + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && mb->is_alt_pressed()) { int x = mb->get_position().x; grabbed = _get_point_from_pos(x); if (grabbed != -1) { int total_w = get_size().width - get_size().height - draw_spacing; - Gradient::Point newPoint = points[grabbed]; - newPoint.offset = CLAMP(x / float(total_w), 0, 1); + Gradient::Point new_point = points[grabbed]; + new_point.offset = CLAMP(x / float(total_w), 0, 1); - points.push_back(newPoint); + points.push_back(new_point); points.sort(); for (int i = 0; i < points.size(); ++i) { - if (points[i].offset == newPoint.offset) { + if (points[i].offset == new_point.offset) { grabbed = i; break; } @@ -138,8 +142,8 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } } - //select - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + // Select. + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { update(); int x = mb->get_position().x; int total_w = get_size().width - get_size().height - draw_spacing; @@ -158,16 +162,16 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - //insert - Gradient::Point newPoint; - newPoint.offset = CLAMP(x / float(total_w), 0, 1); + // Insert point. + Gradient::Point new_point; + new_point.offset = CLAMP(x / float(total_w), 0, 1); Gradient::Point prev; Gradient::Point next; int pos = -1; for (int i = 0; i < points.size(); i++) { - if (points[i].offset < newPoint.offset) { + if (points[i].offset < new_point.offset) { pos = i; } } @@ -191,12 +195,12 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { prev = points[pos]; } - newPoint.color = prev.color.lerp(next.color, (newPoint.offset - prev.offset) / (next.offset - prev.offset)); + new_point.color = prev.color.lerp(next.color, (new_point.offset - prev.offset) / (next.offset - prev.offset)); - points.push_back(newPoint); + points.push_back(new_point); points.sort(); for (int i = 0; i < points.size(); i++) { - if (points[i].offset == newPoint.offset) { + if (points[i].offset == new_point.offset) { grabbed = i; break; } @@ -205,7 +209,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { emit_signal(SNAME("ramp_changed")); } - if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { if (grabbing) { grabbing = false; emit_signal(SNAME("ramp_changed")); @@ -223,7 +227,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { float newofs = CLAMP(x / float(total_w), 0, 1); // Snap to "round" coordinates if holding Ctrl. - // Be more precise if holding Shift as well + // Be more precise if holding Shift as well. if (mm->is_ctrl_pressed()) { newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1); } else if (mm->is_shift_pressed()) { @@ -283,119 +287,85 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } void GradientEdit::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - if (!picker->is_connected("color_changed", callable_mp(this, &GradientEdit::_color_changed))) { - picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed)); + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (!picker->is_connected("color_changed", callable_mp(this, &GradientEdit::_color_changed))) { + picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed)); + } + [[fallthrough]]; } - } + case NOTIFICATION_THEME_CHANGED: { + draw_spacing = BASE_SPACING * get_theme_default_base_scale(); + draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale(); + } break; - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - draw_spacing = BASE_SPACING * get_theme_default_base_scale(); - draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale(); - } + case NOTIFICATION_DRAW: { + int w = get_size().x; + int h = get_size().y; - if (p_what == NOTIFICATION_DRAW) { - int w = get_size().x; - int h = get_size().y; + if (w == 0 || h == 0) { + return; // Safety check. We have division by 'h'. And in any case there is nothing to draw with such size. + } - if (w == 0 || h == 0) { - return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size - } + int total_w = get_size().width - get_size().height - draw_spacing; - int total_w = get_size().width - get_size().height - draw_spacing; + // Draw checker pattern for ramp. + draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true); - //Draw checker pattern for ramp - draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true); + // Draw color ramp. + gradient_cache->set_points(points); + gradient_cache->set_interpolation_mode(interpolation_mode); + preview_texture->set_gradient(gradient_cache); + draw_texture_rect(preview_texture, Rect2(0, 0, total_w, h)); - //Draw color ramp - Gradient::Point prev; - prev.offset = 0; - if (points.size() == 0) { - prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points - } else { - prev.color = points[0].color; //Extend color of first point to the beginning. - } + // Draw point markers. + for (int i = 0; i < points.size(); i++) { + Color col = points[i].color.inverted(); + col.a = 0.9; - for (int i = -1; i < points.size(); i++) { - Gradient::Point next; - //If there is no next point - if (i + 1 == points.size()) { - if (points.size() == 0) { - next.color = Color(0, 0, 0); //Draw black rectangle if we have no points - } else { - next.color = points[i].color; //Extend color of last point to the end. + draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col); + Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2); + draw_rect(rect, points[i].color, true); + draw_rect(rect, col, false); + if (grabbed == i) { + rect = rect.grow(-1); + if (has_focus()) { + draw_rect(rect, Color(1, 0, 0, 0.9), false); + } else { + draw_rect(rect, Color(0.6, 0, 0, 0.9), false); + } + + rect = rect.grow(-1); + draw_rect(rect, col, false); } - next.offset = 1; - } else { - next = points[i + 1]; } - if (prev.offset == next.offset) { - prev = next; - continue; + // Draw "button" for color selector. + draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true); + if (grabbed != -1) { + // Draw with selection color. + draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color); + } else { + // If no color selected draw grey color with 'X' on top. + draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1)); + draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6)); } - Vector<Vector2> points; - Vector<Color> colors; - points.push_back(Vector2(prev.offset * total_w, h)); - points.push_back(Vector2(prev.offset * total_w, 0)); - points.push_back(Vector2(next.offset * total_w, 0)); - points.push_back(Vector2(next.offset * total_w, h)); - colors.push_back(prev.color); - colors.push_back(prev.color); - colors.push_back(next.color); - colors.push_back(next.color); - draw_primitive(points, colors, Vector<Point2>()); - prev = next; - } - - //Draw point markers - for (int i = 0; i < points.size(); i++) { - Color col = points[i].color.inverted(); - col.a = 0.9; - - draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col); - Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2); - draw_rect(rect, points[i].color, true); - draw_rect(rect, col, false); - if (grabbed == i) { - rect = rect.grow(-1); - if (has_focus()) { - draw_rect(rect, Color(1, 0, 0, 0.9), false); - } else { - draw_rect(rect, Color(0.6, 0, 0, 0.9), false); - } - - rect = rect.grow(-1); - draw_rect(rect, col, false); + // Draw borders around color ramp if in focus. + if (has_focus()) { + draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); } - } - - //Draw "button" for color selector - draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true); - if (grabbed != -1) { - //Draw with selection color - draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color); - } else { - //if no color selected draw grey color with 'X' on top. - draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1)); - draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6)); - draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6)); - } - - //Draw borders around color ramp if in focus - if (has_focus()) { - draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6)); - draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6)); - draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); - draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); - } - } + } break; - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (!is_visible()) { - grabbing = false; - } + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + grabbing = false; + } + } break; } } @@ -448,12 +418,25 @@ void GradientEdit::set_points(Vector<Gradient::Point> &p_points) { } points.clear(); points = p_points; + points.sort(); } Vector<Gradient::Point> &GradientEdit::get_points() { return points; } +void GradientEdit::set_interpolation_mode(Gradient::InterpolationMode p_interp_mode) { + interpolation_mode = p_interp_mode; +} + +Gradient::InterpolationMode GradientEdit::get_interpolation_mode() { + return interpolation_mode; +} + +ColorPicker *GradientEdit::get_picker() { + return picker; +} + void GradientEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("ramp_changed")); } |