From ef933c92352f2447363c73f4f6bcfab7a692345f Mon Sep 17 00:00:00 2001 From: Chaosus Date: Sun, 22 Feb 2026 19:50:05 +0300 Subject: [PATCH] Add smooth to the changing of properties values in visual shader --- doc/classes/EditorSpinSlider.xml | 3 +++ editor/gui/editor_spin_slider.cpp | 25 ++++++++++++++++++- editor/gui/editor_spin_slider.h | 3 +++ editor/inspector/editor_inspector.cpp | 10 ++++++++ editor/inspector/editor_inspector.h | 4 +++ editor/inspector/editor_properties.cpp | 12 +++++++++ editor/inspector/editor_properties.h | 2 ++ editor/inspector/editor_properties_vector.cpp | 8 ++++++ editor/inspector/editor_properties_vector.h | 1 + editor/shader/visual_shader_editor_plugin.cpp | 2 ++ 10 files changed, 69 insertions(+), 1 deletion(-) diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index c9762c40ff..c3bb8762c8 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -13,6 +13,9 @@ The state in which the control used to manipulate the value will be. + + If [code]true[/code], changing via dragging is applied only at the end of the input (for example, when the user releases a mouse button). + If [code]true[/code], the [EditorSpinSlider] is considered to be editing an integer value. If [code]false[/code], the [EditorSpinSlider] is considered to be editing a floating-point value. This is used to determine whether a slider should be drawn by default. The slider is only drawn for floats; integers use up-down arrows similar to [SpinBox] instead, unless [member control_state] is set to [constant CONTROL_STATE_PREFER_SLIDER]. It will also use [member EditorSettings.interface/inspector/integer_drag_speed] instead of [member EditorSettings.interface/inspector/float_drag_speed] if the slider is available. diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index 0b9206ea36..3c2d903170 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -91,7 +91,12 @@ void EditorSpinSlider::gui_input(const Ref &p_event) { } _grab_start(); } else { + bool grabbing = grabbing_spinner; _grab_end(); + + if (deferred_drag_mode && grabbing) { + _notify_shared_value_changed(); // Need to be emitted at the end, since the signal doesn't emitted in `set_value_no_signal` method. + } } } else if (mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed() && is_grabbing()) { @@ -132,7 +137,13 @@ void EditorSpinSlider::gui_input(const Ref &p_event) { const double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); const double drag_step = MAX(get_step(), default_float_step); const double new_value = pre_grab_value + drag_step * grabbing_spinner_dist_cache; - set_value((mm->is_command_or_control_pressed() && !editing_integer) ? Math::round(new_value) : new_value); + + double val = (mm->is_command_or_control_pressed() && !editing_integer) ? Math::round(new_value) : new_value; + if (deferred_drag_mode) { + set_value_no_signal(val); + } else { + set_value(val); + } } } else if (updown_offset != -1) { bool new_hover = (!is_layout_rtl() && mm->get_position().x > updown_offset) || (is_layout_rtl() && mm->get_position().x < updown_offset); @@ -693,6 +704,14 @@ bool EditorSpinSlider::is_grabbing() const { return grabbing_grabber || grabbing_spinner; } +void EditorSpinSlider::set_deferred_drag_mode_enabled(bool p_enabled) { + deferred_drag_mode = p_enabled; +} + +bool EditorSpinSlider::is_deferred_drag_mode_enabled() const { + return deferred_drag_mode; +} + void EditorSpinSlider::_focus_entered(bool p_hide_focus) { if (read_only) { return; @@ -731,6 +750,9 @@ void EditorSpinSlider::_bind_methods() { ClassDB::bind_method(D_METHOD("set_editing_integer", "editing_integer"), &EditorSpinSlider::set_editing_integer); ClassDB::bind_method(D_METHOD("is_editing_integer"), &EditorSpinSlider::is_editing_integer); + ClassDB::bind_method(D_METHOD("set_deferred_drag_mode_enabled", "enabled"), &EditorSpinSlider::set_deferred_drag_mode_enabled, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("is_deferred_drag_mode_enabled"), &EditorSpinSlider::is_deferred_drag_mode_enabled); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only"); @@ -740,6 +762,7 @@ void EditorSpinSlider::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_slider"), "set_hide_slider", "is_hiding_slider"); #endif ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editing_integer"), "set_editing_integer", "is_editing_integer"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_drag_mode"), "set_deferred_drag_mode_enabled", "is_deferred_drag_mode_enabled"); BIND_ENUM_CONSTANT(CONTROL_STATE_DEFAULT); BIND_ENUM_CONSTANT(CONTROL_STATE_PREFER_SLIDER); diff --git a/editor/gui/editor_spin_slider.h b/editor/gui/editor_spin_slider.h index dbb8149f89..c4635362dd 100644 --- a/editor/gui/editor_spin_slider.h +++ b/editor/gui/editor_spin_slider.h @@ -66,6 +66,7 @@ class EditorSpinSlider : public Range { uint64_t value_input_closed_frame = 0; bool value_input_dirty = false; bool value_input_focus_visible = false; + bool deferred_drag_mode = false; public: enum ControlState { @@ -137,6 +138,8 @@ public: bool is_flat() const; bool is_grabbing() const; + void set_deferred_drag_mode_enabled(bool p_enabled = true); + bool is_deferred_drag_mode_enabled() const; void setup_and_show() { _focus_entered(); } LineEdit *get_line_edit(); diff --git a/editor/inspector/editor_inspector.cpp b/editor/inspector/editor_inspector.cpp index 3daf727d9e..6d77338f25 100644 --- a/editor/inspector/editor_inspector.cpp +++ b/editor/inspector/editor_inspector.cpp @@ -1251,6 +1251,7 @@ bool EditorProperty::is_cache_valid() const { } return true; } + void EditorProperty::update_cache() { cache.clear(); if (object && property != StringName()) { @@ -1261,6 +1262,15 @@ void EditorProperty::update_cache() { } } } + +void EditorProperty::set_deferred_drag_mode_enabled(bool p_enabled) { + deferred_drag_mode = p_enabled; +} + +bool EditorProperty::is_deferred_drag_mode_enabled() const { + return deferred_drag_mode; +} + Variant EditorProperty::get_drag_data(const Point2 &p_point) { if (property == StringName()) { return Variant(); diff --git a/editor/inspector/editor_inspector.h b/editor/inspector/editor_inspector.h index 5e9df77e58..31b80c8a8d 100644 --- a/editor/inspector/editor_inspector.h +++ b/editor/inspector/editor_inspector.h @@ -195,6 +195,7 @@ private: bool selectable = true; bool selected = false; int selected_focusable; + bool deferred_drag_mode = false; float split_ratio; @@ -308,6 +309,9 @@ public: virtual void update_cache(); virtual bool is_cache_valid() const; + virtual void set_deferred_drag_mode_enabled(bool p_enabled = true); + bool is_deferred_drag_mode_enabled() const; + void set_selectable(bool p_selectable); bool is_selectable() const; diff --git a/editor/inspector/editor_properties.cpp b/editor/inspector/editor_properties.cpp index f02dbf5463..6fd2d82811 100644 --- a/editor/inspector/editor_properties.cpp +++ b/editor/inspector/editor_properties.cpp @@ -1561,6 +1561,12 @@ void EditorPropertyInteger::_value_changed(int64_t val) { emit_changed(get_edited_property(), val); } +void EditorPropertyInteger::set_deferred_drag_mode_enabled(bool p_enabled) { + EditorProperty::set_deferred_drag_mode_enabled(p_enabled); + + spin->set_deferred_drag_mode_enabled(p_enabled); +} + void EditorPropertyInteger::update_property() { int64_t val = get_edited_property_display_value(); spin->set_value_no_signal(val); @@ -1698,6 +1704,12 @@ void EditorPropertyFloat::_value_changed(double val) { emit_changed(get_edited_property(), val); } +void EditorPropertyFloat::set_deferred_drag_mode_enabled(bool p_enabled) { + EditorProperty::set_deferred_drag_mode_enabled(p_enabled); + + spin->set_deferred_drag_mode_enabled(p_enabled); +} + void EditorPropertyFloat::update_property() { double val = get_edited_property_value(); if (radians_as_degrees) { diff --git a/editor/inspector/editor_properties.h b/editor/inspector/editor_properties.h index 6cc35a37e5..62c818b1d3 100644 --- a/editor/inspector/editor_properties.h +++ b/editor/inspector/editor_properties.h @@ -404,6 +404,7 @@ protected: virtual void _set_read_only(bool p_read_only) override; public: + virtual void set_deferred_drag_mode_enabled(bool p_enabled = true) override; virtual void update_property() override; void setup(const EditorPropertyRangeHint &p_range_hint); EditorPropertyInteger(); @@ -455,6 +456,7 @@ protected: virtual void _set_read_only(bool p_read_only) override; public: + virtual void set_deferred_drag_mode_enabled(bool p_enabled = true) override; virtual void update_property() override; void setup(const EditorPropertyRangeHint &p_range_hint); EditorPropertyFloat(); diff --git a/editor/inspector/editor_properties_vector.cpp b/editor/inspector/editor_properties_vector.cpp index 351a660136..61e8dac055 100644 --- a/editor/inspector/editor_properties_vector.cpp +++ b/editor/inspector/editor_properties_vector.cpp @@ -239,6 +239,14 @@ EditorPropertyVectorN::EditorPropertyVectorN(Variant::Type p_type, bool p_force_ } } +void EditorPropertyVectorN::set_deferred_drag_mode_enabled(bool p_enabled) { + EditorProperty::set_deferred_drag_mode_enabled(p_enabled); + + for (int i = 0; i < component_count; i++) { + spin_sliders[i]->set_deferred_drag_mode_enabled(p_enabled); + } +} + EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) : EditorPropertyVectorN(Variant::VECTOR2, p_force_wide, EDITOR_GET("interface/inspector/horizontal_vector2_editing")) {} diff --git a/editor/inspector/editor_properties_vector.h b/editor/inspector/editor_properties_vector.h index 40c55d33f9..63444bd19c 100644 --- a/editor/inspector/editor_properties_vector.h +++ b/editor/inspector/editor_properties_vector.h @@ -59,6 +59,7 @@ protected: void _notification(int p_what); public: + virtual void set_deferred_drag_mode_enabled(bool p_enabled = true) override; virtual void update_property() override; void setup(const EditorPropertyRangeHint &p_range_hint, bool p_link = false, bool p_is_int = false); EditorPropertyVectorN(Variant::Type p_type, bool p_force_wide, bool p_horizontal); diff --git a/editor/shader/visual_shader_editor_plugin.cpp b/editor/shader/visual_shader_editor_plugin.cpp index 9c2fbc580a..113e9922d3 100644 --- a/editor/shader/visual_shader_editor_plugin.cpp +++ b/editor/shader/visual_shader_editor_plugin.cpp @@ -3405,6 +3405,7 @@ void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, // TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget. property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE, true); ERR_FAIL_NULL_MSG(property_editor, "Failed to create property editor for type: " + Variant::get_type_name(value.get_type())); + property_editor->set_deferred_drag_mode_enabled(); // Determine the best size for the popup based on the property type. // This is done here, since the property editors are also used in the inspector where they have different layout requirements, so we can't just change their default minimum size. @@ -8237,6 +8238,7 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref &p_par if (!prop) { return nullptr; } + prop->set_deferred_drag_mode_enabled(); if (Object::cast_to(prop)) { Object::cast_to(prop)->set_use_sub_inspector(false);