From a4d436b251d6f12798a9bdf55c54c8a55d49922d Mon Sep 17 00:00:00 2001 From: Pijus Zacharka Date: Thu, 5 Mar 2026 20:20:10 +0200 Subject: [PATCH 1/5] added remap_default method that returns a default value if remap would've done a division by zero. --- core/variant/variant_utility.cpp | 8 ++++++++ core/variant/variant_utility.h | 1 + doc/classes/@GlobalScope.xml | 19 ++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 6f0be32e038..eb47f6a1aae 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -556,6 +556,13 @@ double VariantUtilityFunctions::remap(double value, double istart, double istop, return Math::remap(value, istart, istop, ostart, ostop); } +double VariantUtilityFunctions::remap_default(double value, double istart, double istop, double ostart, double ostop, double default_value) { + if (istart == istop) { + return default_value; + } + return Math::remap(value, istart, istop, ostart, ostop); +} + double VariantUtilityFunctions::smoothstep(double from, double to, double val) { return Math::smoothstep(from, to, val); } @@ -1745,6 +1752,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(remap_default, sarray("value", "istart", "istop", "ostart", "ostop", "default_value"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index 2a6c646999f..13e1d14c80d 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -95,6 +95,7 @@ struct VariantUtilityFunctions { static double lerp_angle(double from, double to, double weight); static double inverse_lerp(double from, double to, double weight); static double remap(double value, double istart, double istop, double ostart, double ostop); + static double remap_default(double value, double istart, double istop, double ostart, double ostop, double default_value); static double smoothstep(double from, double to, double val); static double move_toward(double from, double to, double delta); static double rotate_toward(double from, double to, double delta); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 270942b508e..ae397a8bf10 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1102,7 +1102,24 @@ remap(75, 0, 100, -1, 1) # Returns 0.5 [/codeblock] For complex use cases where multiple ranges are needed, consider using [Curve] or [Gradient] instead. - [b]Note:[/b] If [code]istart == istop[/code], the return value is undefined (most likely NaN, INF, or -INF). + [b]Note:[/b] If [code]istart == istop[/code], the return value is undefined (most likely NaN, INF, or -INF). See also [method remap_default]. + + + + + + + + + + + + Maps a [param value] from range [code][istart, istop][/code] to [code][ostart, ostop][/code] and returns [param default_value] if [code]istart == istop[/code]. See also [method remap], [method lerp] and [method inverse_lerp]. If [param value] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. If this is not desired, use [method clamp] on the result of this function. + [codeblock] + remap_default(75, 0, 100, -1, 1, 3) # Returns 0.5 + remap_default(75, 0, 0, -1, 1, 3) # Returns 3.0 + [/codeblock] + For complex use cases where multiple ranges are needed, consider using [Curve] or [Gradient] instead. From 0e69229fa00e9fb97b13d8b9e1c5bd6103666ce8 Mon Sep 17 00:00:00 2001 From: Pijus Zacharka Date: Mon, 9 Mar 2026 01:00:30 +0200 Subject: [PATCH 2/5] Changed remap_default to instead check if the result of remap is finite, changed the documentation to reflect this change, and added a few test cases to test_variant_utility, and they work on my machine --- core/variant/variant_utility.cpp | 9 ++++++--- doc/classes/@GlobalScope.xml | 2 +- tests/core/variant/test_variant_utility.h | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index eb47f6a1aae..7ec824f0717 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -33,6 +33,7 @@ #include "variant_utility.h" #include "core/io/marshalls.h" +#include "core/math/math_funcs.h" #include "core/object/ref_counted.h" #include "core/object/script_language.h" #include "core/os/os.h" @@ -557,10 +558,12 @@ double VariantUtilityFunctions::remap(double value, double istart, double istop, } double VariantUtilityFunctions::remap_default(double value, double istart, double istop, double ostart, double ostop, double default_value) { - if (istart == istop) { - return default_value; + double result = Math::remap(value, istart, istop, ostart, ostop); + if (Math::is_finite(result)) { + return result; } - return Math::remap(value, istart, istop, ostart, ostop); + + return default_value; } double VariantUtilityFunctions::smoothstep(double from, double to, double val) { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index ae397a8bf10..b0bcd70396f 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1114,7 +1114,7 @@ - Maps a [param value] from range [code][istart, istop][/code] to [code][ostart, ostop][/code] and returns [param default_value] if [code]istart == istop[/code]. See also [method remap], [method lerp] and [method inverse_lerp]. If [param value] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. If this is not desired, use [method clamp] on the result of this function. + Maps a [param value] from range [code][istart, istop][/code] to [code][ostart, ostop][/code] and returns [param default_value] if [method remap] would've returned [code]INF[/code] or [code]NAN[/code]. See also [method remap], [method lerp] and [method inverse_lerp]. If [param value] is outside [code][istart, istop][/code], then the resulting value will also be outside [code][ostart, ostop][/code]. If this is not desired, use [method clamp] on the result of this function. [codeblock] remap_default(75, 0, 100, -1, 1, 3) # Returns 0.5 remap_default(75, 0, 0, -1, 1, 3) # Returns 3.0 diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index 8c682293424..c924b83e809 100644 --- a/tests/core/variant/test_variant_utility.h +++ b/tests/core/variant/test_variant_utility.h @@ -32,6 +32,7 @@ #pragma once +#include "core/math/math_defs.h" #include "core/variant/variant_utility.h" #include "tests/test_macros.h" @@ -130,4 +131,20 @@ TEST_CASE("[VariantUtility] Type conversion") { } } +TEST_CASE_TEMPLATE("[VariantUtility] remap_default", T, float, double) { + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(500.0)); + CHECK(VariantUtilityFunctions::remap_default(250.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(1500.0)); + CHECK(VariantUtilityFunctions::remap_default(-50.0, -100.0, 0.0, 0.0, 100.0, -99.0) == doctest::Approx(50.0)); + + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 100.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + + CHECK(VariantUtilityFunctions::remap_default(INFINITY, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(NAN, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, NAN, 1000.0, -99.0) == doctest::Approx(-99.0)); + + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 0.0, 1000.0, -99.0) == doctest::Approx(0.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 50.0, 1000.0, -99.0) == doctest::Approx(50.0)); +} + + } // namespace TestVariantUtility From f5fccc50e00d7282534e85a4aeabc515ad89c454 Mon Sep 17 00:00:00 2001 From: Pijus Zacharka Date: Mon, 9 Mar 2026 12:52:02 +0200 Subject: [PATCH 3/5] fix styling to use tabs in tests... (?) --- tests/core/variant/test_variant_utility.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index c924b83e809..a0815bad366 100644 --- a/tests/core/variant/test_variant_utility.h +++ b/tests/core/variant/test_variant_utility.h @@ -132,18 +132,18 @@ TEST_CASE("[VariantUtility] Type conversion") { } TEST_CASE_TEMPLATE("[VariantUtility] remap_default", T, float, double) { - CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(500.0)); - CHECK(VariantUtilityFunctions::remap_default(250.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(1500.0)); - CHECK(VariantUtilityFunctions::remap_default(-50.0, -100.0, 0.0, 0.0, 100.0, -99.0) == doctest::Approx(50.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(500.0)); + CHECK(VariantUtilityFunctions::remap_default(250.0, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(1500.0)); + CHECK(VariantUtilityFunctions::remap_default(-50.0, -100.0, 0.0, 0.0, 100.0, -99.0) == doctest::Approx(50.0)); - CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 100.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 100.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); - CHECK(VariantUtilityFunctions::remap_default(INFINITY, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); - CHECK(VariantUtilityFunctions::remap_default(NAN, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); - CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, NAN, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(INFINITY, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(NAN, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 200.0, NAN, 1000.0, -99.0) == doctest::Approx(-99.0)); - CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 0.0, 1000.0, -99.0) == doctest::Approx(0.0)); - CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 50.0, 1000.0, -99.0) == doctest::Approx(50.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 0.0, 1000.0, -99.0) == doctest::Approx(0.0)); + CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 50.0, 1000.0, -99.0) == doctest::Approx(50.0)); } From 391bdadf7e2703be24141a7fab1bfc90aa37018e Mon Sep 17 00:00:00 2001 From: Pijus Zacharka Date: Mon, 9 Mar 2026 12:56:15 +0200 Subject: [PATCH 4/5] yeah i have no idea, fix some styling issue again --- tests/core/variant/test_variant_utility.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index a0815bad366..e21fb8761e7 100644 --- a/tests/core/variant/test_variant_utility.h +++ b/tests/core/variant/test_variant_utility.h @@ -145,6 +145,4 @@ TEST_CASE_TEMPLATE("[VariantUtility] remap_default", T, float, double) { CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 0.0, 1000.0, -99.0) == doctest::Approx(0.0)); CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, INFINITY, 50.0, 1000.0, -99.0) == doctest::Approx(50.0)); } - - } // namespace TestVariantUtility From e87d25c38fddd73df7bd29214206e2c53ef4e417 Mon Sep 17 00:00:00 2001 From: Pijus Zacharka Date: Mon, 9 Mar 2026 13:36:12 +0200 Subject: [PATCH 5/5] add one more test case as per CodeRabbits suggestion --- tests/core/variant/test_variant_utility.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index e21fb8761e7..2be83476a95 100644 --- a/tests/core/variant/test_variant_utility.h +++ b/tests/core/variant/test_variant_utility.h @@ -137,6 +137,7 @@ TEST_CASE_TEMPLATE("[VariantUtility] remap_default", T, float, double) { CHECK(VariantUtilityFunctions::remap_default(-50.0, -100.0, 0.0, 0.0, 100.0, -99.0) == doctest::Approx(50.0)); CHECK(VariantUtilityFunctions::remap_default(150.0, 100.0, 100.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); + CHECK(VariantUtilityFunctions::remap_default(100.0, 100.0, 100.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); CHECK(VariantUtilityFunctions::remap_default(INFINITY, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0)); CHECK(VariantUtilityFunctions::remap_default(NAN, 100.0, 200.0, 0.0, 1000.0, -99.0) == doctest::Approx(-99.0));