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

Add set_custom_interpolator() to PropertyTweener #82306

Merged
merged 1 commit into from
Feb 16, 2024
Merged
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
19 changes: 19 additions & 0 deletions doc/classes/PropertyTweener.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@
[/codeblock]
</description>
</method>
<method name="set_custom_interpolator">
<return type="PropertyTweener" />
<param index="0" name="interpolator_method" type="Callable" />
<description>
Allows interpolating the value with a custom easing function. The provided [param interpolator_method] will be called with a value ranging from [code]0.0[/code] to [code]1.0[/code] and is expected to return a value within the same range (values outside the range can be used for overshoot). The return value of the method is then used for interpolation between initial and final value. Note that the parameter passed to the method is still subject to the tweener's own easing.
[b]Example:[/b]
[codeblock]
@export var curve: Curve

func _ready():
var tween = create_tween()
# Interpolate the value using a custom curve.
tween.tween_property(self, "position:x", 300, 1).as_relative().set_custom_interpolator(tween_curve)

func tween_curve(v):
return curve.sample_baked(v)
[/codeblock]
</description>
</method>
<method name="set_delay">
<return type="PropertyTweener" />
<param index="0" name="delay" type="float" />
Expand Down
28 changes: 25 additions & 3 deletions scene/animation/tween.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@ Ref<PropertyTweener> PropertyTweener::set_ease(Tween::EaseType p_ease) {
return this;
}

Ref<PropertyTweener> PropertyTweener::set_custom_interpolator(const Callable &p_method) {
custom_method = p_method;
return this;
}

Ref<PropertyTweener> PropertyTweener::set_delay(double p_delay) {
delay = p_delay;
return this;
Expand Down Expand Up @@ -581,7 +586,23 @@ bool PropertyTweener::step(double &r_delta) {

double time = MIN(elapsed_time - delay, duration);
if (time < duration) {
target_instance->set_indexed(property, tween->interpolate_variant(initial_val, delta_val, time, duration, trans_type, ease_type));
if (custom_method.is_valid()) {
const Variant t = tween->interpolate_variant(0.0, 1.0, time, duration, trans_type, ease_type);
const Variant *argptr = &t;

Variant result;
Callable::CallError ce;
custom_method.callp(&argptr, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling custom method from PropertyTweener: " + Variant::get_callable_error_text(custom_method, &argptr, 1, ce) + ".");
} else if (result.get_type() != Variant::FLOAT) {
ERR_FAIL_V_MSG(false, vformat("Wrong return type in PropertyTweener custom method. Expected float, got %s.", Variant::get_type_name(result.get_type())));
}

target_instance->set_indexed(property, Animation::interpolate_variant(initial_val, final_val, result));
} else {
target_instance->set_indexed(property, tween->interpolate_variant(initial_val, delta_val, time, duration, trans_type, ease_type));
}
TokageItLab marked this conversation as resolved.
Show resolved Hide resolved
r_delta = 0;
return true;
} else {
Expand Down Expand Up @@ -609,6 +630,7 @@ void PropertyTweener::_bind_methods() {
ClassDB::bind_method(D_METHOD("as_relative"), &PropertyTweener::as_relative);
ClassDB::bind_method(D_METHOD("set_trans", "trans"), &PropertyTweener::set_trans);
ClassDB::bind_method(D_METHOD("set_ease", "ease"), &PropertyTweener::set_ease);
ClassDB::bind_method(D_METHOD("set_custom_interpolator", "interpolator_method"), &PropertyTweener::set_custom_interpolator);
ClassDB::bind_method(D_METHOD("set_delay", "delay"), &PropertyTweener::set_delay);
}

Expand Down Expand Up @@ -685,7 +707,7 @@ bool CallbackTweener::step(double &r_delta) {
Callable::CallError ce;
callback.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce));
ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce) + ".");
}

finished = true;
Expand Down Expand Up @@ -765,7 +787,7 @@ bool MethodTweener::step(double &r_delta) {
Callable::CallError ce;
callback.callp(argptr, 1, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce));
ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce) + ".");
}

if (time < duration) {
Expand Down
2 changes: 2 additions & 0 deletions scene/animation/tween.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ class PropertyTweener : public Tweener {
Ref<PropertyTweener> as_relative();
Ref<PropertyTweener> set_trans(Tween::TransitionType p_trans);
Ref<PropertyTweener> set_ease(Tween::EaseType p_ease);
Ref<PropertyTweener> set_custom_interpolator(const Callable &p_method);
Ref<PropertyTweener> set_delay(double p_delay);

void set_tween(const Ref<Tween> &p_tween) override;
Expand All @@ -222,6 +223,7 @@ class PropertyTweener : public Tweener {
double duration = 0;
Tween::TransitionType trans_type = Tween::TRANS_MAX; // This is set inside set_tween();
Tween::EaseType ease_type = Tween::EASE_MAX;
Callable custom_method;

double delay = 0;
bool do_continue = true;
Expand Down