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