Skip to content

Commit

Permalink
Fix first assignment to _min/max_value in Curve bypassing `min < …
Browse files Browse the repository at this point in the history
…max` check
  • Loading branch information
anvilfolk committed Sep 29, 2024
1 parent 1fc8208 commit b3d0f47
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
37 changes: 31 additions & 6 deletions scene/resources/curve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,34 @@ void Curve::update_auto_tangents(int p_index) {

#define MIN_Y_RANGE 0.01

Array Curve::get_limits() const {
Array output;
output.resize(2);

output[0] = _min_value;
output[1] = _max_value;

return output;
}

void Curve::set_limits(const Array p_input) {
if (p_input.size() != 2) {
ERR_PRINT_ED(vformat(R"(Could not find Curve limit values when deserializing "%s". Resetting limits to default values.)", this->get_path()));
_min_value = 0;
_max_value = 1;
return;
}

// Don't need to check min < max because set_min/max_value already do this. When de/serializing, we simply read/write
// previously validated limits. This ensures those checks don't interfere with serialization.
_min_value = p_input[0];
_max_value = p_input[1];
}

void Curve::set_min_value(real_t p_min) {
if (_minmax_set_once & 0b11 && p_min > _max_value - MIN_Y_RANGE) {
if (p_min > _max_value - MIN_Y_RANGE) {
_min_value = _max_value - MIN_Y_RANGE;
} else {
_minmax_set_once |= 0b10; // first bit is "min set"
_min_value = p_min;
}
// Note: min and max are indicative values,
Expand All @@ -320,10 +343,9 @@ void Curve::set_min_value(real_t p_min) {
}

void Curve::set_max_value(real_t p_max) {
if (_minmax_set_once & 0b11 && p_max < _min_value + MIN_Y_RANGE) {
if (p_max < _min_value + MIN_Y_RANGE) {
_max_value = _min_value + MIN_Y_RANGE;
} else {
_minmax_set_once |= 0b01; // second bit is "max set"
_max_value = p_max;
}
emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
Expand Down Expand Up @@ -628,15 +650,18 @@ void Curve::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_min_value", "min"), &Curve::set_min_value);
ClassDB::bind_method(D_METHOD("get_max_value"), &Curve::get_max_value);
ClassDB::bind_method(D_METHOD("set_max_value", "max"), &Curve::set_max_value);
ClassDB::bind_method(D_METHOD("_get_limits"), &Curve::get_limits);
ClassDB::bind_method(D_METHOD("_set_limits", "data"), &Curve::set_limits);
ClassDB::bind_method(D_METHOD("clean_dupes"), &Curve::clean_dupes);
ClassDB::bind_method(D_METHOD("bake"), &Curve::bake);
ClassDB::bind_method(D_METHOD("get_bake_resolution"), &Curve::get_bake_resolution);
ClassDB::bind_method(D_METHOD("set_bake_resolution", "resolution"), &Curve::set_bake_resolution);
ClassDB::bind_method(D_METHOD("_get_data"), &Curve::get_data);
ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve::set_data);

ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01", PROPERTY_USAGE_EDITOR), "set_min_value", "get_min_value");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01", PROPERTY_USAGE_EDITOR), "set_max_value", "get_max_value");
ADD_PROPERTY(PropertyInfo(Variant::NIL, "_limits", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_limits", "_get_limits");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution");
ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
ADD_ARRAY_COUNT("Points", "point_count", "set_point_count", "get_point_count", "point_");
Expand Down
4 changes: 3 additions & 1 deletion scene/resources/curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ class Curve : public Resource {
real_t get_max_value() const { return _max_value; }
void set_max_value(real_t p_max);

Array get_limits() const;
void set_limits(Array input);

real_t get_range() const { return _max_value - _min_value; }

real_t sample(real_t p_offset) const;
Expand Down Expand Up @@ -156,7 +159,6 @@ class Curve : public Resource {
int _bake_resolution = 100;
real_t _min_value = 0.0;
real_t _max_value = 1.0;
int _minmax_set_once = 0b00; // Encodes whether min and max have been set a first time, first bit for min and second for max.
};

VARIANT_ENUM_CAST(Curve::TangentMode)
Expand Down

0 comments on commit b3d0f47

Please sign in to comment.