mirror of
https://github.com/Redot-Engine/redot-engine.git
synced 2025-12-06 23:31:53 -05:00
Merge pull request #109100 from aaronfranke/range-snap
Fix snapping logic in Range
This commit is contained in:
@@ -64,7 +64,7 @@
|
|||||||
</member>
|
</member>
|
||||||
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="0" />
|
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="0" />
|
||||||
<member name="step" type="float" setter="set_step" getter="get_step" default="0.01">
|
<member name="step" type="float" setter="set_step" getter="get_step" default="0.01">
|
||||||
If greater than 0, [member value] will always be rounded to a multiple of this property's value. If [member rounded] is also [code]true[/code], [member value] will first be rounded to a multiple of this property's value, then rounded to the nearest integer.
|
If greater than 0, [member value] will always be rounded to a multiple of this property's value above [member min_value]. For example, if [member min_value] is [code]0.1[/code] and step is 0.2, then [member value] is limited to [code]0.1[/code], [code]0.3[/code], [code]0.5[/code], and so on. If [member rounded] is also [code]true[/code], [member value] will first be rounded to a multiple of this property's value, then rounded to the nearest integer.
|
||||||
</member>
|
</member>
|
||||||
<member name="value" type="float" setter="set_value" getter="get_value" default="0.0">
|
<member name="value" type="float" setter="set_value" getter="get_value" default="0.0">
|
||||||
Range's current value. Changing this property (even via code) will trigger [signal value_changed] signal. Use [method set_value_no_signal] if you want to avoid it.
|
Range's current value. Changing this property (even via code) will trigger [signal value_changed] signal. Use [method set_value_no_signal] if you want to avoid it.
|
||||||
|
|||||||
@@ -30,6 +30,28 @@
|
|||||||
|
|
||||||
#include "range.h"
|
#include "range.h"
|
||||||
|
|
||||||
|
#include "thirdparty/misc/r128.h"
|
||||||
|
|
||||||
|
double Range::_snapped_r128(double p_value, double p_step) {
|
||||||
|
if (p_step != 0) {
|
||||||
|
// All these lines are the equivalent of: p_value = Math::floor(p_value / p_step + 0.5) * p_step;
|
||||||
|
// Convert to String to force rounding to a decimal value (not a binary one).
|
||||||
|
String step_str = String::num(p_step);
|
||||||
|
String value_str = String::num(p_value);
|
||||||
|
R128 step_r128;
|
||||||
|
R128 value_r128;
|
||||||
|
const R128 half_r128 = R128(0.5);
|
||||||
|
r128FromString(&step_r128, step_str.ascii().get_data(), nullptr);
|
||||||
|
r128FromString(&value_r128, value_str.ascii().get_data(), nullptr);
|
||||||
|
r128Div(&value_r128, &value_r128, &step_r128);
|
||||||
|
r128Add(&value_r128, &value_r128, &half_r128);
|
||||||
|
r128Floor(&value_r128, &value_r128);
|
||||||
|
r128Mul(&value_r128, &value_r128, &step_r128);
|
||||||
|
p_value = value_r128;
|
||||||
|
}
|
||||||
|
return p_value;
|
||||||
|
}
|
||||||
|
|
||||||
PackedStringArray Range::get_configuration_warnings() const {
|
PackedStringArray Range::get_configuration_warnings() const {
|
||||||
PackedStringArray warnings = Control::get_configuration_warnings();
|
PackedStringArray warnings = Control::get_configuration_warnings();
|
||||||
|
|
||||||
@@ -140,7 +162,8 @@ void Range::_set_value_no_signal(double p_val) {
|
|||||||
|
|
||||||
double Range::_calc_value(double p_val, double p_step) const {
|
double Range::_calc_value(double p_val, double p_step) const {
|
||||||
if (p_step > 0) {
|
if (p_step > 0) {
|
||||||
p_val = Math::round((p_val - shared->min) / p_step) * p_step + shared->min;
|
// Subtract min to support cases like min = 0.1, step = 0.2, snaps to 0.1, 0.3, 0.5, etc.
|
||||||
|
p_val = _snapped_r128(p_val - shared->min, p_step) + shared->min;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_rounded_values) {
|
if (_rounded_values) {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class Range : public Control {
|
|||||||
void _set_value_no_signal(double p_val);
|
void _set_value_no_signal(double p_val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static double _snapped_r128(double p_value, double p_step);
|
||||||
double _calc_value(double p_val, double p_step) const;
|
double _calc_value(double p_val, double p_step) const;
|
||||||
virtual void _value_changed(double p_value);
|
virtual void _value_changed(double p_value);
|
||||||
void _notify_shared_value_changed() { shared->emit_value_changed(); }
|
void _notify_shared_value_changed() { shared->emit_value_changed(); }
|
||||||
|
|||||||
Reference in New Issue
Block a user