Add set_custom_interpolator() to PropertyTweener

This commit is contained in:
kobewi 2023-09-25 15:56:04 +02:00
parent b1371806ad
commit 58f4984d60
3 changed files with 46 additions and 3 deletions

View File

@ -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" />

View File

@ -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;
@ -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));
}
r_delta = 0;
return true;
} else {
@ -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);
}
@ -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;
@ -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) {

View File

@ -197,6 +197,7 @@ public:
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;
@ -222,6 +223,7 @@ private:
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;