Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added pingpong built-in function #46346

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,19 @@ class Math {
return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
}

static _ALWAYS_INLINE_ float fract(float value) {
return value - floor(value);
}
static _ALWAYS_INLINE_ double fract(double value) {
return value - floor(value);
}
static _ALWAYS_INLINE_ float pingpong(float value, float length) {
return (length != 0.0f) ? abs(fract((value - length) / (length * 2.0f)) * length * 2.0f - length) : 0.0f;
}
static _ALWAYS_INLINE_ double pingpong(double value, double length) {
return (length != 0.0) ? abs(fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0;
}

// double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
static int step_decimals(double p_step);
Expand Down
5 changes: 5 additions & 0 deletions core/variant/variant_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ struct VariantUtilityFunctions {
return Math::wrapf(value, min, max);
}

static inline double pingpong(double value, double length) {
return Math::pingpong(value, length);
}

static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
Expand Down Expand Up @@ -1218,6 +1222,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);

FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(pingpong, sarray("value", "length"), Variant::UTILITY_FUNC_TYPE_MATH);

// Random

Expand Down
23 changes: 23 additions & 0 deletions doc/classes/@GlobalScope.xml
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,29 @@
[b]WARNING:[/b] Due to the way it is implemented, this function returns [code]0[/code] rather than [code]1[/code] for non-positive values of [code]value[/code] (in reality, 1 is the smallest integer power of 2).
</description>
</method>
<method name="pingpong">
<return type="float">
</return>
<argument index="0" name="value" type="float">
</argument>
<argument index="1" name="length" type="float">
</argument>
<description>
Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). If [code]length[/code] is less than zero, it becomes positive.
[codeblock]
pingpong(-3.0, 3.0) # Returns 3
pingpong(-2.0, 3.0) # Returns 2
pingpong(-1.0, 3.0) # Returns 1
pingpong(0.0, 3.0) # Returns 0
pingpong(1.0, 3.0) # Returns 1
pingpong(2.0, 3.0) # Returns 2
pingpong(3.0, 3.0) # Returns 3
pingpong(4.0, 3.0) # Returns 2
pingpong(5.0, 3.0) # Returns 1
pingpong(6.0, 3.0) # Returns 0
[/codeblock]
</description>
</method>
<method name="polar2cartesian">
<return type="Vector2">
</return>
Expand Down
18 changes: 18 additions & 0 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -680,5 +680,23 @@ public static real_t Wrap(real_t value, real_t min, real_t max)
real_t range = max - min;
return IsZeroApprox(range) ? min : min + ((value - min) % range + range) % range;
}

private static real_t Fract(real_t value)
{
return value - (real_t)Math.Floor(value);
}

