summaryrefslogtreecommitdiff
path: root/editor/editor_spin_slider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_spin_slider.cpp')
-rw-r--r--editor/editor_spin_slider.cpp148
1 files changed, 77 insertions, 71 deletions
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 5db18d8853..d76a3d2da7 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -29,11 +29,16 @@
/*************************************************************************/
#include "editor_spin_slider.h"
+
+#include "core/input/input.h"
#include "core/math/expression.h"
-#include "core/os/input.h"
+#include "editor_node.h"
#include "editor_scale.h"
String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
+ if (grabber->is_visible()) {
+ return rtos(get_value()) + "\n\n" + TTR("Hold Ctrl to round to integers. Hold Shift for more precise changes.");
+ }
return rtos(get_value());
}
@@ -42,16 +47,14 @@ String EditorSpinSlider::get_text_value() const {
}
void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
-
- if (read_only)
+ if (read_only) {
return;
+ }
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
-
if (mb->get_button_index() == BUTTON_LEFT) {
if (mb->is_pressed()) {
-
if (updown_offset != -1 && mb->get_position().x > updown_offset) {
//there is an updown, so use it.
if (mb->get_position().y < get_size().height / 2) {
@@ -61,7 +64,6 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
}
return;
} else {
-
grabbing_spinner_attempt = true;
grabbing_spinner_dist_cache = 0;
pre_grab_value = get_value();
@@ -69,11 +71,8 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
grabbing_spinner_mouse_pos = Input::get_singleton()->get_mouse_position();
}
} else {
-
if (grabbing_spinner_attempt) {
-
if (grabbing_spinner) {
-
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse_position(grabbing_spinner_mouse_pos);
update();
@@ -86,17 +85,15 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
}
}
} else if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN) {
-
- if (grabber->is_visible())
+ if (grabber->is_visible()) {
call_deferred("update");
+ }
}
}
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
-
if (grabbing_spinner_attempt) {
-
double diff_x = mm->get_relative().x;
if (mm->get_shift() && grabbing_spinner) {
diff_x *= 0.1;
@@ -109,7 +106,21 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
}
if (grabbing_spinner) {
+ // Don't make the user scroll all the way back to 'in range' if they went off the end.
+ if (pre_grab_value < get_min() && !is_lesser_allowed()) {
+ pre_grab_value = get_min();
+ }
+ if (pre_grab_value > get_max() && !is_greater_allowed()) {
+ pre_grab_value = get_max();
+ }
+
if (mm->get_control()) {
+ // If control was just pressed, don't make the value do a huge jump in magnitude.
+ if (grabbing_spinner_dist_cache != 0) {
+ pre_grab_value += grabbing_spinner_dist_cache * get_step();
+ grabbing_spinner_dist_cache = 0;
+ }
+
set_value(Math::round(pre_grab_value + get_step() * grabbing_spinner_dist_cache * 10));
} else {
set_value(pre_grab_value + get_step() * grabbing_spinner_dist_cache);
@@ -131,12 +142,10 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
}
void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
-
Ref<InputEventMouseButton> mb = p_event;
if (grabbing_grabber) {
if (mb.is_valid()) {
-
if (mb->get_button_index() == BUTTON_WHEEL_UP) {
set_value(get_value() + get_step());
mousewheel_over_grabber = true;
@@ -148,9 +157,7 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
-
if (mb->is_pressed()) {
-
grabbing_grabber = true;
if (!mousewheel_over_grabber) {
grabbing_ratio = get_as_ratio();
@@ -164,8 +171,9 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid() && grabbing_grabber) {
- if (mousewheel_over_grabber)
+ if (mousewheel_over_grabber) {
return;
+ }
float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range);
set_as_ratio(grabbing_ratio + grabbing_ofs);
@@ -174,33 +182,45 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
}
void EditorSpinSlider::_notification(int p_what) {
-
- if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT ||
- p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN ||
+ if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT ||
+ p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN ||
p_what == NOTIFICATION_EXIT_TREE) {
if (grabbing_spinner) {
+ grabber->hide();
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
grabbing_spinner = false;
grabbing_spinner_attempt = false;
}
}
- if (p_what == NOTIFICATION_DRAW) {
+ if (p_what == NOTIFICATION_READY) {
+ // Add a left margin to the stylebox to make the number align with the Label
+ // when it's edited. The LineEdit "focus" stylebox uses the "normal" stylebox's
+ // default margins.
+ Ref<StyleBoxFlat> stylebox =
+ EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "LineEdit")->duplicate();
+ // EditorSpinSliders with a label have more space on the left, so add an
+ // higher margin to match the location where the text begins.
+ // The margin values below were determined by empirical testing.
+ stylebox->set_default_margin(MARGIN_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
+ value_input->add_theme_style_override("normal", stylebox);
+ }
+ if (p_what == NOTIFICATION_DRAW) {
updown_offset = -1;
- Ref<StyleBox> sb = get_stylebox("normal", "LineEdit");
+ Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit");
if (!flat) {
draw_style_box(sb, Rect2(Vector2(), get_size()));
}
- Ref<Font> font = get_font("font", "LineEdit");
+ Ref<Font> font = get_theme_font("font", "LineEdit");
int sep_base = 4 * EDSCALE;
int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
int string_width = font->get_string_size(label).width;
int number_width = get_size().width - sb->get_minimum_size().width - string_width - sep;
- Ref<Texture> updown = get_icon("updown", "SpinBox");
+ Ref<Texture2D> updown = get_theme_icon("updown", "SpinBox");
if (get_step() == 1) {
number_width -= updown->get_width();
@@ -210,7 +230,7 @@ void EditorSpinSlider::_notification(int p_what) {
int vofs = (get_size().height - font->get_height()) / 2 + font->get_ascent();
- Color fc = get_color("font_color", "LineEdit");
+ Color fc = get_theme_color("font_color", "LineEdit");
Color lc;
if (use_custom_label_color) {
lc = custom_label_color;
@@ -219,12 +239,12 @@ void EditorSpinSlider::_notification(int p_what) {
}
if (flat && label != String()) {
- Color label_bg_color = get_color("dark_color_3", "Editor");
+ Color label_bg_color = get_theme_color("dark_color_3", "Editor");
draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + string_width, get_size().height)), label_bg_color);
}
if (has_focus()) {
- Ref<StyleBox> focus = get_stylebox("focus", "LineEdit");
+ Ref<StyleBox> focus = get_theme_stylebox("focus", "LineEdit");
draw_style_box(focus, Rect2(Vector2(), get_size()));
}
@@ -233,7 +253,7 @@ void EditorSpinSlider::_notification(int p_what) {
draw_string(font, Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs), numstr, fc, number_width);
if (get_step() == 1) {
- Ref<Texture> updown2 = get_icon("updown", "SpinBox");
+ Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox");
int updown_vofs = (get_size().height - updown2->get_height()) / 2;
updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown2->get_width();
Color c(1, 1, 1);
@@ -258,7 +278,7 @@ void EditorSpinSlider::_notification(int p_what) {
Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
draw_rect(grabber_rect, c);
- bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input->is_visible();
+ bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input_popup->is_visible();
if (grabber->is_visible() != display_grabber) {
if (display_grabber) {
grabber->show();
@@ -268,11 +288,11 @@ void EditorSpinSlider::_notification(int p_what) {
}
if (display_grabber) {
- Ref<Texture> grabber_tex;
+ Ref<Texture2D> grabber_tex;
if (mouse_over_grabber) {
- grabber_tex = get_icon("grabber_highlight", "HSlider");
+ grabber_tex = get_theme_icon("grabber_highlight", "HSlider");
} else {
- grabber_tex = get_icon("grabber", "HSlider");
+ grabber_tex = get_theme_icon("grabber", "HSlider");
}
if (grabber->get_texture() != grabber_tex) {
@@ -292,21 +312,14 @@ void EditorSpinSlider::_notification(int p_what) {
}
if (p_what == NOTIFICATION_MOUSE_ENTER) {
-
mouse_over_spin = true;
update();
}
if (p_what == NOTIFICATION_MOUSE_EXIT) {
-
mouse_over_spin = false;
update();
}
if (p_what == NOTIFICATION_FOCUS_ENTER) {
- /* Sorry, I don't like this, it makes navigating the different fields with arrows more difficult.
- * Just press enter to edit.
- * if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && !value_input_just_closed) {
- _focus_entered();
- }*/
if ((Input::get_singleton()->is_action_pressed("ui_focus_next") || Input::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) {
_focus_entered();
}
@@ -315,9 +328,8 @@ void EditorSpinSlider::_notification(int p_what) {
}
Size2 EditorSpinSlider::get_minimum_size() const {
-
- Ref<StyleBox> sb = get_stylebox("normal", "LineEdit");
- Ref<Font> font = get_font("font", "LineEdit");
+ Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit");
+ Ref<Font> font = get_theme_font("font", "LineEdit");
Size2 ms = sb->get_minimum_size();
ms.height += font->get_height();
@@ -352,16 +364,17 @@ void EditorSpinSlider::_evaluate_input_text() {
return;
}
- Variant v = expr->execute(Array(), NULL, false);
- if (v.get_type() == Variant::NIL)
+ Variant v = expr->execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
return;
+ }
set_value(v);
}
//text_entered signal
void EditorSpinSlider::_value_input_entered(const String &p_text) {
value_input_just_closed = true;
- value_input->hide();
+ value_input_popup->hide();
}
//modal_closed signal
@@ -372,10 +385,10 @@ void EditorSpinSlider::_value_input_closed() {
//focus_exited signal
void EditorSpinSlider::_value_focus_exited() {
-
// discontinue because the focus_exit was caused by right-click context menu
- if (value_input->get_menu()->is_visible())
+ if (value_input->get_menu()->is_visible()) {
return;
+ }
_evaluate_input_text();
// focus is not on the same element after the vlalue_input was exited
@@ -384,7 +397,7 @@ void EditorSpinSlider::_value_focus_exited() {
// -> modal_close was not called
// -> need to close/hide manually
if (!value_input_just_closed) { //value_input_just_closed should do the same
- value_input->hide();
+ value_input_popup->hide();
//tab was pressed
} else {
//enter, click, esc
@@ -402,7 +415,6 @@ void EditorSpinSlider::_grabber_mouse_exited() {
}
void EditorSpinSlider::set_read_only(bool p_enable) {
-
read_only = p_enable;
update();
}
@@ -412,7 +424,6 @@ bool EditorSpinSlider::is_read_only() const {
}
void EditorSpinSlider::set_flat(bool p_enable) {
-
flat = p_enable;
update();
}
@@ -427,11 +438,11 @@ void EditorSpinSlider::set_custom_label_color(bool p_use_custom_label_color, Col
}
void EditorSpinSlider::_focus_entered() {
- Rect2 gr = get_global_rect();
+ Rect2 gr = get_screen_rect();
value_input->set_text(get_text_value());
- value_input->set_position(gr.position);
- value_input->set_size(gr.size);
- value_input->call_deferred("show_modal");
+ value_input_popup->set_position(gr.position);
+ value_input_popup->set_size(gr.size);
+ value_input_popup->call_deferred("popup");
value_input->call_deferred("grab_focus");
value_input->call_deferred("select_all");
value_input->set_focus_next(find_next_valid_focus()->get_path());
@@ -449,12 +460,6 @@ void EditorSpinSlider::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_flat"), &EditorSpinSlider::is_flat);
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input);
- ClassDB::bind_method(D_METHOD("_grabber_mouse_entered"), &EditorSpinSlider::_grabber_mouse_entered);
- ClassDB::bind_method(D_METHOD("_grabber_mouse_exited"), &EditorSpinSlider::_grabber_mouse_exited);
- ClassDB::bind_method(D_METHOD("_grabber_gui_input"), &EditorSpinSlider::_grabber_gui_input);
- ClassDB::bind_method(D_METHOD("_value_input_closed"), &EditorSpinSlider::_value_input_closed);
- ClassDB::bind_method(D_METHOD("_value_input_entered"), &EditorSpinSlider::_value_input_entered);
- ClassDB::bind_method(D_METHOD("_value_focus_exited"), &EditorSpinSlider::_value_focus_exited);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only");
@@ -462,7 +467,6 @@ void EditorSpinSlider::_bind_methods() {
}
EditorSpinSlider::EditorSpinSlider() {
-
flat = false;
grabbing_spinner_attempt = false;
grabbing_spinner = false;
@@ -476,21 +480,23 @@ EditorSpinSlider::EditorSpinSlider() {
grabber->hide();
grabber->set_as_toplevel(true);
grabber->set_mouse_filter(MOUSE_FILTER_STOP);
- grabber->connect("mouse_entered", this, "_grabber_mouse_entered");
- grabber->connect("mouse_exited", this, "_grabber_mouse_exited");
- grabber->connect("gui_input", this, "_grabber_gui_input");
+ grabber->connect("mouse_entered", callable_mp(this, &EditorSpinSlider::_grabber_mouse_entered));
+ grabber->connect("mouse_exited", callable_mp(this, &EditorSpinSlider::_grabber_mouse_exited));
+ grabber->connect("gui_input", callable_mp(this, &EditorSpinSlider::_grabber_gui_input));
mouse_over_spin = false;
mouse_over_grabber = false;
mousewheel_over_grabber = false;
grabbing_grabber = false;
grabber_range = 1;
+ value_input_popup = memnew(Popup);
+ add_child(value_input_popup);
value_input = memnew(LineEdit);
- add_child(value_input);
- value_input->set_as_toplevel(true);
- value_input->hide();
- value_input->connect("modal_closed", this, "_value_input_closed");
- value_input->connect("text_entered", this, "_value_input_entered");
- value_input->connect("focus_exited", this, "_value_focus_exited");
+ value_input_popup->add_child(value_input);
+ value_input_popup->set_wrap_controls(true);
+ value_input->set_anchors_and_margins_preset(PRESET_WIDE);
+ value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
+ value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered));
+ value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
value_input_just_closed = false;
hide_slider = false;
read_only = false;