2014-08-20 06:01:41 +02:00
/*************************************************************************/
/* tween.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-08-20 06:01:41 +02:00
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-08-20 06:01:41 +02:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-08-20 06:01:41 +02:00
# include "tween.h"
2018-09-11 18:13:45 +02:00
2021-09-24 13:23:49 +02:00
# include "scene/animation/easing_equations.h"
2020-09-05 03:05:30 +02:00
# include "scene/main/node.h"
2019-06-09 05:11:42 +02:00
2021-09-24 13:23:49 +02:00
Tween : : interpolater Tween : : interpolaters [ Tween : : TRANS_MAX ] [ Tween : : EASE_MAX ] = {
{ & linear : : in , & linear : : in , & linear : : in , & linear : : in } , // Linear is the same for each easing.
{ & sine : : in , & sine : : out , & sine : : in_out , & sine : : out_in } ,
{ & quint : : in , & quint : : out , & quint : : in_out , & quint : : out_in } ,
{ & quart : : in , & quart : : out , & quart : : in_out , & quart : : out_in } ,
{ & quad : : in , & quad : : out , & quad : : in_out , & quad : : out_in } ,
{ & expo : : in , & expo : : out , & expo : : in_out , & expo : : out_in } ,
{ & elastic : : in , & elastic : : out , & elastic : : in_out , & elastic : : out_in } ,
{ & cubic : : in , & cubic : : out , & cubic : : in_out , & cubic : : out_in } ,
{ & circ : : in , & circ : : out , & circ : : in_out , & circ : : out_in } ,
{ & bounce : : in , & bounce : : out , & bounce : : in_out , & bounce : : out_in } ,
{ & back : : in , & back : : out , & back : : in_out , & back : : out_in } ,
} ;
2020-09-05 03:05:30 +02:00
void Tweener : : set_tween ( Ref < Tween > p_tween ) {
tween = p_tween ;
}
2021-08-05 13:05:14 +02:00
void Tweener : : clear_tween ( ) {
tween . unref ( ) ;
}
2020-09-05 03:05:30 +02:00
void Tweener : : _bind_methods ( ) {
ADD_SIGNAL ( MethodInfo ( " finished " ) ) ;
}
void Tween : : start_tweeners ( ) {
if ( tweeners . is_empty ( ) ) {
dead = true ;
ERR_FAIL_MSG ( " Tween without commands, aborting. " ) ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
2021-07-26 17:50:35 +02:00
for ( Ref < Tweener > & tweener : tweeners . write [ current_step ] ) {
tweener - > start ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-05 05:12:17 +02:00
}
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > Tween : : tween_property ( Object * p_target , NodePath p_property , Variant p_to , float p_duration ) {
ERR_FAIL_NULL_V ( p_target , nullptr ) ;
2021-08-05 13:05:14 +02:00
ERR_FAIL_COND_V_MSG ( ! valid , nullptr , " Tween invalid. Either finished or created outside scene tree. " ) ;
2020-09-05 03:05:30 +02:00
ERR_FAIL_COND_V_MSG ( started , nullptr , " Can't append to a Tween that has started. Use stop() first. " ) ;
2019-06-09 05:11:42 +02:00
2021-09-16 01:15:31 +02:00
# ifdef DEBUG_ENABLED
Variant : : Type property_type = p_target - > get_indexed ( p_property . get_as_property_path ( ) . get_subnames ( ) ) . get_type ( ) ;
ERR_FAIL_COND_V_MSG ( property_type ! = p_to . get_type ( ) , Ref < PropertyTweener > ( ) , " Type mismatch between property and final value: " + Variant : : get_type_name ( property_type ) + " and " + Variant : : get_type_name ( p_to . get_type ( ) ) ) ;
# endif
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > tweener = memnew ( PropertyTweener ( p_target , p_property , p_to , p_duration ) ) ;
append ( tweener ) ;
return tweener ;
2015-05-05 05:12:17 +02:00
}
2020-09-05 03:05:30 +02:00
Ref < IntervalTweener > Tween : : tween_interval ( float p_time ) {
2021-08-05 13:05:14 +02:00
ERR_FAIL_COND_V_MSG ( ! valid , nullptr , " Tween invalid. Either finished or created outside scene tree. " ) ;
2020-09-05 03:05:30 +02:00
ERR_FAIL_COND_V_MSG ( started , nullptr , " Can't append to a Tween that has started. Use stop() first. " ) ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
Ref < IntervalTweener > tweener = memnew ( IntervalTweener ( p_time ) ) ;
append ( tweener ) ;
return tweener ;
}
2014-08-20 10:39:28 +02:00
2020-09-05 03:05:30 +02:00
Ref < CallbackTweener > Tween : : tween_callback ( Callable p_callback ) {
2021-08-05 13:05:14 +02:00
ERR_FAIL_COND_V_MSG ( ! valid , nullptr , " Tween invalid. Either finished or created outside scene tree. " ) ;
2020-09-05 03:05:30 +02:00
ERR_FAIL_COND_V_MSG ( started , nullptr , " Can't append to a Tween that has started. Use stop() first. " ) ;
Ref < CallbackTweener > tweener = memnew ( CallbackTweener ( p_callback ) ) ;
append ( tweener ) ;
return tweener ;
2014-08-20 06:01:41 +02:00
}
2021-09-16 01:15:31 +02:00
Ref < MethodTweener > Tween : : tween_method ( Callable p_callback , Variant p_from , Variant p_to , float p_duration ) {
2021-08-05 13:05:14 +02:00
ERR_FAIL_COND_V_MSG ( ! valid , nullptr , " Tween invalid. Either finished or created outside scene tree. " ) ;
2020-09-05 03:05:30 +02:00
ERR_FAIL_COND_V_MSG ( started , nullptr , " Can't append to a Tween that has started. Use stop() first. " ) ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
Ref < MethodTweener > tweener = memnew ( MethodTweener ( p_callback , p_from , p_to , p_duration ) ) ;
append ( tweener ) ;
return tweener ;
}
2014-08-20 10:39:28 +02:00
2021-08-05 13:05:14 +02:00
void Tween : : append ( Ref < Tweener > p_tweener ) {
2020-09-05 03:05:30 +02:00
p_tweener - > set_tween ( this ) ;
if ( parallel_enabled ) {
current_step = MAX ( current_step , 0 ) ;
} else {
current_step + + ;
2014-08-20 06:01:41 +02:00
}
2020-09-05 03:05:30 +02:00
parallel_enabled = default_parallel ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
tweeners . resize ( current_step + 1 ) ;
tweeners . write [ current_step ] . push_back ( p_tweener ) ;
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
void Tween : : stop ( ) {
started = false ;
running = false ;
dead = false ;
2022-03-22 17:39:01 +01:00
total_time = 0 ;
2020-09-05 03:05:30 +02:00
}
2016-03-09 00:00:52 +01:00
2020-09-05 03:05:30 +02:00
void Tween : : pause ( ) {
running = false ;
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
void Tween : : play ( ) {
2021-08-05 13:05:14 +02:00
ERR_FAIL_COND_MSG ( ! valid , " Tween invalid. Either finished or created outside scene tree. " ) ;
2020-09-05 03:05:30 +02:00
ERR_FAIL_COND_MSG ( dead , " Can't play finished Tween, use stop() first to reset its state. " ) ;
running = true ;
}
2016-03-09 00:00:52 +01:00
2020-09-05 03:05:30 +02:00
void Tween : : kill ( ) {
running = false ; // For the sake of is_running().
dead = true ;
2014-08-20 06:01:41 +02:00
}
2020-09-05 03:05:30 +02:00
bool Tween : : is_running ( ) {
return running ;
}
2017-03-05 16:44:50 +01:00
2020-09-05 03:05:30 +02:00
bool Tween : : is_valid ( ) {
2021-08-05 13:05:14 +02:00
return valid ;
}
void Tween : : clear ( ) {
valid = false ;
for ( List < Ref < Tweener > > & step : tweeners ) {
for ( Ref < Tweener > & tweener : step ) {
tweener - > clear_tween ( ) ;
}
}
tweeners . clear ( ) ;
2020-09-05 03:05:30 +02:00
}
2017-08-20 17:45:01 +02:00
2020-09-05 03:05:30 +02:00
Ref < Tween > Tween : : bind_node ( Node * p_node ) {
2021-08-02 14:15:40 +02:00
ERR_FAIL_NULL_V ( p_node , this ) ;
2020-09-05 03:05:30 +02:00
bound_node = p_node - > get_instance_id ( ) ;
is_bound = true ;
return this ;
}
2017-08-20 17:45:01 +02:00
2020-09-05 03:05:30 +02:00
Ref < Tween > Tween : : set_process_mode ( TweenProcessMode p_mode ) {
process_mode = p_mode ;
return this ;
2014-08-20 06:01:41 +02:00
}
2020-09-05 03:05:30 +02:00
Tween : : TweenProcessMode Tween : : get_process_mode ( ) {
return process_mode ;
}
Ref < Tween > Tween : : set_pause_mode ( TweenPauseMode p_mode ) {
pause_mode = p_mode ;
return this ;
}
Tween : : TweenPauseMode Tween : : get_pause_mode ( ) {
return pause_mode ;
}
Ref < Tween > Tween : : set_parallel ( bool p_parallel ) {
default_parallel = p_parallel ;
parallel_enabled = p_parallel ;
return this ;
}
Ref < Tween > Tween : : set_loops ( int p_loops ) {
loops = p_loops ;
return this ;
}
Ref < Tween > Tween : : set_speed_scale ( float p_speed ) {
speed_scale = p_speed ;
return this ;
}
Ref < Tween > Tween : : set_trans ( TransitionType p_trans ) {
default_transition = p_trans ;
return this ;
}
2018-09-26 13:13:56 +02:00
2020-09-05 03:05:30 +02:00
Tween : : TransitionType Tween : : get_trans ( ) {
return default_transition ;
}
Ref < Tween > Tween : : set_ease ( EaseType p_ease ) {
default_ease = p_ease ;
return this ;
}
Tween : : EaseType Tween : : get_ease ( ) {
return default_ease ;
}
Ref < Tween > Tween : : parallel ( ) {
parallel_enabled = true ;
return this ;
}
Ref < Tween > Tween : : chain ( ) {
parallel_enabled = false ;
return this ;
}
bool Tween : : custom_step ( float p_delta ) {
bool r = running ;
running = true ;
bool ret = step ( p_delta ) ;
running = running & & r ; // Running might turn false when Tween finished.
return ret ;
}
bool Tween : : step ( float p_delta ) {
if ( dead ) {
return false ;
2014-08-25 07:36:56 +02:00
}
2019-10-23 22:38:43 +02:00
2020-09-05 03:05:30 +02:00
if ( ! running ) {
return true ;
}
2019-10-23 22:38:43 +02:00
2020-09-05 03:05:30 +02:00
if ( is_bound ) {
2022-01-09 18:23:53 +01:00
Node * bound_node = get_bound_node ( ) ;
if ( bound_node ) {
2020-09-05 03:05:30 +02:00
if ( ! bound_node - > is_inside_tree ( ) ) {
return true ;
}
} else {
return false ;
2019-10-23 22:38:43 +02:00
}
}
2020-09-05 03:05:30 +02:00
if ( ! started ) {
2022-01-28 14:54:14 +01:00
ERR_FAIL_COND_V_MSG ( tweeners . is_empty ( ) , false , " Tween started, but has no Tweeners. " ) ;
2020-09-05 03:05:30 +02:00
current_step = 0 ;
loops_done = 0 ;
2022-03-22 17:39:01 +01:00
total_time = 0 ;
2020-09-05 03:05:30 +02:00
start_tweeners ( ) ;
started = true ;
}
2017-03-05 16:44:50 +01:00
2020-09-05 03:05:30 +02:00
float rem_delta = p_delta * speed_scale ;
bool step_active = false ;
2022-03-22 17:39:01 +01:00
total_time + = rem_delta ;
2019-06-09 05:11:42 +02:00
2022-04-30 23:19:20 +02:00
# ifdef DEBUG_ENABLED
float initial_delta = rem_delta ;
bool potential_infinite = false ;
# endif
2020-09-05 03:05:30 +02:00
while ( rem_delta > 0 & & running ) {
float step_delta = rem_delta ;
step_active = false ;
2021-07-26 17:50:35 +02:00
for ( Ref < Tweener > & tweener : tweeners . write [ current_step ] ) {
2020-09-05 03:05:30 +02:00
// Modified inside Tweener.step().
float temp_delta = rem_delta ;
// Turns to true if any Tweener returns true (i.e. is still not finished).
2021-07-26 17:50:35 +02:00
step_active = tweener - > step ( temp_delta ) | | step_active ;
2021-10-28 21:04:22 +02:00
step_delta = MIN ( temp_delta , step_delta ) ;
2018-09-26 13:13:56 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
rem_delta = step_delta ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
if ( ! step_active ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " step_finished " ) , current_step ) ;
2020-09-05 03:05:30 +02:00
current_step + + ;
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
if ( current_step = = tweeners . size ( ) ) {
loops_done + + ;
if ( loops_done = = loops ) {
running = false ;
dead = true ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " finished " ) ) ;
2020-09-05 03:05:30 +02:00
} else {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " loop_finished " ) , loops_done ) ;
2020-09-05 03:05:30 +02:00
current_step = 0 ;
start_tweeners ( ) ;
2022-04-30 23:19:20 +02:00
# ifdef DEBUG_ENABLED
if ( loops < = 0 & & Math : : is_equal_approx ( rem_delta , initial_delta ) ) {
if ( ! potential_infinite ) {
potential_infinite = true ;
} else {
// Looped twice without using any time, this is 100% certain infinite loop.
ERR_FAIL_V_MSG ( false , " Infinite loop detected. Check set_loops() description for more info. " ) ;
}
}
# endif
2020-09-05 03:05:30 +02:00
}
} else {
start_tweeners ( ) ;
}
2018-09-26 13:13:56 +02:00
}
2020-09-05 03:05:30 +02:00
}
return true ;
}
2018-09-26 13:13:56 +02:00
2022-01-09 18:23:53 +01:00
bool Tween : : can_process ( bool p_tree_paused ) const {
2020-09-05 03:05:30 +02:00
if ( is_bound & & pause_mode = = TWEEN_PAUSE_BOUND ) {
2022-01-09 18:23:53 +01:00
Node * bound_node = get_bound_node ( ) ;
if ( bound_node ) {
return bound_node - > can_process ( ) ;
2020-09-05 03:05:30 +02:00
}
2014-08-25 07:36:56 +02:00
}
2020-09-05 03:05:30 +02:00
2022-01-09 18:23:53 +01:00
return ! p_tree_paused | | pause_mode = = TWEEN_PAUSE_PROCESS ;
}
Node * Tween : : get_bound_node ( ) const {
if ( is_bound ) {
return Object : : cast_to < Node > ( ObjectDB : : get_instance ( bound_node ) ) ;
} else {
return nullptr ;
}
2014-08-25 07:36:56 +02:00
}
2022-03-22 17:39:01 +01:00
float Tween : : get_total_time ( ) const {
return total_time ;
}
2021-09-24 13:23:49 +02:00
real_t Tween : : run_equation ( TransitionType p_trans_type , EaseType p_ease_type , real_t p_time , real_t p_initial , real_t p_delta , real_t p_duration ) {
if ( p_duration = = 0 ) {
// Special case to avoid dividing by 0 in equations.
return p_initial + p_delta ;
}
interpolater func = interpolaters [ p_trans_type ] [ p_ease_type ] ;
return func ( p_time , p_initial , p_delta , p_duration ) ;
}
2020-09-05 03:05:30 +02:00
Variant Tween : : interpolate_variant ( Variant p_initial_val , Variant p_delta_val , float p_time , float p_duration , TransitionType p_trans , EaseType p_ease ) {
ERR_FAIL_INDEX_V ( p_trans , TransitionType : : TRANS_MAX , Variant ( ) ) ;
ERR_FAIL_INDEX_V ( p_ease , EaseType : : EASE_MAX , Variant ( ) ) ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
// Helper macro to run equation on sub-elements of the value (e.g. x and y of Vector2).
2017-03-05 16:44:50 +01:00
# define APPLY_EQUATION(element) \
2020-09-05 03:05:30 +02:00
r . element = run_equation ( p_trans , p_ease , p_time , i . element , d . element , p_duration ) ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
switch ( p_initial_val . get_type ( ) ) {
case Variant : : BOOL : {
return ( run_equation ( p_trans , p_ease , p_time , p_initial_val , p_delta_val , p_duration ) ) > = 0.5 ;
}
2014-12-19 10:13:20 +01:00
2020-09-05 03:05:30 +02:00
case Variant : : INT : {
return ( int ) run_equation ( p_trans , p_ease , p_time , ( int ) p_initial_val , ( int ) p_delta_val , p_duration ) ;
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
case Variant : : FLOAT : {
return run_equation ( p_trans , p_ease , p_time , ( real_t ) p_initial_val , ( real_t ) p_delta_val , p_duration ) ;
}
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : VECTOR2 : {
2020-09-05 03:05:30 +02:00
Vector2 i = p_initial_val ;
Vector2 d = p_delta_val ;
2014-08-20 06:01:41 +02:00
Vector2 r ;
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
case Variant : : VECTOR2I : {
Vector2i i = p_initial_val ;
Vector2i d = p_delta_val ;
Vector2i r ;
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
return r ;
}
2014-08-20 06:01:41 +02:00
2020-02-22 17:52:22 +01:00
case Variant : : RECT2 : {
2020-09-05 03:05:30 +02:00
Rect2 i = p_initial_val ;
Rect2 d = p_delta_val ;
2020-02-22 17:52:22 +01:00
Rect2 r ;
APPLY_EQUATION ( position . x ) ;
APPLY_EQUATION ( position . y ) ;
APPLY_EQUATION ( size . x ) ;
APPLY_EQUATION ( size . y ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
case Variant : : RECT2I : {
Rect2i i = p_initial_val ;
Rect2i d = p_delta_val ;
Rect2i r ;
APPLY_EQUATION ( position . x ) ;
APPLY_EQUATION ( position . y ) ;
APPLY_EQUATION ( size . x ) ;
APPLY_EQUATION ( size . y ) ;
return r ;
}
2020-02-22 17:52:22 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : VECTOR3 : {
2020-09-05 03:05:30 +02:00
Vector3 i = p_initial_val ;
Vector3 d = p_delta_val ;
2014-08-20 06:01:41 +02:00
Vector3 r ;
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
APPLY_EQUATION ( z ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
case Variant : : VECTOR3I : {
Vector3i i = p_initial_val ;
Vector3i d = p_delta_val ;
Vector3i r ;
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
APPLY_EQUATION ( z ) ;
return r ;
}
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM2D : {
2020-09-05 03:05:30 +02:00
Transform2D i = p_initial_val ;
Transform2D d = p_delta_val ;
2017-02-07 08:45:49 +01:00
Transform2D r ;
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( elements [ 0 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 0 ] [ 1 ] ) ;
APPLY_EQUATION ( elements [ 1 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 1 ] [ 1 ] ) ;
APPLY_EQUATION ( elements [ 2 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 2 ] [ 1 ] ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
2020-02-22 17:52:22 +01:00
2021-01-20 08:02:02 +01:00
case Variant : : QUATERNION : {
2020-09-05 03:05:30 +02:00
Quaternion i = p_initial_val ;
Quaternion d = p_delta_val ;
2021-01-20 08:02:02 +01:00
Quaternion r ;
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
APPLY_EQUATION ( z ) ;
APPLY_EQUATION ( w ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
2020-02-22 17:52:22 +01:00
2017-11-17 03:09:00 +01:00
case Variant : : AABB : {
2020-09-05 03:05:30 +02:00
AABB i = p_initial_val ;
AABB d = p_delta_val ;
2017-11-17 03:09:00 +01:00
AABB r ;
2014-08-20 06:01:41 +02:00
2017-06-06 20:33:51 +02:00
APPLY_EQUATION ( position . x ) ;
APPLY_EQUATION ( position . y ) ;
APPLY_EQUATION ( position . z ) ;
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( size . x ) ;
APPLY_EQUATION ( size . y ) ;
APPLY_EQUATION ( size . z ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
2020-02-22 17:52:22 +01:00
case Variant : : BASIS : {
2020-09-05 03:05:30 +02:00
Basis i = p_initial_val ;
Basis d = p_delta_val ;
2020-02-22 17:52:22 +01:00
Basis r ;
APPLY_EQUATION ( elements [ 0 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 0 ] [ 1 ] ) ;
APPLY_EQUATION ( elements [ 0 ] [ 2 ] ) ;
APPLY_EQUATION ( elements [ 1 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 1 ] [ 1 ] ) ;
APPLY_EQUATION ( elements [ 1 ] [ 2 ] ) ;
APPLY_EQUATION ( elements [ 2 ] [ 0 ] ) ;
APPLY_EQUATION ( elements [ 2 ] [ 1 ] ) ;
APPLY_EQUATION ( elements [ 2 ] [ 2 ] ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
2020-02-22 17:52:22 +01:00
2021-04-28 09:36:08 +02:00
case Variant : : TRANSFORM3D : {
2020-09-05 03:05:30 +02:00
Transform3D i = p_initial_val ;
Transform3D d = p_delta_val ;
2020-10-17 07:08:21 +02:00
Transform3D r ;
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( basis . elements [ 0 ] [ 0 ] ) ;
APPLY_EQUATION ( basis . elements [ 0 ] [ 1 ] ) ;
APPLY_EQUATION ( basis . elements [ 0 ] [ 2 ] ) ;
APPLY_EQUATION ( basis . elements [ 1 ] [ 0 ] ) ;
APPLY_EQUATION ( basis . elements [ 1 ] [ 1 ] ) ;
APPLY_EQUATION ( basis . elements [ 1 ] [ 2 ] ) ;
APPLY_EQUATION ( basis . elements [ 2 ] [ 0 ] ) ;
APPLY_EQUATION ( basis . elements [ 2 ] [ 1 ] ) ;
APPLY_EQUATION ( basis . elements [ 2 ] [ 2 ] ) ;
APPLY_EQUATION ( origin . x ) ;
APPLY_EQUATION ( origin . y ) ;
APPLY_EQUATION ( origin . z ) ;
2020-09-05 03:05:30 +02:00
return r ;
}
2020-02-22 17:52:22 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : COLOR : {
2020-09-05 03:05:30 +02:00
Color i = p_initial_val ;
Color d = p_delta_val ;
2014-08-20 06:01:41 +02:00
Color r ;
APPLY_EQUATION ( r ) ;
APPLY_EQUATION ( g ) ;
APPLY_EQUATION ( b ) ;
APPLY_EQUATION ( a ) ;
2020-09-05 03:05:30 +02:00
return r ;
2017-03-05 16:44:50 +01:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
default : {
return p_initial_val ;
2017-03-05 16:44:50 +01:00
}
2014-08-22 05:24:53 +02:00
} ;
2020-09-05 03:05:30 +02:00
# undef APPLY_EQUATION
2014-08-20 06:19:22 +02:00
}
2020-09-05 03:05:30 +02:00
Variant Tween : : calculate_delta_value ( Variant p_intial_val , Variant p_final_val ) {
2021-09-16 01:15:31 +02:00
ERR_FAIL_COND_V_MSG ( p_intial_val . get_type ( ) ! = p_final_val . get_type ( ) , p_intial_val , " Type mismatch between initial and final value: " + Variant : : get_type_name ( p_intial_val . get_type ( ) ) + " and " + Variant : : get_type_name ( p_final_val . get_type ( ) ) ) ;
2020-09-05 03:05:30 +02:00
switch ( p_intial_val . get_type ( ) ) {
case Variant : : BOOL : {
return ( int ) p_final_val - ( int ) p_intial_val ;
2017-05-30 22:20:15 +02:00
}
2014-08-20 10:39:28 +02:00
2020-09-05 03:05:30 +02:00
case Variant : : RECT2 : {
Rect2 i = p_intial_val ;
Rect2 f = p_final_val ;
return Rect2 ( f . position - i . position , f . size - i . size ) ;
2014-08-22 05:24:53 +02:00
}
2020-09-05 03:05:30 +02:00
case Variant : : RECT2I : {
Rect2i i = p_intial_val ;
Rect2i f = p_final_val ;
return Rect2i ( f . position - i . position , f . size - i . size ) ;
2020-05-14 16:41:43 +02:00
}
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM2D : {
2020-09-05 03:05:30 +02:00
Transform2D i = p_intial_val ;
Transform2D f = p_final_val ;
return Transform2D ( f . elements [ 0 ] [ 0 ] - i . elements [ 0 ] [ 0 ] ,
f . elements [ 0 ] [ 1 ] - i . elements [ 0 ] [ 1 ] ,
f . elements [ 1 ] [ 0 ] - i . elements [ 1 ] [ 0 ] ,
f . elements [ 1 ] [ 1 ] - i . elements [ 1 ] [ 1 ] ,
f . elements [ 2 ] [ 0 ] - i . elements [ 2 ] [ 0 ] ,
f . elements [ 2 ] [ 1 ] - i . elements [ 2 ] [ 1 ] ) ;
}
2019-06-09 05:11:42 +02:00
2017-11-17 03:09:00 +01:00
case Variant : : AABB : {
2020-09-05 03:05:30 +02:00
AABB i = p_intial_val ;
AABB f = p_final_val ;
return AABB ( f . position - i . position , f . size - i . size ) ;
}
2019-06-09 05:11:42 +02:00
2020-02-22 17:52:22 +01:00
case Variant : : BASIS : {
2020-09-05 03:05:30 +02:00
Basis i = p_intial_val ;
Basis f = p_final_val ;
return Basis ( f . elements [ 0 ] [ 0 ] - i . elements [ 0 ] [ 0 ] ,
2020-02-22 17:52:22 +01:00
f . elements [ 0 ] [ 1 ] - i . elements [ 0 ] [ 1 ] ,
f . elements [ 0 ] [ 2 ] - i . elements [ 0 ] [ 2 ] ,
f . elements [ 1 ] [ 0 ] - i . elements [ 1 ] [ 0 ] ,
f . elements [ 1 ] [ 1 ] - i . elements [ 1 ] [ 1 ] ,
f . elements [ 1 ] [ 2 ] - i . elements [ 1 ] [ 2 ] ,
f . elements [ 2 ] [ 0 ] - i . elements [ 2 ] [ 0 ] ,
f . elements [ 2 ] [ 1 ] - i . elements [ 2 ] [ 1 ] ,
f . elements [ 2 ] [ 2 ] - i . elements [ 2 ] [ 2 ] ) ;
2020-09-05 03:05:30 +02:00
}
2020-02-22 17:52:22 +01:00
2021-04-28 09:36:08 +02:00
case Variant : : TRANSFORM3D : {
2020-09-05 03:05:30 +02:00
Transform3D i = p_intial_val ;
Transform3D f = p_final_val ;
return Transform3D ( f . basis . elements [ 0 ] [ 0 ] - i . basis . elements [ 0 ] [ 0 ] ,
2014-08-20 06:01:41 +02:00
f . basis . elements [ 0 ] [ 1 ] - i . basis . elements [ 0 ] [ 1 ] ,
f . basis . elements [ 0 ] [ 2 ] - i . basis . elements [ 0 ] [ 2 ] ,
f . basis . elements [ 1 ] [ 0 ] - i . basis . elements [ 1 ] [ 0 ] ,
f . basis . elements [ 1 ] [ 1 ] - i . basis . elements [ 1 ] [ 1 ] ,
f . basis . elements [ 1 ] [ 2 ] - i . basis . elements [ 1 ] [ 2 ] ,
f . basis . elements [ 2 ] [ 0 ] - i . basis . elements [ 2 ] [ 0 ] ,
f . basis . elements [ 2 ] [ 1 ] - i . basis . elements [ 2 ] [ 1 ] ,
f . basis . elements [ 2 ] [ 2 ] - i . basis . elements [ 2 ] [ 2 ] ,
f . origin . x - i . origin . x ,
f . origin . y - i . origin . y ,
2017-03-05 16:44:50 +01:00
f . origin . z - i . origin . z ) ;
2020-09-05 03:05:30 +02:00
}
2014-08-20 06:01:41 +02:00
2020-02-22 17:52:22 +01:00
default : {
2020-09-05 03:05:30 +02:00
return Variant : : evaluate ( Variant : : OP_SUBTRACT , p_final_val , p_intial_val ) ;
2020-02-22 17:52:22 +01:00
}
2014-08-20 06:01:41 +02:00
} ;
}
2020-09-05 03:05:30 +02:00
void Tween : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " tween_property " , " object " , " property " , " final_val " , " duration " ) , & Tween : : tween_property ) ;
ClassDB : : bind_method ( D_METHOD ( " tween_interval " , " time " ) , & Tween : : tween_interval ) ;
ClassDB : : bind_method ( D_METHOD ( " tween_callback " , " callback " ) , & Tween : : tween_callback ) ;
ClassDB : : bind_method ( D_METHOD ( " tween_method " , " method " , " from " , " to " , " duration " ) , & Tween : : tween_method ) ;
ClassDB : : bind_method ( D_METHOD ( " custom_step " , " delta " ) , & Tween : : custom_step ) ;
ClassDB : : bind_method ( D_METHOD ( " stop " ) , & Tween : : stop ) ;
ClassDB : : bind_method ( D_METHOD ( " pause " ) , & Tween : : pause ) ;
ClassDB : : bind_method ( D_METHOD ( " play " ) , & Tween : : play ) ;
ClassDB : : bind_method ( D_METHOD ( " kill " ) , & Tween : : kill ) ;
2022-03-22 17:39:01 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_total_elapsed_time " ) , & Tween : : get_total_time ) ;
2020-09-05 03:05:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_running " ) , & Tween : : is_running ) ;
ClassDB : : bind_method ( D_METHOD ( " is_valid " ) , & Tween : : is_valid ) ;
ClassDB : : bind_method ( D_METHOD ( " bind_node " , " node " ) , & Tween : : bind_node ) ;
ClassDB : : bind_method ( D_METHOD ( " set_process_mode " , " mode " ) , & Tween : : set_process_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_pause_mode " , " mode " ) , & Tween : : set_pause_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_parallel " , " parallel " ) , & Tween : : set_parallel , DEFVAL ( true ) ) ;
ClassDB : : bind_method ( D_METHOD ( " set_loops " , " loops " ) , & Tween : : set_loops , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " set_speed_scale " , " speed " ) , & Tween : : set_speed_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " set_trans " , " trans " ) , & Tween : : set_trans ) ;
ClassDB : : bind_method ( D_METHOD ( " set_ease " , " ease " ) , & Tween : : set_ease ) ;
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " parallel " ) , & Tween : : parallel ) ;
ClassDB : : bind_method ( D_METHOD ( " chain " ) , & Tween : : chain ) ;
2019-06-09 05:11:42 +02:00
2022-04-17 23:13:39 +02:00
ClassDB : : bind_static_method ( " Tween " , D_METHOD ( " interpolate_value " , " initial_value " , " delta_value " , " elapsed_time " , " duration " , " trans_type " , " ease_type " ) , & Tween : : interpolate_variant ) ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
ADD_SIGNAL ( MethodInfo ( " step_finished " , PropertyInfo ( Variant : : INT , " idx " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " loop_finished " , PropertyInfo ( Variant : : INT , " loop_count " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " finished " ) ) ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
BIND_ENUM_CONSTANT ( TWEEN_PROCESS_PHYSICS ) ;
BIND_ENUM_CONSTANT ( TWEEN_PROCESS_IDLE ) ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
BIND_ENUM_CONSTANT ( TWEEN_PAUSE_BOUND ) ;
BIND_ENUM_CONSTANT ( TWEEN_PAUSE_STOP ) ;
BIND_ENUM_CONSTANT ( TWEEN_PAUSE_PROCESS ) ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
BIND_ENUM_CONSTANT ( TRANS_LINEAR ) ;
BIND_ENUM_CONSTANT ( TRANS_SINE ) ;
BIND_ENUM_CONSTANT ( TRANS_QUINT ) ;
BIND_ENUM_CONSTANT ( TRANS_QUART ) ;
BIND_ENUM_CONSTANT ( TRANS_QUAD ) ;
BIND_ENUM_CONSTANT ( TRANS_EXPO ) ;
BIND_ENUM_CONSTANT ( TRANS_ELASTIC ) ;
BIND_ENUM_CONSTANT ( TRANS_CUBIC ) ;
BIND_ENUM_CONSTANT ( TRANS_CIRC ) ;
BIND_ENUM_CONSTANT ( TRANS_BOUNCE ) ;
BIND_ENUM_CONSTANT ( TRANS_BACK ) ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
BIND_ENUM_CONSTANT ( EASE_IN ) ;
BIND_ENUM_CONSTANT ( EASE_OUT ) ;
BIND_ENUM_CONSTANT ( EASE_IN_OUT ) ;
BIND_ENUM_CONSTANT ( EASE_OUT_IN ) ;
}
2014-08-20 06:01:41 +02:00
2022-04-17 23:13:39 +02:00
Tween : : Tween ( ) {
ERR_FAIL_MSG ( " Tween can't be created directly. Use create_tween() method. " ) ;
}
Tween : : Tween ( bool p_valid ) {
valid = p_valid ;
}
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : from ( Variant p_value ) {
initial_val = p_value ;
do_continue = false ;
return this ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : from_current ( ) {
do_continue = false ;
return this ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : as_relative ( ) {
relative = true ;
return this ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : set_trans ( Tween : : TransitionType p_trans ) {
trans_type = p_trans ;
return this ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : set_ease ( Tween : : EaseType p_ease ) {
ease_type = p_ease ;
return this ;
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
Ref < PropertyTweener > PropertyTweener : : set_delay ( float p_delay ) {
delay = p_delay ;
return this ;
2014-08-20 06:01:41 +02:00
}
2020-09-05 03:05:30 +02:00
void PropertyTweener : : start ( ) {
elapsed_time = 0 ;
finished = false ;
Object * target_instance = ObjectDB : : get_instance ( target ) ;
if ( ! target_instance ) {
WARN_PRINT ( " Target object freed before starting, aborting Tweener. " ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
if ( do_continue ) {
initial_val = target_instance - > get_indexed ( property ) ;
2020-05-14 16:41:43 +02:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
if ( relative ) {
final_val = Variant : : evaluate ( Variant : : Operator : : OP_ADD , initial_val , base_final_val ) ;
2020-05-14 16:41:43 +02:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
delta_val = tween - > calculate_delta_value ( initial_val , final_val ) ;
2019-06-09 05:11:42 +02:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
bool PropertyTweener : : step ( float & r_delta ) {
if ( finished ) {
// This is needed in case there's a parallel Tweener with longer duration.
return false ;
2019-06-09 05:11:42 +02:00
}
2014-08-20 06:01:41 +02:00
2020-09-05 03:05:30 +02:00
Object * target_instance = ObjectDB : : get_instance ( target ) ;
if ( ! target_instance ) {
return false ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
elapsed_time + = r_delta ;
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
if ( elapsed_time < delay ) {
r_delta = 0 ;
return true ;
2015-05-05 05:12:17 +02:00
}
2016-04-07 09:45:16 +02:00
2020-09-05 03:05:30 +02:00
float time = MIN ( elapsed_time - delay , duration ) ;
if ( time < duration ) {
2022-03-27 03:09:12 +02:00
target_instance - > set_indexed ( property , tween - > interpolate_variant ( initial_val , delta_val , time , duration , trans_type , ease_type ) ) ;
2020-09-05 03:05:30 +02:00
r_delta = 0 ;
return true ;
2020-05-14 16:41:43 +02:00
} else {
2022-03-27 03:09:12 +02:00
target_instance - > set_indexed ( property , final_val ) ;
2020-09-05 03:05:30 +02:00
finished = true ;
r_delta = elapsed_time - delay - duration ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " finished " ) ) ;
2020-09-05 03:05:30 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2015-01-07 12:46:01 +01:00
}
2020-09-05 03:05:30 +02:00
void PropertyTweener : : set_tween ( Ref < Tween > p_tween ) {
tween = p_tween ;
if ( trans_type = = Tween : : TRANS_MAX ) {
trans_type = tween - > get_trans ( ) ;
2015-05-05 05:12:17 +02:00
}
2020-09-05 03:05:30 +02:00
if ( ease_type = = Tween : : EASE_MAX ) {
ease_type = tween - > get_ease ( ) ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
}
2015-01-07 12:46:01 +01:00
2020-09-05 03:05:30 +02:00
void PropertyTweener : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " from " , " value " ) , & PropertyTweener : : from ) ;
ClassDB : : bind_method ( D_METHOD ( " from_current " ) , & PropertyTweener : : from_current ) ;
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_delay " , " delay " ) , & PropertyTweener : : set_delay ) ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
PropertyTweener : : PropertyTweener ( Object * p_target , NodePath p_property , Variant p_to , float p_duration ) {
target = p_target - > get_instance_id ( ) ;
property = p_property . get_as_property_path ( ) . get_subnames ( ) ;
initial_val = p_target - > get_indexed ( property ) ;
base_final_val = p_to ;
final_val = base_final_val ;
duration = p_duration ;
2014-08-25 07:36:56 +02:00
}
2020-09-05 03:05:30 +02:00
PropertyTweener : : PropertyTweener ( ) {
ERR_FAIL_MSG ( " Can't create empty PropertyTweener. Use get_tree().tween_property() or tween_property() instead. " ) ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
void IntervalTweener : : start ( ) {
elapsed_time = 0 ;
finished = false ;
}
2017-05-30 22:20:15 +02:00
2020-09-05 03:05:30 +02:00
bool IntervalTweener : : step ( float & r_delta ) {
if ( finished ) {
return false ;
2020-05-14 16:41:43 +02:00
}
2017-05-30 22:21:50 +02:00
2020-09-05 03:05:30 +02:00
elapsed_time + = r_delta ;
if ( elapsed_time < duration ) {
r_delta = 0 ;
return true ;
} else {
finished = true ;
r_delta = elapsed_time - duration ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " finished " ) ) ;
2020-09-05 03:05:30 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
IntervalTweener : : IntervalTweener ( float p_time ) {
duration = p_time ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
IntervalTweener : : IntervalTweener ( ) {
ERR_FAIL_MSG ( " Can't create empty IntervalTweener. Use get_tree().tween_interval() instead. " ) ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < CallbackTweener > CallbackTweener : : set_delay ( float p_delay ) {
delay = p_delay ;
return this ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
void CallbackTweener : : start ( ) {
elapsed_time = 0 ;
finished = false ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
bool CallbackTweener : : step ( float & r_delta ) {
if ( finished ) {
return false ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
elapsed_time + = r_delta ;
if ( elapsed_time > = delay ) {
Variant result ;
Callable : : CallError ce ;
callback . call ( nullptr , 0 , result , ce ) ;
if ( ce . error ! = Callable : : CallError : : CALL_OK ) {
2022-04-30 13:30:05 +02:00
ERR_FAIL_V_MSG ( false , " Error calling method from CallbackTweener: " + Variant : : get_callable_error_text ( callback , nullptr , 0 , ce ) ) ;
2020-09-05 03:05:30 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
finished = true ;
r_delta = elapsed_time - delay ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " finished " ) ) ;
2020-09-05 03:05:30 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
r_delta = 0 ;
return true ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
void CallbackTweener : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " set_delay " , " delay " ) , & CallbackTweener : : set_delay ) ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
CallbackTweener : : CallbackTweener ( Callable p_callback ) {
callback = p_callback ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
CallbackTweener : : CallbackTweener ( ) {
ERR_FAIL_MSG ( " Can't create empty CallbackTweener. Use get_tree().tween_callback() instead. " ) ;
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
Ref < MethodTweener > MethodTweener : : set_delay ( float p_delay ) {
delay = p_delay ;
return this ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
Ref < MethodTweener > MethodTweener : : set_trans ( Tween : : TransitionType p_trans ) {
trans_type = p_trans ;
return this ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
Ref < MethodTweener > MethodTweener : : set_ease ( Tween : : EaseType p_ease ) {
ease_type = p_ease ;
return this ;
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
void MethodTweener : : start ( ) {
elapsed_time = 0 ;
finished = false ;
}
2017-05-30 22:20:15 +02:00
2020-09-05 03:05:30 +02:00
bool MethodTweener : : step ( float & r_delta ) {
if ( finished ) {
return false ;
2020-05-14 16:41:43 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
elapsed_time + = r_delta ;
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
if ( elapsed_time < delay ) {
r_delta = 0 ;
return true ;
2020-03-06 08:40:40 +01:00
}
2014-08-22 05:24:53 +02:00
2022-03-27 03:09:12 +02:00
Variant current_val ;
2020-09-05 03:05:30 +02:00
float time = MIN ( elapsed_time - delay , duration ) ;
2022-03-27 03:09:12 +02:00
if ( time < duration ) {
current_val = tween - > interpolate_variant ( initial_val , delta_val , time , duration , trans_type , ease_type ) ;
} else {
current_val = final_val ;
}
2020-09-05 03:05:30 +02:00
const Variant * * argptr = ( const Variant * * ) alloca ( sizeof ( Variant * ) ) ;
argptr [ 0 ] = & current_val ;
2014-08-22 05:24:53 +02:00
2020-09-05 03:05:30 +02:00
Variant result ;
Callable : : CallError ce ;
callback . call ( argptr , 1 , result , ce ) ;
if ( ce . error ! = Callable : : CallError : : CALL_OK ) {
2022-04-30 13:30:05 +02:00
ERR_FAIL_V_MSG ( false , " Error calling method from MethodTweener: " + Variant : : get_callable_error_text ( callback , argptr , 1 , ce ) ) ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
2020-09-05 03:05:30 +02:00
if ( time < duration ) {
r_delta = 0 ;
return true ;
} else {
finished = true ;
r_delta = elapsed_time - delay - duration ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " finished " ) ) ;
2020-09-05 03:05:30 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
void MethodTweener : : set_tween ( Ref < Tween > p_tween ) {
tween = p_tween ;
if ( trans_type = = Tween : : TRANS_MAX ) {
trans_type = tween - > get_trans ( ) ;
2020-05-14 16:41:43 +02:00
}
2020-09-05 03:05:30 +02:00
if ( ease_type = = Tween : : EASE_MAX ) {
ease_type = tween - > get_ease ( ) ;
2020-03-06 08:40:40 +01:00
}
2020-09-05 03:05:30 +02:00
}
2014-08-25 07:36:56 +02:00
2020-09-05 03:05:30 +02:00
void MethodTweener : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " set_delay " , " delay " ) , & MethodTweener : : set_delay ) ;
ClassDB : : bind_method ( D_METHOD ( " set_trans " , " trans " ) , & MethodTweener : : set_trans ) ;
ClassDB : : bind_method ( D_METHOD ( " set_ease " , " ease " ) , & MethodTweener : : set_ease ) ;
2014-08-25 07:36:56 +02:00
}
2021-09-16 01:15:31 +02:00
MethodTweener : : MethodTweener ( Callable p_callback , Variant p_from , Variant p_to , float p_duration ) {
2020-09-05 03:05:30 +02:00
callback = p_callback ;
initial_val = p_from ;
delta_val = tween - > calculate_delta_value ( p_from , p_to ) ;
2022-03-27 03:09:12 +02:00
final_val = p_to ;
2020-09-05 03:05:30 +02:00
duration = p_duration ;
2014-08-20 06:01:41 +02:00
}
2020-09-05 03:05:30 +02:00
MethodTweener : : MethodTweener ( ) {
ERR_FAIL_MSG ( " Can't create empty MethodTweener. Use get_tree().tween_method() instead. " ) ;
2014-08-20 06:01:41 +02:00
}