diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 6f0be32e038..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" @@ -556,6 +557,15 @@ 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) { + double result = Math::remap(value, istart, istop, ostart, ostop); + if (Math::is_finite(result)) { + return result; + } + + return default_value; +} + double VariantUtilityFunctions::smoothstep(double from, double to, double val) { return Math::smoothstep(from, to, val); } @@ -1745,6 +1755,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..b0bcd70396f 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 [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 + [/codeblock] + For complex use cases where multiple ranges are needed, consider using [Curve] or [Gradient] instead. diff --git a/tests/core/variant/test_variant_utility.h b/tests/core/variant/test_variant_utility.h index 8c682293424..2be83476a95 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,19 @@ 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(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)); + 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