diff options
Diffstat (limited to 'editor/editor_spin_slider.cpp')
-rw-r--r-- | editor/editor_spin_slider.cpp | 148 |
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; |