Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/classes/SpinBox.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
Changes the alignment of the underlying [LineEdit].
</member>
<member name="custom_arrow_round" type="bool" setter="set_custom_arrow_round" getter="is_custom_arrow_rounding" default="false">
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].
</member>
<member name="custom_arrow_step" type="float" setter="set_custom_arrow_step" getter="get_custom_arrow_step" default="0.0">
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].
Comment thread
beicause marked this conversation as resolved.
Expand Down
1 change: 1 addition & 0 deletions scene/gui/color_picker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
45 changes: 29 additions & 16 deletions scene/gui/spin_box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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;
Expand Down Expand Up @@ -271,14 +280,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions scene/gui/spin_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<InputEvent> &p_event);

Expand Down Expand Up @@ -180,5 +182,8 @@ class SpinBox : public Range {
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();
};