/// <summary>
/// Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code].
/// If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave).
/// If [code]length[/code] is less than zero, it becomes positive.
/// </summary>
/// <param name="value">The value to pingpong.</param>
/// <param name="length">The maximum value of the function.</param>
/// <returns>The ping-ponged value.</returns>
public static real_t PingPong(real_t value, real_t length)
{
return (length != 0.0) ? Math.Abs(Mathf.Fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0;
}
}
}
47 changes: 25 additions & 22 deletions modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,71 +151,74 @@
</constant>
<constant name="MATH_WRAPF" value="45" enum="BuiltinFunc">
</constant>
<constant name="LOGIC_MAX" value="46" enum="BuiltinFunc">
<constant name="MATH_PINGPONG" value="46" enum="BuiltinFunc">
Return the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). If [code]length[/code] is less than zero, it becomes positive.
</constant>
<constant name="LOGIC_MAX" value="47" enum="BuiltinFunc">
Return the greater of the two numbers, also known as their maximum.
</constant>
<constant name="LOGIC_MIN" value="47" enum="BuiltinFunc">
<constant name="LOGIC_MIN" value="48" enum="BuiltinFunc">
Return the lesser of the two numbers, also known as their minimum.
</constant>
<constant name="LOGIC_CLAMP" value="48" enum="BuiltinFunc">
<constant name="LOGIC_CLAMP" value="49" enum="BuiltinFunc">
Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to [code]min(max(input, range_low), range_high)[/code].
</constant>
<constant name="LOGIC_NEAREST_PO2" value="49" enum="BuiltinFunc">
<constant name="LOGIC_NEAREST_PO2" value="50" enum="BuiltinFunc">
Return the nearest power of 2 to the input.
</constant>
<constant name="OBJ_WEAKREF" value="50" enum="BuiltinFunc">
<constant name="OBJ_WEAKREF" value="51" enum="BuiltinFunc">
Create a [WeakRef] from the input.
</constant>
<constant name="TYPE_CONVERT" value="51" enum="BuiltinFunc">
<constant name="TYPE_CONVERT" value="52" enum="BuiltinFunc">
Convert between types.
</constant>
<constant name="TYPE_OF" value="52" enum="BuiltinFunc">
<constant name="TYPE_OF" value="53" enum="BuiltinFunc">
Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned.
</constant>
<constant name="TYPE_EXISTS" value="53" enum="BuiltinFunc">
<constant name="TYPE_EXISTS" value="54" enum="BuiltinFunc">
Checks if a type is registered in the [ClassDB].
</constant>
<constant name="TEXT_CHAR" value="54" enum="BuiltinFunc">
<constant name="TEXT_CHAR" value="55" enum="BuiltinFunc">
Return a character with the given ascii value.
</constant>
<constant name="TEXT_STR" value="55" enum="BuiltinFunc">
<constant name="TEXT_STR" value="56" enum="BuiltinFunc">
Convert the input to a string.
</constant>
<constant name="TEXT_PRINT" value="56" enum="BuiltinFunc">
<constant name="TEXT_PRINT" value="57" enum="BuiltinFunc">
Print the given string to the output window.
</constant>
<constant name="TEXT_PRINTERR" value="57" enum="BuiltinFunc">
<constant name="TEXT_PRINTERR" value="58" enum="BuiltinFunc">
Print the given string to the standard error output.
</constant>
<constant name="TEXT_PRINTRAW" value="58" enum="BuiltinFunc">
<constant name="TEXT_PRINTRAW" value="59" enum="BuiltinFunc">
Print the given string to the standard output, without adding a newline.
</constant>
<constant name="VAR_TO_STR" value="59" enum="BuiltinFunc">
<constant name="VAR_TO_STR" value="60" enum="BuiltinFunc">
Serialize a [Variant] to a string.
</constant>
<constant name="STR_TO_VAR" value="60" enum="BuiltinFunc">
<constant name="STR_TO_VAR" value="61" enum="BuiltinFunc">
Deserialize a [Variant] from a string serialized using [constant VAR_TO_STR].
</constant>
<constant name="VAR_TO_BYTES" value="61" enum="BuiltinFunc">
<constant name="VAR_TO_BYTES" value="62" enum="BuiltinFunc">
Serialize a [Variant] to a [PackedByteArray].
</constant>
<constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc">
<constant name="BYTES_TO_VAR" value="63" enum="BuiltinFunc">
Deserialize a [Variant] from a [PackedByteArray] serialized using [constant VAR_TO_BYTES].
</constant>
<constant name="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc">
<constant name="MATH_SMOOTHSTEP" value="64" enum="BuiltinFunc">
Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula:
[codeblock]
var t = clamp((weight - from) / (to - from), 0.0, 1.0)
return t * t * (3.0 - 2.0 * t)
[/codeblock]
</constant>
<constant name="MATH_POSMOD" value="64" enum="BuiltinFunc">
<constant name="MATH_POSMOD" value="65" enum="BuiltinFunc">
</constant>
<constant name="MATH_LERP_ANGLE" value="65" enum="BuiltinFunc">
<constant name="MATH_LERP_ANGLE" value="66" enum="BuiltinFunc">
</constant>
<constant name="TEXT_ORD" value="66" enum="BuiltinFunc">
<constant name="TEXT_ORD" value="67" enum="BuiltinFunc">
</constant>
<constant name="FUNC_MAX" value="67" enum="BuiltinFunc">
<constant name="FUNC_MAX" value="68" enum="BuiltinFunc">
Represents the size of the [enum BuiltinFunc] enum.
</constant>
</constants>
Expand Down
17 changes: 17 additions & 0 deletions modules/visual_script/visual_script_builtin_funcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"cartesian2polar",
"wrapi",
"wrapf",
"pingpong",
"max",
"min",
"clamp",
Expand Down Expand Up @@ -196,6 +197,7 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case MATH_RANDI_RANGE:
case MATH_POLAR2CARTESIAN:
case MATH_CARTESIAN2POLAR:
case MATH_PINGPONG:
case LOGIC_MAX:
case LOGIC_MIN:
case TYPE_CONVERT:
Expand Down Expand Up @@ -405,6 +407,13 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::FLOAT, "y");
}
} break;
case MATH_PINGPONG: {
if (p_idx == 0) {
return PropertyInfo(Variant::FLOAT, "value");
} else {
return PropertyInfo(Variant::FLOAT, "length");
}
} break;
case MATH_WRAP: {
if (p_idx == 0) {
return PropertyInfo(Variant::INT, "value");
Expand Down Expand Up @@ -564,6 +573,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_RAD2DEG:
case MATH_LINEAR2DB:
case MATH_WRAPF:
case MATH_PINGPONG:
case MATH_DB2LINEAR: {
t = Variant::FLOAT;
} break;
Expand Down Expand Up @@ -908,6 +918,11 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
double y = *p_inputs[1];
*r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
} break;
case VisualScriptBuiltinFunc::MATH_PINGPONG: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
*r_return = Math::pingpong((double)*p_inputs[0], (double)*p_inputs[1]);
} break;
case VisualScriptBuiltinFunc::MATH_WRAP: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
Expand Down Expand Up @@ -1254,6 +1269,7 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_CARTESIAN2POLAR);
BIND_ENUM_CONSTANT(MATH_WRAP);
BIND_ENUM_CONSTANT(MATH_WRAPF);
BIND_ENUM_CONSTANT(MATH_PINGPONG);
BIND_ENUM_CONSTANT(LOGIC_MAX);
BIND_ENUM_CONSTANT(LOGIC_MIN);
BIND_ENUM_CONSTANT(LOGIC_CLAMP);
Expand Down Expand Up @@ -1346,6 +1362,7 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/cartesian2polar", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAPF>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/pingpong", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_PINGPONG>);

VisualScriptLanguage::singleton->add_register_func("functions/built_in/max", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/min", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>);
Expand Down
1 change: 1 addition & 0 deletions modules/visual_script/visual_script_builtin_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class VisualScriptBuiltinFunc : public VisualScriptNode {
MATH_CARTESIAN2POLAR,
MATH_WRAP,
MATH_WRAPF,
MATH_PINGPONG,
LOGIC_MAX,
LOGIC_MIN,
LOGIC_CLAMP,
Expand Down