diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index cd6992c5bd3..6f8f3815a18 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -49,6 +49,9 @@ Changes the alignment of the underlying [LineEdit]. + + If [code]true[/code], the value will be rounded to a multiple of [member custom_arrow_step] when interacting with the arrow buttons. Otherwise, increments the value by [member custom_arrow_step] and then rounds it according to [member Range.step]. + If not [code]0[/code], sets the step when interacting with the arrow buttons of the [SpinBox]. [b]Note:[/b] [member Range.value] will still be rounded to a multiple of [member Range.step]. diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 97e51524149..dbc799e23d7 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -2170,6 +2170,7 @@ ColorPicker::ColorPicker() { intensity_slider->set_step(0.001); intensity_value->set_allow_greater(true); intensity_value->set_custom_arrow_step(1); + intensity_value->set_custom_arrow_round(true); hex_hbc = memnew(HBoxContainer); hex_hbc->set_alignment(ALIGNMENT_BEGIN); diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index f6dbacbad24..0a8b925f782 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -201,14 +201,7 @@ void SpinBox::_range_click_timeout() { bool mouse_on_down_button = down_button_rc.has_point(mpos); if (mouse_on_up_button || mouse_on_down_button) { - // Arrow button is being pressed. Snap the value to next step. - double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - temp_step = Math::snapped(temp_step, get_step()); - double new_value = _calc_value(get_value(), temp_step); - if ((mouse_on_up_button && new_value <= get_value() + CMP_EPSILON) || (!mouse_on_up_button && new_value >= get_value() - CMP_EPSILON)) { - new_value = _calc_value(get_value() + (mouse_on_up_button ? temp_step : -temp_step), temp_step); - } - set_value(new_value); + _arrow_clicked(mouse_on_up_button); } if (range_click_timer->is_one_shot()) { @@ -231,6 +224,22 @@ void SpinBox::_release_mouse_from_drag_mode() { } } +void SpinBox::_arrow_clicked(bool p_up) { + double arrow_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + if (custom_arrow_round) { + // Arrow button is being pressed, snap the value to next `arrow_step`. + // `arrow_step` should be a multiple of `step`, otherwise it may not be able to increase/decrease the value. + arrow_step = Math::snapped(arrow_step, get_step()); + double new_value = _calc_value(get_value(), arrow_step); + if ((p_up && new_value <= get_value()) || (!p_up && new_value >= get_value())) { + new_value = _calc_value(get_value() + (p_up ? arrow_step : -arrow_step), arrow_step); + } + set_value(new_value); + } else { + set_value(get_value() + (p_up ? arrow_step : -arrow_step)); + } +} + void SpinBox::_mouse_exited() { if (state_cache.up_button_hovered || state_cache.down_button_hovered) { state_cache.up_button_hovered = false; @@ -271,14 +280,7 @@ void SpinBox::gui_input(const Ref &p_event) { line_edit->grab_focus(true); if (mouse_on_up_button || mouse_on_down_button) { - // Arrow button is being pressed. Snap the value to next step. - double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - temp_step = Math::snapped(temp_step, get_step()); - double new_value = _calc_value(get_value(), temp_step); - if ((mouse_on_up_button && new_value <= get_value() + CMP_EPSILON) || (!mouse_on_up_button && new_value >= get_value() - CMP_EPSILON)) { - new_value = _calc_value(get_value() + (mouse_on_up_button ? temp_step : -temp_step), temp_step); - } - set_value(new_value); + _arrow_clicked(mouse_on_up_button); } state_cache.up_button_pressed = mouse_on_up_button; state_cache.down_button_pressed = mouse_on_down_button; @@ -614,6 +616,14 @@ double SpinBox::get_custom_arrow_step() const { return custom_arrow_step; } +void SpinBox::set_custom_arrow_round(bool p_round) { + custom_arrow_round = p_round; +} + +bool SpinBox::is_custom_arrow_rounding() const { + return custom_arrow_round; +} + void SpinBox::_value_changed(double p_value) { _update_buttons_state_for_current_value(); } @@ -646,6 +656,8 @@ void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_editable", "enabled"), &SpinBox::set_editable); ClassDB::bind_method(D_METHOD("set_custom_arrow_step", "arrow_step"), &SpinBox::set_custom_arrow_step); ClassDB::bind_method(D_METHOD("get_custom_arrow_step"), &SpinBox::get_custom_arrow_step); + ClassDB::bind_method(D_METHOD("set_custom_arrow_round", "round"), &SpinBox::set_custom_arrow_round); + ClassDB::bind_method(D_METHOD("is_custom_arrow_rounding"), &SpinBox::is_custom_arrow_rounding); ClassDB::bind_method(D_METHOD("is_editable"), &SpinBox::is_editable); ClassDB::bind_method(D_METHOD("set_update_on_text_changed", "enabled"), &SpinBox::set_update_on_text_changed); ClassDB::bind_method(D_METHOD("get_update_on_text_changed"), &SpinBox::get_update_on_text_changed); @@ -660,6 +672,7 @@ void SpinBox::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step", PROPERTY_HINT_RANGE, "0,10000,0.0001,or_greater"), "set_custom_arrow_step", "get_custom_arrow_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_arrow_round"), "set_custom_arrow_round", "is_custom_arrow_rounding"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_all_on_focus"), "set_select_all_on_focus", "is_select_all_on_focus"); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SpinBox, buttons_vertical_separation); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 60766d49ab6..032349db5bb 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -67,6 +67,7 @@ class SpinBox : public Range { Timer *range_click_timer = nullptr; void _range_click_timeout(); void _release_mouse_from_drag_mode(); + void _arrow_clicked(bool p_up); void _update_text(bool p_only_update_if_value_changed = false); void _text_submitted(const String &p_string); @@ -76,6 +77,7 @@ class SpinBox : public Range { String suffix; String last_text_value; double custom_arrow_step = 0.0; + bool custom_arrow_round = false; void _line_edit_input(const Ref &p_event); @@ -180,5 +182,8 @@ public: void set_custom_arrow_step(const double p_custom_arrow_step); double get_custom_arrow_step() const; + void set_custom_arrow_round(bool p_round); + bool is_custom_arrow_rounding() const; + SpinBox(); };