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
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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
# include "core/method_bind_ext.gen.inc"
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
void Tween : : _add_pending_command ( StringName p_key , const Variant & p_arg1 , const Variant & p_arg2 , const Variant & p_arg3 , const Variant & p_arg4 , const Variant & p_arg5 , const Variant & p_arg6 , const Variant & p_arg7 , const Variant & p_arg8 , const Variant & p_arg9 , const Variant & p_arg10 ) {
2015-05-05 05:12:17 +02:00
2019-06-09 05:11:42 +02:00
// Add a new pending command and reference it
2015-05-05 05:12:17 +02:00
pending_commands . push_back ( PendingCommand ( ) ) ;
2017-03-05 16:44:50 +01:00
PendingCommand & cmd = pending_commands . back ( ) - > get ( ) ;
2015-05-05 05:12:17 +02:00
2019-06-09 05:11:42 +02:00
// Update the command with the target key
2015-05-05 05:12:17 +02:00
cmd . key = p_key ;
2019-06-09 05:11:42 +02:00
// Determine command argument count
2017-03-05 16:44:50 +01:00
int & count = cmd . args ;
if ( p_arg10 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 10 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg9 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 9 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg8 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 8 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg7 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 7 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg6 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 6 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg5 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 5 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg4 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 4 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg3 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 3 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg2 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 2 ;
2017-03-05 16:44:50 +01:00
else if ( p_arg1 . get_type ( ) ! = Variant : : NIL )
2015-05-05 05:12:17 +02:00
count = 1 ;
2019-11-20 16:22:16 +01:00
else
count = 0 ;
2019-06-09 05:11:42 +02:00
// Add the specified arguments to the command
2017-03-05 16:44:50 +01:00
if ( count > 0 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 0 ] = p_arg1 ;
2017-03-05 16:44:50 +01:00
if ( count > 1 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 1 ] = p_arg2 ;
2017-03-05 16:44:50 +01:00
if ( count > 2 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 2 ] = p_arg3 ;
2017-03-05 16:44:50 +01:00
if ( count > 3 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 3 ] = p_arg4 ;
2017-03-05 16:44:50 +01:00
if ( count > 4 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 4 ] = p_arg5 ;
2017-03-05 16:44:50 +01:00
if ( count > 5 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 5 ] = p_arg6 ;
2017-03-05 16:44:50 +01:00
if ( count > 6 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 6 ] = p_arg7 ;
2017-03-05 16:44:50 +01:00
if ( count > 7 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 7 ] = p_arg8 ;
2017-03-05 16:44:50 +01:00
if ( count > 8 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 8 ] = p_arg9 ;
2017-03-05 16:44:50 +01:00
if ( count > 9 )
2015-05-05 05:12:17 +02:00
cmd . arg [ 9 ] = p_arg10 ;
}
void Tween : : _process_pending_commands ( ) {
2019-06-09 05:11:42 +02:00
// For each pending command...
2017-03-05 16:44:50 +01:00
for ( List < PendingCommand > : : Element * E = pending_commands . front ( ) ; E ; E = E - > next ( ) ) {
2015-05-05 05:12:17 +02:00
2019-06-09 05:11:42 +02:00
// Get the command
2017-03-05 16:44:50 +01:00
PendingCommand & cmd = E - > get ( ) ;
2020-02-19 20:27:19 +01:00
Callable : : CallError err ;
2019-06-09 05:11:42 +02:00
// Grab all of the arguments for the command
2015-05-05 05:12:17 +02:00
Variant * arg [ 10 ] = {
& cmd . arg [ 0 ] ,
& cmd . arg [ 1 ] ,
& cmd . arg [ 2 ] ,
& cmd . arg [ 3 ] ,
& cmd . arg [ 4 ] ,
& cmd . arg [ 5 ] ,
& cmd . arg [ 6 ] ,
& cmd . arg [ 7 ] ,
& cmd . arg [ 8 ] ,
& cmd . arg [ 9 ] ,
} ;
2019-06-09 05:11:42 +02:00
// Execute the command (and retrieve any errors)
2017-03-05 16:44:50 +01:00
this - > call ( cmd . key , ( const Variant * * ) arg , cmd . args , err ) ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// Clear the pending commands
2015-05-05 05:12:17 +02:00
pending_commands . clear ( ) ;
}
2017-03-05 16:44:50 +01:00
bool Tween : : _set ( const StringName & p_name , const Variant & p_value ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Set the correct attribute based on the given name
2017-03-05 16:44:50 +01:00
String name = p_name ;
2019-06-09 05:11:42 +02:00
if ( name = = " playback/speed " | | name = = " speed " ) { // Backwards compatibility
2017-01-13 23:36:04 +01:00
set_speed_scale ( p_value ) ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
} else if ( name = = " playback/active " ) {
2014-08-20 06:01:41 +02:00
set_active ( p_value ) ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 10:39:28 +02:00
2017-03-05 16:44:50 +01:00
} else if ( name = = " playback/repeat " ) {
2014-08-20 10:39:28 +02:00
set_repeat ( p_value ) ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 06:01:41 +02:00
}
2020-05-05 13:02:33 +02:00
return false ;
2014-08-20 06:01:41 +02:00
}
2017-03-05 16:44:50 +01:00
bool Tween : : _get ( const StringName & p_name , Variant & r_ret ) const {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Get the correct attribute based on the given name
2017-03-05 16:44:50 +01:00
String name = p_name ;
2019-06-09 05:11:42 +02:00
if ( name = = " playback/speed " ) { // Backwards compatibility
2017-03-05 16:44:50 +01:00
r_ret = speed_scale ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
} else if ( name = = " playback/active " ) {
2017-03-05 16:44:50 +01:00
r_ret = is_active ( ) ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 10:39:28 +02:00
2019-06-09 05:11:42 +02:00
} else if ( name = = " playback/repeat " ) {
2017-03-05 16:44:50 +01:00
r_ret = is_repeat ( ) ;
2020-05-05 13:02:33 +02:00
return true ;
2014-08-20 06:01:41 +02:00
}
2020-05-05 13:02:33 +02:00
return false ;
2014-08-20 06:01:41 +02:00
}
void Tween : : _get_property_list ( List < PropertyInfo > * p_list ) const {
2019-06-09 05:11:42 +02:00
// Add the property info for the Tween object
2017-03-05 16:44:50 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " playback/active " , PROPERTY_HINT_NONE , " " ) ) ;
p_list - > push_back ( PropertyInfo ( Variant : : BOOL , " playback/repeat " , PROPERTY_HINT_NONE , " " ) ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
p_list - > push_back ( PropertyInfo ( Variant : : FLOAT , " playback/speed " , PROPERTY_HINT_RANGE , " -64,64,0.01 " ) ) ;
2014-08-20 06:01:41 +02:00
}
void Tween : : _notification ( int p_what ) {
2019-06-09 05:11:42 +02:00
// What notification did we receive?
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2016-03-09 00:00:52 +01:00
2014-11-06 01:20:42 +01:00
case NOTIFICATION_ENTER_TREE : {
2019-06-09 05:11:42 +02:00
// Are we not already active?
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
if ( ! is_active ( ) ) {
2019-06-09 05:11:42 +02:00
// Make sure that a previous process state was not saved
// Only process if "processing" is set
2017-09-30 16:19:07 +02:00
set_physics_process_internal ( false ) ;
2017-01-10 22:02:19 +01:00
set_process_internal ( false ) ;
2014-08-20 06:01:41 +02:00
}
} break ;
2019-06-09 05:11:42 +02:00
case NOTIFICATION_READY : {
// Do nothing
2014-08-20 06:01:41 +02:00
} break ;
2019-06-09 05:11:42 +02:00
2017-01-10 22:02:19 +01:00
case NOTIFICATION_INTERNAL_PROCESS : {
2019-06-09 05:11:42 +02:00
// Are we processing during physics time?
2017-09-30 16:19:07 +02:00
if ( tween_process_mode = = TWEEN_PROCESS_PHYSICS )
2019-06-09 05:11:42 +02:00
// Do nothing since we aren't aligned with physics when we should be
2014-08-20 06:01:41 +02:00
break ;
2019-06-09 05:11:42 +02:00
// Should we update?
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
if ( is_active ( ) )
2019-06-09 05:11:42 +02:00
// Update the tweens
2017-03-05 16:44:50 +01:00
_tween_process ( get_process_delta_time ( ) ) ;
2014-08-20 06:01:41 +02:00
} break ;
2016-03-09 00:00:52 +01:00
2019-06-09 05:11:42 +02:00
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS : {
// Are we processing during 'regular' time?
2017-03-05 16:44:50 +01:00
if ( tween_process_mode = = TWEEN_PROCESS_IDLE )
Fix misc. source comment typos
Found using `codespell -q 3 -S ./thirdparty,*.po -L ang,ba,cas,dof,doubleclick,fave,hist,leapyear,lod,nd,numer,ois,paket,seeked,sinc,switchs,te,uint -D ~/Projects/codespell/codespell_lib/data/dictionary.txt `
2019-09-19 20:36:39 +02:00
// Do nothing since we would only process during idle time
2014-08-20 06:01:41 +02:00
break ;
2019-06-09 05:11:42 +02:00
// Should we update?
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
if ( is_active ( ) )
2019-06-09 05:11:42 +02:00
// Update the tweens
2017-09-30 16:19:07 +02:00
_tween_process ( get_physics_process_delta_time ( ) ) ;
2014-08-20 06:01:41 +02:00
} break ;
2016-03-09 00:00:52 +01:00
2019-06-09 05:11:42 +02:00
case NOTIFICATION_EXIT_TREE : {
// We've left the tree. Stop all tweens
2014-08-20 06:01:41 +02:00
stop_all ( ) ;
} break ;
}
}
void Tween : : _bind_methods ( ) {
2019-06-09 05:11:42 +02:00
// Bind getters and setters
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_active " ) , & Tween : : is_active ) ;
ClassDB : : bind_method ( D_METHOD ( " set_active " , " active " ) , & Tween : : set_active ) ;
ClassDB : : bind_method ( D_METHOD ( " is_repeat " ) , & Tween : : is_repeat ) ;
ClassDB : : bind_method ( D_METHOD ( " set_repeat " , " repeat " ) , & Tween : : set_repeat ) ;
ClassDB : : bind_method ( D_METHOD ( " set_speed_scale " , " speed " ) , & Tween : : set_speed_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_speed_scale " ) , & Tween : : get_speed_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " set_tween_process_mode " , " mode " ) , & Tween : : set_tween_process_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tween_process_mode " ) , & Tween : : get_tween_process_mode ) ;
2019-06-09 05:11:42 +02:00
// Bind the various Tween control methods
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " start " ) , & Tween : : start ) ;
ClassDB : : bind_method ( D_METHOD ( " reset " , " object " , " key " ) , & Tween : : reset , DEFVAL ( " " ) ) ;
ClassDB : : bind_method ( D_METHOD ( " reset_all " ) , & Tween : : reset_all ) ;
ClassDB : : bind_method ( D_METHOD ( " stop " , " object " , " key " ) , & Tween : : stop , DEFVAL ( " " ) ) ;
ClassDB : : bind_method ( D_METHOD ( " stop_all " ) , & Tween : : stop_all ) ;
ClassDB : : bind_method ( D_METHOD ( " resume " , " object " , " key " ) , & Tween : : resume , DEFVAL ( " " ) ) ;
ClassDB : : bind_method ( D_METHOD ( " resume_all " ) , & Tween : : resume_all ) ;
ClassDB : : bind_method ( D_METHOD ( " remove " , " object " , " key " ) , & Tween : : remove , DEFVAL ( " " ) ) ;
2018-08-15 17:26:10 +02:00
ClassDB : : bind_method ( D_METHOD ( " _remove_by_uid " , " uid " ) , & Tween : : _remove_by_uid ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " remove_all " ) , & Tween : : remove_all ) ;
ClassDB : : bind_method ( D_METHOD ( " seek " , " time " ) , & Tween : : seek ) ;
ClassDB : : bind_method ( D_METHOD ( " tell " ) , & Tween : : tell ) ;
ClassDB : : bind_method ( D_METHOD ( " get_runtime " ) , & Tween : : get_runtime ) ;
2019-06-09 05:11:42 +02:00
// Bind interpolation and follow methods
2019-12-12 01:15:15 +01:00
ClassDB : : bind_method ( D_METHOD ( " interpolate_property " , " object " , " property " , " initial_val " , " final_val " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : interpolate_property , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " interpolate_method " , " object " , " method " , " initial_val " , " final_val " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : interpolate_method , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " interpolate_callback " , " object " , " duration " , " callback " , " arg1 " , " arg2 " , " arg3 " , " arg4 " , " arg5 " ) , & Tween : : interpolate_callback , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) ) ;
ClassDB : : bind_method ( D_METHOD ( " interpolate_deferred_callback " , " object " , " duration " , " callback " , " arg1 " , " arg2 " , " arg3 " , " arg4 " , " arg5 " ) , & Tween : : interpolate_deferred_callback , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) , DEFVAL ( Variant ( ) ) ) ;
2019-12-12 01:15:15 +01:00
ClassDB : : bind_method ( D_METHOD ( " follow_property " , " object " , " property " , " initial_val " , " target " , " target_property " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : follow_property , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " follow_method " , " object " , " method " , " initial_val " , " target " , " target_method " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : follow_method , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " targeting_property " , " object " , " property " , " initial " , " initial_val " , " final_val " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : targeting_property , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " targeting_method " , " object " , " method " , " initial " , " initial_method " , " final_val " , " duration " , " trans_type " , " ease_type " , " delay " ) , & Tween : : targeting_method , DEFVAL ( TRANS_LINEAR ) , DEFVAL ( EASE_IN_OUT ) , DEFVAL ( 0 ) ) ;
2017-03-05 16:44:50 +01:00
2019-06-09 05:11:42 +02:00
// Add the Tween signals
2018-01-23 13:06:03 +01:00
ADD_SIGNAL ( MethodInfo ( " tween_started " , PropertyInfo ( Variant : : OBJECT , " object " ) , PropertyInfo ( Variant : : NODE_PATH , " key " ) ) ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
ADD_SIGNAL ( MethodInfo ( " tween_step " , PropertyInfo ( Variant : : OBJECT , " object " ) , PropertyInfo ( Variant : : NODE_PATH , " key " ) , PropertyInfo ( Variant : : FLOAT , " elapsed " ) , PropertyInfo ( Variant : : OBJECT , " value " ) ) ) ;
2018-01-23 13:06:03 +01:00
ADD_SIGNAL ( MethodInfo ( " tween_completed " , PropertyInfo ( Variant : : OBJECT , " object " ) , PropertyInfo ( Variant : : NODE_PATH , " key " ) ) ) ;
2019-03-19 13:58:37 +01:00
ADD_SIGNAL ( MethodInfo ( " tween_all_completed " ) ) ;
2017-03-05 16:44:50 +01:00
2019-06-09 05:11:42 +02:00
// Add the properties and tie them to the getters and setters
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " repeat " ) , " set_repeat " , " is_repeat " ) ;
2017-10-21 16:28:08 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " playback_process_mode " , PROPERTY_HINT_ENUM , " Physics,Idle " ) , " set_tween_process_mode " , " get_tween_process_mode " ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " playback_speed " , PROPERTY_HINT_RANGE , " -64,64,0.01 " ) , " set_speed_scale " , " get_speed_scale " ) ;
2014-12-19 10:13:20 +01:00
2019-06-09 05:11:42 +02:00
// Bind Idle vs Physics process
2017-09-30 16:19:07 +02:00
BIND_ENUM_CONSTANT ( TWEEN_PROCESS_PHYSICS ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( TWEEN_PROCESS_IDLE ) ;
2019-06-09 05:11:42 +02:00
// Bind the Transition type constants
2017-08-20 17:45:01 +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
// Bind the easing constants
2017-08-20 17:45:01 +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
}
2019-10-23 22:38:43 +02:00
Variant Tween : : _get_initial_val ( const InterpolateData & p_data ) const {
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// What type of data are we interpolating?
2017-03-05 16:44:50 +01:00
switch ( p_data . type ) {
2014-08-25 07:36:56 +02:00
case INTER_PROPERTY :
case INTER_METHOD :
case FOLLOW_PROPERTY :
case FOLLOW_METHOD :
2019-06-09 05:11:42 +02:00
// Simply use the given initial value
2014-08-25 07:36:56 +02:00
return p_data . initial_val ;
case TARGETING_PROPERTY :
case TARGETING_METHOD : {
2019-06-09 05:11:42 +02:00
// Get the object that is being targeted
2017-03-05 16:44:50 +01:00
Object * object = ObjectDB : : get_instance ( p_data . target_id ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( object = = nullptr , p_data . initial_val ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Are we targeting a property or a method?
2019-10-23 22:38:43 +02:00
Variant initial_val ;
2017-03-05 16:44:50 +01:00
if ( p_data . type = = TARGETING_PROPERTY ) {
2019-06-09 05:11:42 +02:00
// Get the property from the target object
2017-03-05 16:44:50 +01:00
bool valid = false ;
2017-05-30 22:20:15 +02:00
initial_val = object - > get_indexed ( p_data . target_key , & valid ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! valid , p_data . initial_val ) ;
} else {
2019-06-09 05:11:42 +02:00
// Call the method and get the initial value from it
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2020-04-02 01:20:12 +02:00
initial_val = object - > call ( p_data . target_key [ 0 ] , nullptr , 0 , error ) ;
2020-02-19 20:27:19 +01:00
ERR_FAIL_COND_V ( error . error ! = Callable : : CallError : : CALL_OK , p_data . initial_val ) ;
2014-08-25 07:36:56 +02:00
}
2017-03-05 16:44:50 +01:00
return initial_val ;
2018-09-26 13:13:56 +02:00
}
case INTER_CALLBACK :
2019-06-09 05:11:42 +02:00
// Callback does not have a special initial value
2018-09-26 13:13:56 +02:00
break ;
2014-08-25 07:36:56 +02:00
}
2019-06-09 05:11:42 +02:00
// If we've made it here, just return the delta value as the initial value
2014-08-25 07:36:56 +02:00
return p_data . delta_val ;
}
2019-10-23 22:38:43 +02:00
Variant Tween : : _get_final_val ( const InterpolateData & p_data ) const {
switch ( p_data . type ) {
case FOLLOW_PROPERTY :
case FOLLOW_METHOD : {
// Get the object that is being followed
Object * target = ObjectDB : : get_instance ( p_data . target_id ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( target = = nullptr , p_data . initial_val ) ;
2019-10-23 22:38:43 +02:00
// We want to figure out the final value
Variant final_val ;
if ( p_data . type = = FOLLOW_PROPERTY ) {
// Read the property as-is
bool valid = false ;
final_val = target - > get_indexed ( p_data . target_key , & valid ) ;
ERR_FAIL_COND_V ( ! valid , p_data . initial_val ) ;
} else {
// We're looking at a method. Call the method on the target object
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2020-04-02 01:20:12 +02:00
final_val = target - > call ( p_data . target_key [ 0 ] , nullptr , 0 , error ) ;
2020-02-19 20:27:19 +01:00
ERR_FAIL_COND_V ( error . error ! = Callable : : CallError : : CALL_OK , p_data . initial_val ) ;
2019-10-23 22:38:43 +02:00
}
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// If we're looking at an INT value, instead convert it to a FLOAT
2019-10-23 22:38:43 +02:00
// This is better for interpolation
if ( final_val . get_type ( ) = = Variant : : INT ) final_val = final_val . operator real_t ( ) ;
return final_val ;
}
default : {
// If we're not following a final value/method, use the final value from the data
return p_data . final_val ;
}
}
}
2017-03-05 16:44:50 +01:00
Variant & Tween : : _get_delta_val ( InterpolateData & p_data ) {
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// What kind of data are we interpolating?
2017-03-05 16:44:50 +01:00
switch ( p_data . type ) {
2014-08-25 07:36:56 +02:00
case INTER_PROPERTY :
case INTER_METHOD :
2019-06-09 05:11:42 +02:00
// Simply return the given delta value
2014-08-25 07:36:56 +02:00
return p_data . delta_val ;
case FOLLOW_PROPERTY :
case FOLLOW_METHOD : {
2019-06-09 05:11:42 +02:00
// We're following an object, so grab that instance
2017-03-05 16:44:50 +01:00
Object * target = ObjectDB : : get_instance ( p_data . target_id ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( target = = nullptr , p_data . initial_val ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// We want to figure out the final value
2017-03-05 16:44:50 +01:00
Variant final_val ;
if ( p_data . type = = FOLLOW_PROPERTY ) {
2019-06-09 05:11:42 +02:00
// Read the property as-is
2017-03-05 16:44:50 +01:00
bool valid = false ;
2017-05-30 22:20:15 +02:00
final_val = target - > get_indexed ( p_data . target_key , & valid ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! valid , p_data . initial_val ) ;
} else {
2019-06-09 05:11:42 +02:00
// We're looking at a method. Call the method on the target object
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2020-04-02 01:20:12 +02:00
final_val = target - > call ( p_data . target_key [ 0 ] , nullptr , 0 , error ) ;
2020-02-19 20:27:19 +01:00
ERR_FAIL_COND_V ( error . error ! = Callable : : CallError : : CALL_OK , p_data . initial_val ) ;
2014-08-25 07:36:56 +02:00
}
2017-03-05 16:44:50 +01:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// If we're looking at an INT value, instead convert it to a FLOAT
2019-06-09 05:11:42 +02:00
// This is better for interpolation
2017-03-05 16:44:50 +01:00
if ( final_val . get_type ( ) = = Variant : : INT ) final_val = final_val . operator real_t ( ) ;
2019-06-09 05:11:42 +02:00
// Calculate the delta based on the initial value and the final value
2017-03-05 16:44:50 +01:00
_calc_delta_val ( p_data . initial_val , final_val , p_data . delta_val ) ;
return p_data . delta_val ;
2018-09-26 13:13:56 +02:00
}
2014-08-25 07:36:56 +02:00
case TARGETING_PROPERTY :
case TARGETING_METHOD : {
2019-06-09 05:11:42 +02:00
// Grab the initial value from the data to calculate delta
2017-03-05 16:44:50 +01:00
Variant initial_val = _get_initial_val ( p_data ) ;
2019-06-09 05:11:42 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// If we're looking at an INT value, instead convert it to a FLOAT
2019-06-09 05:11:42 +02:00
// This is better for interpolation
2017-03-05 16:44:50 +01:00
if ( initial_val . get_type ( ) = = Variant : : INT ) initial_val = initial_val . operator real_t ( ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Calculate the delta based on the initial value and the final value
2017-03-05 16:44:50 +01:00
_calc_delta_val ( initial_val , p_data . final_val , p_data . delta_val ) ;
return p_data . delta_val ;
2018-09-26 13:13:56 +02:00
}
case INTER_CALLBACK :
2019-06-09 05:11:42 +02:00
// Callbacks have no special delta
2018-09-26 13:13:56 +02:00
break ;
2014-08-25 07:36:56 +02:00
}
2019-06-09 05:11:42 +02:00
// If we've made it here, use the initial value as the delta
2014-08-25 07:36:56 +02:00
return p_data . initial_val ;
}
2017-03-05 16:44:50 +01:00
Variant Tween : : _run_equation ( InterpolateData & p_data ) {
2019-06-09 05:11:42 +02:00
// Get the initial and delta values from the data
2019-10-23 22:38:43 +02:00
Variant initial_val = _get_initial_val ( p_data ) ;
2017-03-05 16:44:50 +01:00
Variant & delta_val = _get_delta_val ( p_data ) ;
2014-08-20 06:01:41 +02:00
Variant result ;
2017-03-05 16:44:50 +01:00
# define APPLY_EQUATION(element) \
2017-01-13 19:40:18 +01:00
r . element = _run_equation ( p_data . trans_type , p_data . ease_type , p_data . elapsed - p_data . delay , i . element , d . element , p_data . duration ) ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// What type of data are we interpolating?
2017-03-05 16:44:50 +01:00
switch ( initial_val . get_type ( ) ) {
2014-12-19 10:13:20 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : BOOL :
2019-06-09 05:11:42 +02:00
// Run the boolean specific equation (checking if it is at least 0.5)
2017-03-05 16:44:50 +01:00
result = ( _run_equation ( p_data . trans_type , p_data . ease_type , p_data . elapsed - p_data . delay , initial_val , delta_val , p_data . duration ) ) > = 0.5 ;
break ;
2014-12-19 10:13:20 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : INT :
2019-06-09 05:11:42 +02:00
// Run the integer specific equation
2017-03-05 16:44:50 +01:00
result = ( int ) _run_equation ( p_data . trans_type , p_data . ease_type , p_data . elapsed - p_data . delay , ( int ) initial_val , ( int ) delta_val , p_data . duration ) ;
break ;
2014-08-20 06:01:41 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
case Variant : : FLOAT :
// Run the FLOAT specific equation
2017-03-05 16:44:50 +01:00
result = _run_equation ( p_data . trans_type , p_data . ease_type , p_data . elapsed - p_data . delay , ( real_t ) initial_val , ( real_t ) delta_val , p_data . duration ) ;
break ;
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : VECTOR2 : {
2019-06-09 05:11:42 +02:00
// Get vectors for initial and delta values
2014-08-20 06:01:41 +02:00
Vector2 i = initial_val ;
Vector2 d = delta_val ;
Vector2 r ;
2019-06-09 05:11:42 +02:00
// Execute the equation and mutate the r vector
// This uses the custom APPLY_EQUATION macro defined above
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2014-08-20 06:01:41 +02:00
2020-02-22 17:52:22 +01:00
case Variant : : RECT2 : {
// Get the Rect2 for initial and delta value
Rect2 i = initial_val ;
Rect2 d = delta_val ;
Rect2 r ;
// Execute the equation for the position and size of Rect2
APPLY_EQUATION ( position . x ) ;
APPLY_EQUATION ( position . y ) ;
APPLY_EQUATION ( size . x ) ;
APPLY_EQUATION ( size . y ) ;
result = r ;
} break ;
2017-03-05 16:44:50 +01:00
case Variant : : VECTOR3 : {
2019-06-09 05:11:42 +02:00
// Get vectors for initial and delta values
2014-08-20 06:01:41 +02:00
Vector3 i = initial_val ;
Vector3 d = delta_val ;
Vector3 r ;
2019-06-09 05:11:42 +02:00
// Execute the equation and mutate the r vector
// This uses the custom APPLY_EQUATION macro defined above
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
APPLY_EQUATION ( z ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM2D : {
2019-06-09 05:11:42 +02:00
// Get the transforms for initial and delta values
2017-02-07 08:45:49 +01:00
Transform2D i = initial_val ;
Transform2D d = delta_val ;
Transform2D r ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Execute the equation on the transforms and mutate the r transform
// This uses the custom APPLY_EQUATION macro defined above
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 ] ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2020-02-22 17:52:22 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : QUAT : {
2019-06-09 05:11:42 +02:00
// Get the quaternian for the initial and delta values
2014-08-20 06:01:41 +02:00
Quat i = initial_val ;
Quat d = delta_val ;
Quat r ;
2019-06-09 05:11:42 +02:00
// Execute the equation on the quaternian values and mutate the r quaternian
// This uses the custom APPLY_EQUATION macro defined above
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( x ) ;
APPLY_EQUATION ( y ) ;
APPLY_EQUATION ( z ) ;
APPLY_EQUATION ( w ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2020-02-22 17:52:22 +01:00
2017-11-17 03:09:00 +01:00
case Variant : : AABB : {
2019-06-09 05:11:42 +02:00
// Get the AABB's for the initial and delta values
2017-11-17 03:09:00 +01:00
AABB i = initial_val ;
AABB d = delta_val ;
AABB r ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Execute the equation for the position and size of the AABB's and mutate the r AABB
// This uses the custom APPLY_EQUATION macro defined above
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 ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2020-02-22 17:52:22 +01:00
case Variant : : BASIS : {
// Get the basis for initial and delta values
Basis i = initial_val ;
Basis d = delta_val ;
Basis r ;
// Execute the equation on all the basis and mutate the r basis
// This uses the custom APPLY_EQUATION macro defined above
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 ] ) ;
result = r ;
} break ;
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM : {
2019-06-09 05:11:42 +02:00
// Get the transforms for the initial and delta values
2014-08-20 06:01:41 +02:00
Transform i = initial_val ;
Transform d = delta_val ;
Transform r ;
2019-06-09 05:11:42 +02:00
// Execute the equation for each of the transforms and their origin and mutate the r transform
// This uses the custom APPLY_EQUATION macro defined above
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 ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2020-02-22 17:52:22 +01:00
2017-03-05 16:44:50 +01:00
case Variant : : COLOR : {
2019-06-09 05:11:42 +02:00
// Get the Color for initial and delta value
2014-08-20 06:01:41 +02:00
Color i = initial_val ;
Color d = delta_val ;
Color r ;
2019-06-09 05:11:42 +02:00
// Apply the equation on the Color RGBA, and mutate the r color
// This uses the custom APPLY_EQUATION macro defined above
2014-08-20 06:01:41 +02:00
APPLY_EQUATION ( r ) ;
APPLY_EQUATION ( g ) ;
APPLY_EQUATION ( b ) ;
APPLY_EQUATION ( a ) ;
result = r ;
2017-03-05 16:44:50 +01:00
} break ;
2020-02-22 17:52:22 +01:00
2017-05-30 22:20:15 +02:00
default : {
2019-06-09 05:11:42 +02:00
// If unknown, just return the initial value
2017-05-30 22:20:15 +02:00
result = initial_val ;
} break ;
2014-08-20 06:01:41 +02:00
} ;
# undef APPLY_EQUATION
2019-06-09 05:11:42 +02:00
// Return the result that was computed
2014-08-20 06:01:41 +02:00
return result ;
}
2017-03-05 16:44:50 +01:00
bool Tween : : _apply_tween_value ( InterpolateData & p_data , Variant & value ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Get the object we want to apply the new value to
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( p_data . id ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( object = = nullptr , false ) ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// What kind of data are we mutating?
2017-03-05 16:44:50 +01:00
switch ( p_data . type ) {
2014-08-20 06:01:41 +02:00
2014-08-22 05:24:53 +02:00
case INTER_PROPERTY :
2014-08-25 07:36:56 +02:00
case FOLLOW_PROPERTY :
2017-03-05 16:44:50 +01:00
case TARGETING_PROPERTY : {
2019-06-09 05:11:42 +02:00
// Simply set the property on the object
2017-03-05 16:44:50 +01:00
bool valid = false ;
2017-05-30 22:20:15 +02:00
object - > set_indexed ( p_data . key , value , & valid ) ;
2017-03-05 16:44:50 +01:00
return valid ;
}
2014-08-20 06:01:41 +02:00
2014-08-22 05:24:53 +02:00
case INTER_METHOD :
2014-08-25 07:36:56 +02:00
case FOLLOW_METHOD :
2017-03-05 16:44:50 +01:00
case TARGETING_METHOD : {
2019-06-09 05:11:42 +02:00
// We want to call the method on the target object
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2019-06-09 05:11:42 +02:00
// Do we have a non-nil value passed in?
2017-03-05 16:44:50 +01:00
if ( value . get_type ( ) ! = Variant : : NIL ) {
2019-06-09 05:11:42 +02:00
// Pass it as an argument to the function call
2017-03-05 16:44:50 +01:00
Variant * arg [ 1 ] = { & value } ;
2017-05-30 22:20:15 +02:00
object - > call ( p_data . key [ 0 ] , ( const Variant * * ) arg , 1 , error ) ;
2017-03-05 16:44:50 +01:00
} else {
2019-06-09 05:11:42 +02:00
// Don't pass any argument
2020-04-02 01:20:12 +02:00
object - > call ( p_data . key [ 0 ] , nullptr , 0 , error ) ;
2014-08-22 05:24:53 +02:00
}
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Did we get an error from the function call?
2020-02-19 20:27:19 +01:00
return error . error = = Callable : : CallError : : CALL_OK ;
2017-03-05 16:44:50 +01:00
}
2014-08-22 05:24:53 +02:00
case INTER_CALLBACK :
2019-06-09 05:11:42 +02:00
// Nothing to apply for a callback
2014-08-22 05:24:53 +02:00
break ;
} ;
2019-06-09 05:11:42 +02:00
// No issues found!
2014-08-20 06:01:41 +02:00
return true ;
}
void Tween : : _tween_process ( float p_delta ) {
2019-06-09 05:11:42 +02:00
// Process all of the pending commands
2015-05-05 05:12:17 +02:00
_process_pending_commands ( ) ;
2019-06-09 05:11:42 +02:00
// If the scale is 0, make no progress on the tweens
2014-08-20 06:01:41 +02:00
if ( speed_scale = = 0 )
return ;
2019-06-09 05:11:42 +02:00
// Update the delta and whether we are pending an update
p_delta * = speed_scale ;
2017-03-05 16:44:50 +01:00
pending_update + + ;
2014-08-22 05:24:53 +02:00
2019-06-09 05:11:42 +02:00
// Are we repeating the interpolations?
if ( repeat ) {
// For each interpolation...
bool repeats_finished = true ;
2017-03-05 16:44:50 +01:00
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the data from it
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-08-22 05:24:53 +02:00
2019-06-09 05:11:42 +02:00
// Is not finished?
2017-03-05 16:44:50 +01:00
if ( ! data . finish ) {
2019-06-09 05:11:42 +02:00
// We aren't finished yet, no need to check the rest
repeats_finished = false ;
2014-08-22 05:24:53 +02:00
break ;
}
}
2019-06-09 05:11:42 +02:00
// If we are all finished, we can reset all of the tweens
if ( repeats_finished )
2014-08-22 05:24:53 +02:00
reset_all ( ) ;
}
2019-06-09 05:11:42 +02:00
// Are all of the tweens complete?
bool all_finished = true ;
// For each tween we wish to interpolate...
2017-03-05 16:44:50 +01:00
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Get the data from it
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2019-06-09 05:11:42 +02:00
// Track if we hit one that isn't finished yet
2018-06-26 19:19:11 +02:00
all_finished = all_finished & & data . finish ;
2019-06-09 05:11:42 +02:00
// Is the data not active or already finished? No need to go any further
2017-03-05 16:44:50 +01:00
if ( ! data . active | | data . finish )
2014-08-20 06:01:41 +02:00
continue ;
2014-08-20 10:39:28 +02:00
2019-06-09 05:11:42 +02:00
// Get the target object for this interpolation
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( data . id ) ;
2020-04-02 01:20:12 +02:00
if ( object = = nullptr )
2014-08-22 05:24:53 +02:00
continue ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Are we still delaying this tween?
2014-08-21 09:34:16 +02:00
bool prev_delaying = data . elapsed < = data . delay ;
data . elapsed + = p_delta ;
2017-03-05 16:44:50 +01:00
if ( data . elapsed < data . delay )
2014-08-21 09:34:16 +02:00
continue ;
2017-03-05 16:44:50 +01:00
else if ( prev_delaying ) {
2019-06-09 05:11:42 +02:00
// We can apply the tween's value to the data and emit that the tween has started
2014-08-25 07:36:56 +02:00
_apply_tween_value ( data , data . initial_val ) ;
2018-06-26 19:19:11 +02:00
emit_signal ( " tween_started " , object , NodePath ( Vector < StringName > ( ) , data . key , false ) ) ;
2014-08-25 07:36:56 +02:00
}
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Are we at the end of the tween?
2017-03-05 16:44:50 +01:00
if ( data . elapsed > ( data . delay + data . duration ) ) {
2019-06-09 05:11:42 +02:00
// Set the elapsed time to the end and mark this one as finished
2017-01-13 19:40:18 +01:00
data . elapsed = data . delay + data . duration ;
2014-08-21 09:34:16 +02:00
data . finish = true ;
}
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Are we interpolating a callback?
2017-12-29 13:59:45 +01:00
if ( data . type = = INTER_CALLBACK ) {
2019-06-09 05:11:42 +02:00
// Is the tween completed?
2017-12-29 13:59:45 +01:00
if ( data . finish ) {
2019-06-09 05:11:42 +02:00
// Are we calling this callback deferred or immediately?
2017-12-29 13:59:45 +01:00
if ( data . call_deferred ) {
2019-06-09 05:11:42 +02:00
// Run the deferred function callback, applying the correct number of arguments
2017-12-29 13:59:45 +01:00
switch ( data . args ) {
case 0 :
object - > call_deferred ( data . key [ 0 ] ) ;
break ;
case 1 :
object - > call_deferred ( data . key [ 0 ] , data . arg [ 0 ] ) ;
break ;
case 2 :
object - > call_deferred ( data . key [ 0 ] , data . arg [ 0 ] , data . arg [ 1 ] ) ;
break ;
case 3 :
object - > call_deferred ( data . key [ 0 ] , data . arg [ 0 ] , data . arg [ 1 ] , data . arg [ 2 ] ) ;
break ;
case 4 :
object - > call_deferred ( data . key [ 0 ] , data . arg [ 0 ] , data . arg [ 1 ] , data . arg [ 2 ] , data . arg [ 3 ] ) ;
break ;
case 5 :
object - > call_deferred ( data . key [ 0 ] , data . arg [ 0 ] , data . arg [ 1 ] , data . arg [ 2 ] , data . arg [ 3 ] , data . arg [ 4 ] ) ;
break ;
2015-01-07 12:46:01 +01:00
}
2017-12-29 13:59:45 +01:00
} else {
2019-06-09 05:11:42 +02:00
// Call the function directly with the arguments
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2017-12-29 13:59:45 +01:00
Variant * arg [ 5 ] = {
& data . arg [ 0 ] ,
& data . arg [ 1 ] ,
& data . arg [ 2 ] ,
& data . arg [ 3 ] ,
& data . arg [ 4 ] ,
} ;
object - > call ( data . key [ 0 ] , ( const Variant * * ) arg , data . args , error ) ;
2014-08-25 07:36:56 +02:00
}
2017-12-29 13:59:45 +01:00
}
} else {
2019-06-09 05:11:42 +02:00
// We can apply the value directly
2017-12-29 13:59:45 +01:00
Variant result = _run_equation ( data ) ;
_apply_tween_value ( data , result ) ;
2019-06-09 05:11:42 +02:00
// Emit that the tween has taken a step
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
emit_signal ( " tween_step " , object , NodePath ( Vector < StringName > ( ) , data . key , false ) , data . elapsed , result ) ;
2014-08-22 05:24:53 +02:00
}
2019-06-09 05:11:42 +02:00
// Is the tween now finished?
2015-05-05 05:12:17 +02:00
if ( data . finish ) {
2019-06-09 05:11:42 +02:00
// Set it to the final value directly
2019-10-23 22:38:43 +02:00
Variant final_val = _get_final_val ( data ) ;
_apply_tween_value ( data , final_val ) ;
2019-06-09 05:11:42 +02:00
// Mark the tween as completed and emit the signal
2018-06-26 19:19:11 +02:00
data . elapsed = 0 ;
2017-05-30 22:20:15 +02:00
emit_signal ( " tween_completed " , object , NodePath ( Vector < StringName > ( ) , data . key , false ) ) ;
2019-06-09 05:11:42 +02:00
// If we are not repeating the tween, remove it
2015-05-05 05:12:17 +02:00
if ( ! repeat )
2018-08-15 17:26:10 +02:00
call_deferred ( " _remove_by_uid " , data . uid ) ;
2019-06-09 05:11:42 +02:00
} else if ( ! repeat ) {
// Check whether all tweens are finished
2018-06-26 19:19:11 +02:00
all_finished = all_finished & & data . finish ;
2019-06-09 05:11:42 +02:00
}
2014-08-20 06:01:41 +02:00
}
2019-06-09 05:11:42 +02:00
// One less update left to go
2017-03-05 16:44:50 +01:00
pending_update - - ;
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
2019-06-09 05:11:42 +02:00
// If all tweens are completed, we no longer need to be active
2019-03-19 13:58:37 +01:00
if ( all_finished ) {
2018-06-26 19:19:11 +02:00
set_active ( false ) ;
2019-03-19 13:58:37 +01:00
emit_signal ( " tween_all_completed " ) ;
}
2014-08-20 06:01:41 +02:00
}
void Tween : : set_tween_process_mode ( TweenProcessMode p_mode ) {
2017-03-05 16:44:50 +01:00
tween_process_mode = p_mode ;
2014-08-20 06:01:41 +02:00
}
Tween : : TweenProcessMode Tween : : get_tween_process_mode ( ) const {
return tween_process_mode ;
}
bool Tween : : is_active ( ) const {
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
return is_processing_internal ( ) | | is_physics_processing_internal ( ) ;
2014-08-20 06:01:41 +02:00
}
void Tween : : set_active ( bool p_active ) {
2019-06-09 05:11:42 +02:00
// Do nothing if it's the same active mode that we currently are
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
if ( is_active ( ) = = p_active )
2014-08-20 06:01:41 +02:00
return ;
2019-06-09 05:11:42 +02:00
// Depending on physics or idle, set processing
Fix and make Tween node less confusing
I've made the following changes:
- make `is_active` the main way of keeping track of tween
processing/activity, meaning that `is_active` will now return
`false` if all tween actions have finished or if it isn't started
or if it was stopped via `set_active(false)` or any other mode
- removed is_stopped because is redundand now
The above meant that we don't have to keep track of yet another variable
`available` since everything is based on `*processing_internal` so I
removed it, likewise it's own local `processing` variable was removed,
as well as the "double" `_set_process` which it feels more like a hack.
What wasn't changed:
- `tell()` still returns max value (i.e. `== get_runtime()` when all
tweens `finish`)
*More testing is needed*. So far I've tested repeat on/off, delay,
`is_active()` working corretly, `set_active(true), set_active(false)`,
but probably more tests are necessary, all the resets, stops, resume
etc.
2018-06-26 17:29:08 +02:00
switch ( tween_process_mode ) {
case TWEEN_PROCESS_IDLE : set_process_internal ( p_active ) ; break ;
case TWEEN_PROCESS_PHYSICS : set_physics_process_internal ( p_active ) ; break ;
}
2014-08-20 06:01:41 +02:00
}
2014-08-20 10:39:28 +02:00
bool Tween : : is_repeat ( ) const {
return repeat ;
}
void Tween : : set_repeat ( bool p_repeat ) {
repeat = p_repeat ;
}
2017-01-13 23:36:04 +01:00
void Tween : : set_speed_scale ( float p_speed ) {
2017-03-05 16:44:50 +01:00
speed_scale = p_speed ;
2014-08-20 06:01:41 +02:00
}
2017-01-13 23:36:04 +01:00
float Tween : : get_speed_scale ( ) const {
2014-08-20 06:01:41 +02:00
return speed_scale ;
}
2020-03-06 08:40:40 +01:00
void Tween : : start ( ) {
2019-09-01 01:25:22 +02:00
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! is_inside_tree ( ) , " Tween was not added to the SceneTree! " ) ;
2019-09-01 01:25:22 +02:00
2019-06-09 05:11:42 +02:00
// Are there any pending updates?
2018-09-09 23:23:15 +02:00
if ( pending_update ! = 0 ) {
2019-06-09 05:11:42 +02:00
// Start the tweens after deferring
2020-01-22 22:27:37 +01:00
call_deferred ( " start " ) ;
2020-03-06 08:40:40 +01:00
return ;
2018-09-09 23:23:15 +02:00
}
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// We want to be activated
2014-08-20 06:01:41 +02:00
set_active ( true ) ;
}
2020-03-06 08:40:40 +01:00
void Tween : : reset ( Object * p_object , StringName p_key ) {
2019-06-09 05:11:42 +02:00
// Find all interpolations that use the same object and target string
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the target object
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( data . id ) ;
2020-04-02 01:20:12 +02:00
if ( object = = nullptr )
2014-08-22 05:24:53 +02:00
continue ;
2019-06-09 05:11:42 +02:00
// Do we have the correct object and key?
2017-05-30 22:20:15 +02:00
if ( object = = p_object & & ( data . concatenated_key = = p_key | | p_key = = " " ) ) {
2019-06-09 05:11:42 +02:00
// Reset the tween to the initial state
2014-08-21 09:34:16 +02:00
data . elapsed = 0 ;
data . finish = false ;
2019-06-09 05:11:42 +02:00
// Also apply the initial state if there isn't a delay
2017-03-05 16:44:50 +01:00
if ( data . delay = = 0 )
2014-08-21 09:51:18 +02:00
_apply_tween_value ( data , data . initial_val ) ;
2014-08-21 09:34:16 +02:00
}
2014-08-20 06:01:41 +02:00
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : reset_all ( ) {
2019-06-09 05:11:42 +02:00
// Go through all interpolations
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the target data and set it back to the initial state
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-08-21 09:34:16 +02:00
data . elapsed = 0 ;
data . finish = false ;
2019-06-09 05:11:42 +02:00
// If there isn't a delay, apply the value to the object
2017-03-05 16:44:50 +01:00
if ( data . delay = = 0 )
2014-08-21 09:51:18 +02:00
_apply_tween_value ( data , data . initial_val ) ;
2014-08-20 06:01:41 +02:00
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : stop ( Object * p_object , StringName p_key ) {
2019-06-09 05:11:42 +02:00
// Find the tween that has the given target object and string key
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Get the object the tween is targeting
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( data . id ) ;
2020-04-02 01:20:12 +02:00
if ( object = = nullptr )
2014-08-22 05:24:53 +02:00
continue ;
2019-06-09 05:11:42 +02:00
// Is this the correct object and does it have the given key?
2017-05-30 22:20:15 +02:00
if ( object = = p_object & & ( data . concatenated_key = = p_key | | p_key = = " " ) )
2019-06-09 05:11:42 +02:00
// Disable the tween
2014-08-20 06:01:41 +02:00
data . active = false ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : stop_all ( ) {
2019-06-09 05:11:42 +02:00
// We no longer need to be active since all tweens have been stopped
2014-08-20 06:01:41 +02:00
set_active ( false ) ;
2019-06-09 05:11:42 +02:00
// For each interpolation...
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Simply set it inactive
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-08-20 06:01:41 +02:00
data . active = false ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : resume ( Object * p_object , StringName p_key ) {
2019-06-09 05:11:42 +02:00
// We need to be activated
// TODO: What if no tween is found??
2014-08-20 06:01:41 +02:00
set_active ( true ) ;
2019-06-09 05:11:42 +02:00
// Find the tween that uses the given target object and string key
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Grab the object
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( data . id ) ;
2020-04-02 01:20:12 +02:00
if ( object = = nullptr )
2014-08-22 05:24:53 +02:00
continue ;
2019-06-09 05:11:42 +02:00
// If the object and string key match, activate it
2017-05-30 22:20:15 +02:00
if ( object = = p_object & & ( data . concatenated_key = = p_key | | p_key = = " " ) )
2014-08-20 06:01:41 +02:00
data . active = true ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : resume_all ( ) {
2019-06-09 05:11:42 +02:00
// Set ourselves active so we can process tweens
// TODO: What if there are no tweens? We get set to active for no reason!
2014-08-20 06:01:41 +02:00
set_active ( true ) ;
2019-06-09 05:11:42 +02:00
// For each interpolation...
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Simply grab it and set it to active
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-08-20 06:01:41 +02:00
data . active = true ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : remove ( Object * p_object , StringName p_key ) {
2019-06-09 05:11:42 +02:00
// If we are still updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
2018-08-15 17:26:10 +02:00
call_deferred ( " remove " , p_object , p_key ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// For each interpolation...
2016-09-25 23:25:52 +02:00
List < List < InterpolateData > : : Element * > for_removal ;
2017-03-05 16:44:50 +01:00
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the target object
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-12-19 10:13:20 +01:00
Object * object = ObjectDB : : get_instance ( data . id ) ;
2020-04-02 01:20:12 +02:00
if ( object = = nullptr )
2014-08-22 05:24:53 +02:00
continue ;
2019-06-09 05:11:42 +02:00
// If the target object and string key match, queue it for removal
2017-05-30 22:20:15 +02:00
if ( object = = p_object & & ( data . concatenated_key = = p_key | | p_key = = " " ) ) {
2016-09-25 23:25:52 +02:00
for_removal . push_back ( E ) ;
2014-08-20 06:19:22 +02:00
}
}
2019-06-09 05:11:42 +02:00
// For each interpolation we wish to remove...
2017-03-05 16:44:50 +01:00
for ( List < List < InterpolateData > : : Element * > : : Element * E = for_removal . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Erase it
2016-09-25 23:25:52 +02:00
interpolates . erase ( E - > get ( ) ) ;
}
2018-08-15 17:26:10 +02:00
}
void Tween : : _remove_by_uid ( int uid ) {
2019-06-09 05:11:42 +02:00
// If we are still updating, call this function again later
2018-08-15 17:26:10 +02:00
if ( pending_update ! = 0 ) {
call_deferred ( " _remove_by_uid " , uid ) ;
return ;
}
2019-06-09 05:11:42 +02:00
// Find the interpolation that matches the given UID
2018-08-15 17:26:10 +02:00
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
if ( uid = = E - > get ( ) . uid ) {
2019-06-09 05:11:42 +02:00
// It matches, erase it and stop looking
2018-08-15 17:26:10 +02:00
E - > erase ( ) ;
break ;
}
}
}
void Tween : : _push_interpolate_data ( InterpolateData & p_data ) {
pending_update + + ;
2019-06-09 05:11:42 +02:00
// Add the new interpolation
2018-08-15 17:26:10 +02:00
p_data . uid = + + uid ;
interpolates . push_back ( p_data ) ;
2019-06-09 05:11:42 +02:00
2018-08-15 17:26:10 +02:00
pending_update - - ;
2014-08-20 06:19:22 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : remove_all ( ) {
2019-06-09 05:11:42 +02:00
// If we are still updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
2015-05-05 05:12:17 +02:00
call_deferred ( " remove_all " ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// We no longer need to be active
2014-08-20 06:19:22 +02:00
set_active ( false ) ;
2019-06-09 05:11:42 +02:00
// Clear out all interpolations and reset the uid
2014-08-20 06:19:22 +02:00
interpolates . clear ( ) ;
2018-08-15 17:26:10 +02:00
uid = 0 ;
2014-08-20 06:19:22 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : seek ( real_t p_time ) {
2019-06-09 05:11:42 +02:00
// Go through each interpolation...
2017-03-05 16:44:50 +01:00
pending_update + + ;
for ( List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the target data
2017-03-05 16:44:50 +01:00
InterpolateData & data = E - > get ( ) ;
2014-08-20 10:39:28 +02:00
2019-06-09 05:11:42 +02:00
// Update the elapsed data to be set to the target time
2014-08-20 10:39:28 +02:00
data . elapsed = p_time ;
2014-08-22 08:25:41 +02:00
2019-06-09 05:11:42 +02:00
// Are we at the end?
if ( data . elapsed < data . delay ) {
// There is still time left to go
2014-08-22 08:25:41 +02:00
data . finish = false ;
2014-08-21 09:34:16 +02:00
continue ;
2017-03-05 16:44:50 +01:00
} else if ( data . elapsed > = ( data . delay + data . duration ) ) {
2019-06-09 05:11:42 +02:00
// We are past the end of it, set the elapsed time to the end and mark as finished
2017-01-13 19:40:18 +01:00
data . elapsed = ( data . delay + data . duration ) ;
2019-06-09 05:11:42 +02:00
data . finish = true ;
2017-05-30 22:20:15 +02:00
} else {
2019-06-09 05:11:42 +02:00
// We are not finished with this interpolation yet
2014-08-22 08:25:41 +02:00
data . finish = false ;
2017-05-30 22:20:15 +02:00
}
2014-08-20 10:39:28 +02:00
2019-06-09 05:11:42 +02:00
// If we are a callback, do nothing special
2018-09-26 13:13:56 +02:00
if ( data . type = = INTER_CALLBACK ) {
continue ;
2014-08-22 05:24:53 +02:00
}
2019-06-09 05:11:42 +02:00
// Run the equation on the data and apply the value
2014-08-20 10:39:28 +02:00
Variant result = _run_equation ( data ) ;
_apply_tween_value ( data , result ) ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-20 10:39:28 +02:00
}
2014-08-20 06:19:22 +02:00
2014-08-22 08:25:41 +02:00
real_t Tween : : tell ( ) const {
2019-06-09 05:11:42 +02:00
// We want to grab the position of the furthest along tween
2017-03-05 16:44:50 +01:00
pending_update + + ;
2014-08-22 08:25:41 +02:00
real_t pos = 0 ;
2019-06-09 05:11:42 +02:00
// For each interpolation...
for ( const List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
// Get the data and figure out if it's position is further along than the previous ones
2017-03-05 16:44:50 +01:00
const InterpolateData & data = E - > get ( ) ;
if ( data . elapsed > pos )
2019-06-09 05:11:42 +02:00
// Save it if so
2014-08-22 08:25:41 +02:00
pos = data . elapsed ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2014-08-22 08:25:41 +02:00
return pos ;
}
real_t Tween : : get_runtime ( ) const {
2019-06-09 05:11:42 +02:00
// If the tween isn't moving, it'll last forever
2018-05-23 13:55:15 +02:00
if ( speed_scale = = 0 ) {
return INFINITY ;
}
2017-03-05 16:44:50 +01:00
pending_update + + ;
2019-06-09 05:11:42 +02:00
// For each interpolation...
2014-08-21 09:34:16 +02:00
real_t runtime = 0 ;
2017-03-05 16:44:50 +01:00
for ( const List < InterpolateData > : : Element * E = interpolates . front ( ) ; E ; E = E - > next ( ) ) {
2019-06-09 05:11:42 +02:00
// Get the tween data and see if it's runtime is greater than the previous tweens
2017-03-05 16:44:50 +01:00
const InterpolateData & data = E - > get ( ) ;
2017-01-13 19:40:18 +01:00
real_t t = data . delay + data . duration ;
2017-03-05 16:44:50 +01:00
if ( t > runtime )
2019-06-09 05:11:42 +02:00
// This is the longest running tween
2014-08-21 09:34:16 +02:00
runtime = t ;
}
2017-03-05 16:44:50 +01:00
pending_update - - ;
2018-05-23 13:55:15 +02:00
2019-06-09 05:11:42 +02:00
// Adjust the runtime for the current speed scale
2018-05-23 13:55:15 +02:00
return runtime / speed_scale ;
2014-08-21 09:34:16 +02:00
}
2017-03-05 16:44:50 +01:00
bool Tween : : _calc_delta_val ( const Variant & p_initial_val , const Variant & p_final_val , Variant & p_delta_val ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Get the initial, final, and delta values
2017-03-05 16:44:50 +01:00
const Variant & initial_val = p_initial_val ;
const Variant & final_val = p_final_val ;
Variant & delta_val = p_delta_val ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// What kind of data are we interpolating?
2017-03-05 16:44:50 +01:00
switch ( initial_val . get_type ( ) ) {
2014-12-19 10:13:20 +01:00
case Variant : : BOOL :
2019-06-09 05:11:42 +02:00
// We'll treat booleans just like integers
2014-08-20 06:01:41 +02:00
case Variant : : INT :
2019-06-09 05:11:42 +02:00
// Compute the integer delta
2017-03-05 16:44:50 +01:00
delta_val = ( int ) final_val - ( int ) initial_val ;
2014-08-20 06:01:41 +02:00
break ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
case Variant : : FLOAT :
// Convert to FLOAT and find the delta
2017-03-05 16:44:50 +01:00
delta_val = ( real_t ) final_val - ( real_t ) initial_val ;
2014-08-20 06:01:41 +02:00
break ;
case Variant : : VECTOR2 :
2019-06-09 05:11:42 +02:00
// Convert to Vectors and find the delta
2014-08-20 06:01:41 +02:00
delta_val = final_val . operator Vector2 ( ) - initial_val . operator Vector2 ( ) ;
break ;
2020-02-22 17:52:22 +01:00
case Variant : : RECT2 : {
// Build a new Rect2 and use the new position and sizes to make a delta
Rect2 i = initial_val ;
Rect2 f = final_val ;
delta_val = Rect2 ( f . position - i . position , f . size - i . size ) ;
} break ;
2014-08-20 06:01:41 +02:00
case Variant : : VECTOR3 :
2019-06-09 05:11:42 +02:00
// Convert to Vectors and find the delta
2014-08-20 06:01:41 +02:00
delta_val = final_val . operator Vector3 ( ) - initial_val . operator Vector3 ( ) ;
break ;
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM2D : {
2019-06-09 05:11:42 +02:00
// Build a new transform which is the difference between the initial and final values
2017-03-05 16:44:50 +01:00
Transform2D i = initial_val ;
Transform2D f = final_val ;
Transform2D d = Transform2D ( ) ;
d [ 0 ] [ 0 ] = f . elements [ 0 ] [ 0 ] - i . elements [ 0 ] [ 0 ] ;
d [ 0 ] [ 1 ] = f . elements [ 0 ] [ 1 ] - i . elements [ 0 ] [ 1 ] ;
d [ 1 ] [ 0 ] = f . elements [ 1 ] [ 0 ] - i . elements [ 1 ] [ 0 ] ;
d [ 1 ] [ 1 ] = f . elements [ 1 ] [ 1 ] - i . elements [ 1 ] [ 1 ] ;
d [ 2 ] [ 0 ] = f . elements [ 2 ] [ 0 ] - i . elements [ 2 ] [ 0 ] ;
d [ 2 ] [ 1 ] = f . elements [ 2 ] [ 1 ] - i . elements [ 2 ] [ 1 ] ;
delta_val = d ;
} break ;
2019-06-09 05:11:42 +02:00
2014-08-20 06:01:41 +02:00
case Variant : : QUAT :
2019-06-09 05:11:42 +02:00
// Convert to quaternianls and find the delta
2014-08-20 06:01:41 +02:00
delta_val = final_val . operator Quat ( ) - initial_val . operator Quat ( ) ;
break ;
2019-06-09 05:11:42 +02:00
2017-11-17 03:09:00 +01:00
case Variant : : AABB : {
2019-06-09 05:11:42 +02:00
// Build a new AABB and use the new position and sizes to make a delta
2017-11-17 03:09:00 +01:00
AABB i = initial_val ;
AABB f = final_val ;
delta_val = AABB ( f . position - i . position , f . size - i . size ) ;
2017-03-05 16:44:50 +01:00
} break ;
2019-06-09 05:11:42 +02:00
2020-02-22 17:52:22 +01:00
case Variant : : BASIS : {
// Build a new basis which is the delta between the initial and final values
Basis i = initial_val ;
Basis f = final_val ;
delta_val = Basis ( f . elements [ 0 ] [ 0 ] - i . elements [ 0 ] [ 0 ] ,
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 ] ) ;
} break ;
2017-03-05 16:44:50 +01:00
case Variant : : TRANSFORM : {
2019-06-09 05:11:42 +02:00
// Build a new transform which is the difference between the initial and final values
2017-03-05 16:44:50 +01:00
Transform i = initial_val ;
Transform f = final_val ;
Transform d ;
d . set ( 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 ) ;
2014-08-20 06:01:41 +02:00
2017-03-05 16:44:50 +01:00
delta_val = d ;
} break ;
2019-06-09 05:11:42 +02:00
2017-03-05 16:44:50 +01:00
case Variant : : COLOR : {
2019-06-09 05:11:42 +02:00
// Make a new color which is the difference between each the color's RGBA attributes
2017-03-05 16:44:50 +01:00
Color i = initial_val ;
Color f = final_val ;
delta_val = Color ( f . r - i . r , f . g - i . g , f . b - i . b , f . a - i . a ) ;
} break ;
2014-08-20 06:01:41 +02:00
2020-02-22 17:52:22 +01:00
default : {
static Variant : : Type supported_types [ ] = {
Variant : : BOOL ,
Variant : : INT ,
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
Variant : : FLOAT ,
2020-02-22 17:52:22 +01:00
Variant : : VECTOR2 ,
Variant : : RECT2 ,
Variant : : VECTOR3 ,
Variant : : TRANSFORM2D ,
Variant : : QUAT ,
Variant : : AABB ,
Variant : : BASIS ,
Variant : : TRANSFORM ,
Variant : : COLOR ,
} ;
int length = * ( & supported_types + 1 ) - supported_types ;
String error_msg = " Invalid parameter type. Supported types are: " ;
for ( int i = 0 ; i < length ; i + + ) {
if ( i ! = 0 ) {
error_msg + = " , " ;
}
error_msg + = Variant : : get_type_name ( supported_types [ i ] ) ;
}
error_msg + = " . " ;
ERR_PRINT ( error_msg ) ;
2014-08-20 06:01:41 +02:00
return false ;
2020-02-22 17:52:22 +01:00
}
2014-08-20 06:01:41 +02:00
} ;
return true ;
}
2020-03-06 08:40:40 +01:00
void Tween : : _build_interpolation ( InterpolateType p_interpolation_type , Object * p_object , NodePath * p_property , StringName * p_method , Variant p_initial_val , Variant p_final_val , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// TODO: Add initialization+implementation for remaining interpolation types
// TODO: Fix this method's organization to take advantage of the type
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Make a new interpolation data
2014-08-20 06:01:41 +02:00
InterpolateData data ;
data . active = true ;
2019-06-09 05:11:42 +02:00
data . type = p_interpolation_type ;
2014-08-21 09:34:16 +02:00
data . finish = false ;
2014-08-20 06:01:41 +02:00
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Validate and apply interpolation data
// Give it the object
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_MSG ( p_object = = nullptr , " Invalid object provided to Tween. " ) ;
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2019-06-09 05:11:42 +02:00
// Validate the initial and final values
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( p_initial_val . get_type ( ) ! = p_final_val . get_type ( ) , " Initial value type ' " + Variant : : get_type_name ( p_initial_val . get_type ( ) ) + " ' does not match final value type ' " + Variant : : get_type_name ( p_final_val . get_type ( ) ) + " '. " ) ;
2014-08-20 06:01:41 +02:00
data . initial_val = p_initial_val ;
data . final_val = p_final_val ;
2019-06-09 05:11:42 +02:00
// Check the Duration
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( p_duration < 0 , " Only non-negative duration values allowed in Tweens. " ) ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2019-06-09 05:11:42 +02:00
// Tween Delay
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( p_delay < 0 , " Only non-negative delay values allowed in Tweens. " ) ;
2019-06-09 05:11:42 +02:00
data . delay = p_delay ;
// Transition type
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( p_trans_type < 0 | | p_trans_type > = TRANS_COUNT , " Invalid transition type provided to Tween. " ) ;
2014-08-20 06:01:41 +02:00
data . trans_type = p_trans_type ;
2019-06-09 05:11:42 +02:00
// Easing type
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( p_ease_type < 0 | | p_ease_type > = EASE_COUNT , " Invalid easing type provided to Tween. " ) ;
2014-08-20 06:01:41 +02:00
data . ease_type = p_ease_type ;
2019-06-09 05:11:42 +02:00
// Is the property defined?
if ( p_property ) {
// Check that the object actually contains the given property
bool prop_valid = false ;
p_object - > get_indexed ( p_property - > get_subnames ( ) , & prop_valid ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! prop_valid , " Tween target object has no property named: " + p_property - > get_concatenated_subnames ( ) + " . " ) ;
2019-06-09 05:11:42 +02:00
data . key = p_property - > get_subnames ( ) ;
data . concatenated_key = p_property - > get_concatenated_subnames ( ) ;
}
// Is the method defined?
if ( p_method ) {
// Does the object even have the requested method?
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! p_object - > has_method ( * p_method ) , " Tween target object has no method named: " + * p_method + " . " ) ;
2019-06-09 05:11:42 +02:00
data . key . push_back ( * p_method ) ;
data . concatenated_key = * p_method ;
}
// Is there not a valid delta?
2017-03-05 16:44:50 +01:00
if ( ! _calc_delta_val ( data . initial_val , data . final_val , data . delta_val ) )
2020-03-06 08:40:40 +01:00
return ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Add this interpolation to the total
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : interpolate_property ( Object * p_object , NodePath p_property , Variant p_initial_val , Variant p_final_val , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are busy updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
2019-06-09 05:11:42 +02:00
_add_pending_command ( " interpolate_property " , p_object , p_property , p_initial_val , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
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
2019-06-09 05:11:42 +02:00
// Get the property from the node path
p_property = p_property . get_as_property_path ( ) ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// If no initial value given, grab the initial value from the object
// TODO: Is this documented? This is very useful and removes a lot of clutter from tweens!
if ( p_initial_val . get_type ( ) = = Variant : : NIL ) p_initial_val = p_object - > get_indexed ( p_property . get_subnames ( ) ) ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Convert any integers into REALs as they are better for interpolation
if ( p_initial_val . get_type ( ) = = Variant : : INT ) p_initial_val = p_initial_val . operator real_t ( ) ;
if ( p_final_val . get_type ( ) = = Variant : : INT ) p_final_val = p_final_val . operator real_t ( ) ;
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Build the interpolation data
2020-04-02 01:20:12 +02:00
_build_interpolation ( INTER_PROPERTY , p_object , & p_property , nullptr , p_initial_val , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2019-06-09 05:11:42 +02:00
}
2014-08-20 06:01:41 +02:00
2020-03-06 08:40:40 +01:00
void Tween : : interpolate_method ( Object * p_object , StringName p_method , Variant p_initial_val , Variant p_final_val , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are busy updating, call this function again later
if ( pending_update ! = 0 ) {
_add_pending_command ( " interpolate_method " , p_object , p_method , p_initial_val , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2020-03-06 08:40:40 +01:00
return ;
2019-06-09 05:11:42 +02:00
}
2014-08-20 06:01:41 +02:00
2019-06-09 05:11:42 +02:00
// Convert any integers into REALs as they are better for interpolation
if ( p_initial_val . get_type ( ) = = Variant : : INT ) p_initial_val = p_initial_val . operator real_t ( ) ;
if ( p_final_val . get_type ( ) = = Variant : : INT ) p_final_val = p_final_val . operator real_t ( ) ;
// Build the interpolation data
2020-04-02 01:20:12 +02:00
_build_interpolation ( INTER_METHOD , p_object , nullptr , & p_method , p_initial_val , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2014-08-20 06:01:41 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : interpolate_callback ( Object * p_object , real_t p_duration , String p_callback , VARIANT_ARG_DECLARE ) {
2019-06-09 05:11:42 +02:00
// If we are already updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " interpolate_callback " , p_object , p_duration , p_callback , p_arg1 , p_arg2 , p_arg3 , p_arg4 , p_arg5 ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2016-04-07 09:45:16 +02:00
2019-06-09 05:11:42 +02:00
// Check that the target object is valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// Duration cannot be negative
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2015-01-07 12:46:01 +01:00
2019-06-09 05:11:42 +02:00
// Check whether the object even has the callback
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! p_object - > has_method ( p_callback ) , " Object has no callback named: " + p_callback + " . " ) ;
2015-01-07 12:46:01 +01:00
2019-06-09 05:11:42 +02:00
// Build a new InterpolationData
2015-01-07 12:46:01 +01:00
InterpolateData data ;
data . active = true ;
data . type = INTER_CALLBACK ;
data . finish = false ;
data . call_deferred = false ;
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Give the data it's configuration
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key . push_back ( p_callback ) ;
data . concatenated_key = p_callback ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2015-01-07 12:46:01 +01:00
data . delay = 0 ;
2019-06-09 05:11:42 +02:00
// Add arguments to the interpolation
2017-03-05 16:44:50 +01:00
int args = 0 ;
if ( p_arg5 . get_type ( ) ! = Variant : : NIL )
args = 5 ;
else if ( p_arg4 . get_type ( ) ! = Variant : : NIL )
args = 4 ;
else if ( p_arg3 . get_type ( ) ! = Variant : : NIL )
args = 3 ;
else if ( p_arg2 . get_type ( ) ! = Variant : : NIL )
args = 2 ;
else if ( p_arg1 . get_type ( ) ! = Variant : : NIL )
args = 1 ;
2016-03-09 00:00:52 +01:00
else
2017-03-05 16:44:50 +01:00
args = 0 ;
2015-01-07 12:46:01 +01:00
data . args = args ;
data . arg [ 0 ] = p_arg1 ;
data . arg [ 1 ] = p_arg2 ;
data . arg [ 2 ] = p_arg3 ;
data . arg [ 3 ] = p_arg4 ;
data . arg [ 4 ] = p_arg5 ;
2019-06-09 05:11:42 +02:00
// Add the new interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2015-01-07 12:46:01 +01:00
}
2020-03-06 08:40:40 +01:00
void Tween : : interpolate_deferred_callback ( Object * p_object , real_t p_duration , String p_callback , VARIANT_ARG_DECLARE ) {
2019-06-09 05:11:42 +02:00
// If we are already updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " interpolate_deferred_callback " , p_object , p_duration , p_callback , p_arg1 , p_arg2 , p_arg3 , p_arg4 , p_arg5 ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// Check that the target object is valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// No negative durations allowed
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2014-08-22 05:24:53 +02:00
2019-06-09 05:11:42 +02:00
// Confirm the callback exists on the object
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! p_object - > has_method ( p_callback ) , " Object has no callback named: " + p_callback + " . " ) ;
2014-08-22 05:24:53 +02:00
2019-06-09 05:11:42 +02:00
// Create a new InterpolateData for the callback
2014-08-22 05:24:53 +02:00
InterpolateData data ;
data . active = true ;
data . type = INTER_CALLBACK ;
data . finish = false ;
2015-01-07 12:46:01 +01:00
data . call_deferred = true ;
2014-08-22 05:24:53 +02:00
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Give the data it's configuration
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key . push_back ( p_callback ) ;
data . concatenated_key = p_callback ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2014-08-22 05:24:53 +02:00
data . delay = 0 ;
2015-01-07 12:46:01 +01:00
2019-06-09 05:11:42 +02:00
// Collect arguments for the callback
2017-03-05 16:44:50 +01:00
int args = 0 ;
if ( p_arg5 . get_type ( ) ! = Variant : : NIL )
args = 5 ;
else if ( p_arg4 . get_type ( ) ! = Variant : : NIL )
args = 4 ;
else if ( p_arg3 . get_type ( ) ! = Variant : : NIL )
args = 3 ;
else if ( p_arg2 . get_type ( ) ! = Variant : : NIL )
args = 2 ;
else if ( p_arg1 . get_type ( ) ! = Variant : : NIL )
args = 1 ;
2016-03-09 00:00:52 +01:00
else
2017-03-05 16:44:50 +01:00
args = 0 ;
2015-01-07 12:46:01 +01:00
data . args = args ;
data . arg [ 0 ] = p_arg1 ;
data . arg [ 1 ] = p_arg2 ;
data . arg [ 2 ] = p_arg3 ;
data . arg [ 3 ] = p_arg4 ;
data . arg [ 4 ] = p_arg5 ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Add the new interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-25 07:36:56 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : follow_property ( Object * p_object , NodePath p_property , Variant p_initial_val , Object * p_target , NodePath p_target_property , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are already updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " follow_property " , p_object , p_property , p_initial_val , p_target , p_target_property , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// Get the two properties from their paths
2017-05-30 22:20:15 +02:00
p_property = p_property . get_as_property_path ( ) ;
p_target_property = p_target_property . get_as_property_path ( ) ;
2019-06-09 05:11:42 +02:00
// If no initial value is given, grab it from the source object
// TODO: Is this documented? It's really helpful for decluttering tweens
2017-05-30 22:20:15 +02:00
if ( p_initial_val . get_type ( ) = = Variant : : NIL ) p_initial_val = p_object - > get_indexed ( p_property . get_subnames ( ) ) ;
2017-05-30 22:21:50 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert initial INT values to FLOAT as they are better for interpolation
2017-03-05 16:44:50 +01:00
if ( p_initial_val . get_type ( ) = = Variant : : INT ) p_initial_val = p_initial_val . operator real_t ( ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Confirm the source and target objects are valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
ERR_FAIL_COND ( p_target = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// No negative durations
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2019-06-09 05:11:42 +02:00
// Ensure transition and easing types are valid
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_trans_type < 0 | | p_trans_type > = TRANS_COUNT ) ;
ERR_FAIL_COND ( p_ease_type < 0 | | p_ease_type > = EASE_COUNT ) ;
2019-06-09 05:11:42 +02:00
// No negative delays
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_delay < 0 ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Confirm the source and target objects have the desired properties
2014-08-25 07:36:56 +02:00
bool prop_valid = false ;
2017-05-30 22:20:15 +02:00
p_object - > get_indexed ( p_property . get_subnames ( ) , & prop_valid ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( ! prop_valid ) ;
2014-08-25 07:36:56 +02:00
bool target_prop_valid = false ;
2017-05-30 22:20:15 +02:00
Variant target_val = p_target - > get_indexed ( p_target_property . get_subnames ( ) , & target_prop_valid ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( ! target_prop_valid ) ;
2014-08-25 07:36:56 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert target INT to FLOAT since it is better for interpolation
2017-03-05 16:44:50 +01:00
if ( target_val . get_type ( ) = = Variant : : INT ) target_val = target_val . operator real_t ( ) ;
2019-06-09 05:11:42 +02:00
// Verify that the target value and initial value are the same type
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( target_val . get_type ( ) ! = p_initial_val . get_type ( ) ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Create a new InterpolateData
2014-08-25 07:36:56 +02:00
InterpolateData data ;
data . active = true ;
data . type = FOLLOW_PROPERTY ;
data . finish = false ;
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Give the InterpolateData it's configuration
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key = p_property . get_subnames ( ) ;
data . concatenated_key = p_property . get_concatenated_subnames ( ) ;
2014-08-25 07:36:56 +02:00
data . initial_val = p_initial_val ;
2017-08-07 12:17:31 +02:00
data . target_id = p_target - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . target_key = p_target_property . get_subnames ( ) ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2014-08-25 07:36:56 +02:00
data . trans_type = p_trans_type ;
data . ease_type = p_ease_type ;
data . delay = p_delay ;
2019-06-09 05:11:42 +02:00
// Add the interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-25 07:36:56 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : follow_method ( Object * p_object , StringName p_method , Variant p_initial_val , Object * p_target , StringName p_target_method , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are currently updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " follow_method " , p_object , p_method , p_initial_val , p_target , p_target_method , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert initial INT values to FLOAT as they are better for interpolation
2017-03-05 16:44:50 +01:00
if ( p_initial_val . get_type ( ) = = Variant : : INT ) p_initial_val = p_initial_val . operator real_t ( ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Verify the source and target objects are valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
ERR_FAIL_COND ( p_target = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// No negative durations
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2019-06-09 05:11:42 +02:00
// Ensure that the transition and ease types are valid
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_trans_type < 0 | | p_trans_type > = TRANS_COUNT ) ;
ERR_FAIL_COND ( p_ease_type < 0 | | p_ease_type > = EASE_COUNT ) ;
2019-06-09 05:11:42 +02:00
// No negative delays
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_delay < 0 ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Confirm both objects have the target methods
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! p_object - > has_method ( p_method ) , " Object has no method named: " + p_method + " . " ) ;
ERR_FAIL_COND_MSG ( ! p_target - > has_method ( p_target_method ) , " Target has no method named: " + p_target_method + " . " ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Call the method to get the target value
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2020-04-02 01:20:12 +02:00
Variant target_val = p_target - > call ( p_target_method , nullptr , 0 , error ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( error . error ! = Callable : : CallError : : CALL_OK ) ;
2014-08-25 07:36:56 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert target INT values to FLOAT as they are better for interpolation
2017-03-05 16:44:50 +01:00
if ( target_val . get_type ( ) = = Variant : : INT ) target_val = target_val . operator real_t ( ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( target_val . get_type ( ) ! = p_initial_val . get_type ( ) ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Make the new InterpolateData for the method follow
2014-08-25 07:36:56 +02:00
InterpolateData data ;
data . active = true ;
data . type = FOLLOW_METHOD ;
data . finish = false ;
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Give the data it's configuration
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key . push_back ( p_method ) ;
data . concatenated_key = p_method ;
2014-08-25 07:36:56 +02:00
data . initial_val = p_initial_val ;
2017-08-07 12:17:31 +02:00
data . target_id = p_target - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . target_key . push_back ( p_target_method ) ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2014-08-25 07:36:56 +02:00
data . trans_type = p_trans_type ;
data . ease_type = p_ease_type ;
data . delay = p_delay ;
2019-06-09 05:11:42 +02:00
// Add the new interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-25 07:36:56 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : targeting_property ( Object * p_object , NodePath p_property , Object * p_initial , NodePath p_initial_property , Variant p_final_val , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are currently updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " targeting_property " , p_object , p_property , p_initial , p_initial_property , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
// Grab the target property and the target property
2017-05-30 22:20:15 +02:00
p_property = p_property . get_as_property_path ( ) ;
p_initial_property = p_initial_property . get_as_property_path ( ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert the initial INT values to FLOAT as they are better for Interpolation
2017-03-05 16:44:50 +01:00
if ( p_final_val . get_type ( ) = = Variant : : INT ) p_final_val = p_final_val . operator real_t ( ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Verify both objects are valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
ERR_FAIL_COND ( p_initial = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// No negative durations
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2019-06-09 05:11:42 +02:00
// Ensure transition and easing types are valid
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_trans_type < 0 | | p_trans_type > = TRANS_COUNT ) ;
ERR_FAIL_COND ( p_ease_type < 0 | | p_ease_type > = EASE_COUNT ) ;
2019-06-09 05:11:42 +02:00
// No negative delays
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_delay < 0 ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Ensure the initial and target properties exist on their objects
2014-08-25 07:36:56 +02:00
bool prop_valid = false ;
2017-05-30 22:20:15 +02:00
p_object - > get_indexed ( p_property . get_subnames ( ) , & prop_valid ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( ! prop_valid ) ;
2014-08-25 07:36:56 +02:00
bool initial_prop_valid = false ;
2017-05-30 22:20:15 +02:00
Variant initial_val = p_initial - > get_indexed ( p_initial_property . get_subnames ( ) , & initial_prop_valid ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( ! initial_prop_valid ) ;
2014-08-25 07:36:56 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert the initial INT value to FLOAT as it is better for interpolation
2017-03-05 16:44:50 +01:00
if ( initial_val . get_type ( ) = = Variant : : INT ) initial_val = initial_val . operator real_t ( ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( initial_val . get_type ( ) ! = p_final_val . get_type ( ) ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Build the InterpolateData object
2014-08-25 07:36:56 +02:00
InterpolateData data ;
data . active = true ;
data . type = TARGETING_PROPERTY ;
data . finish = false ;
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Give the data it's configuration
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key = p_property . get_subnames ( ) ;
data . concatenated_key = p_property . get_concatenated_subnames ( ) ;
2017-08-07 12:17:31 +02:00
data . target_id = p_initial - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . target_key = p_initial_property . get_subnames ( ) ;
2014-08-25 07:36:56 +02:00
data . initial_val = initial_val ;
data . final_val = p_final_val ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2014-08-25 07:36:56 +02:00
data . trans_type = p_trans_type ;
data . ease_type = p_ease_type ;
data . delay = p_delay ;
2019-06-09 05:11:42 +02:00
// Ensure there is a valid delta
2020-03-06 08:40:40 +01:00
if ( ! _calc_delta_val ( data . initial_val , data . final_val , data . delta_val ) ) {
return ;
}
2014-08-22 05:24:53 +02:00
2019-06-09 05:11:42 +02:00
// Add the interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-22 05:24:53 +02:00
}
2020-03-06 08:40:40 +01:00
void Tween : : targeting_method ( Object * p_object , StringName p_method , Object * p_initial , StringName p_initial_method , Variant p_final_val , real_t p_duration , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) {
2019-06-09 05:11:42 +02:00
// If we are currently updating, call this function again later
2017-03-05 16:44:50 +01:00
if ( pending_update ! = 0 ) {
_add_pending_command ( " targeting_method " , p_object , p_method , p_initial , p_initial_method , p_final_val , p_duration , p_trans_type , p_ease_type , p_delay ) ;
2020-03-06 08:40:40 +01:00
return ;
2015-05-05 05:12:17 +02:00
}
2019-06-09 05:11:42 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert final INT values to FLOAT as they are better for interpolation
2017-03-05 16:44:50 +01:00
if ( p_final_val . get_type ( ) = = Variant : : INT ) p_final_val = p_final_val . operator real_t ( ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Make sure the given objects are valid
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( p_object = = nullptr ) ;
ERR_FAIL_COND ( p_initial = = nullptr ) ;
2019-06-09 05:11:42 +02:00
// No negative durations
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_duration < 0 ) ;
2019-06-09 05:11:42 +02:00
// Ensure transition and easing types are valid
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_trans_type < 0 | | p_trans_type > = TRANS_COUNT ) ;
ERR_FAIL_COND ( p_ease_type < 0 | | p_ease_type > = EASE_COUNT ) ;
2019-06-09 05:11:42 +02:00
// No negative delays
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( p_delay < 0 ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Make sure both objects have the given method
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND_MSG ( ! p_object - > has_method ( p_method ) , " Object has no method named: " + p_method + " . " ) ;
ERR_FAIL_COND_MSG ( ! p_initial - > has_method ( p_initial_method ) , " Initial Object has no method named: " + p_initial_method + " . " ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Call the method to get the initial value
2020-02-19 20:27:19 +01:00
Callable : : CallError error ;
2020-04-02 01:20:12 +02:00
Variant initial_val = p_initial - > call ( p_initial_method , nullptr , 0 , error ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( error . error ! = Callable : : CallError : : CALL_OK ) ;
2014-08-25 07:36:56 +02:00
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
// Convert initial INT values to FLOAT as they aer better for interpolation
2017-03-05 16:44:50 +01:00
if ( initial_val . get_type ( ) = = Variant : : INT ) initial_val = initial_val . operator real_t ( ) ;
2020-03-06 08:40:40 +01:00
ERR_FAIL_COND ( initial_val . get_type ( ) ! = p_final_val . get_type ( ) ) ;
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Build the new InterpolateData object
2014-08-25 07:36:56 +02:00
InterpolateData data ;
data . active = true ;
data . type = TARGETING_METHOD ;
data . finish = false ;
data . elapsed = 0 ;
2019-06-09 05:11:42 +02:00
// Configure the data
2017-08-07 12:17:31 +02:00
data . id = p_object - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . key . push_back ( p_method ) ;
data . concatenated_key = p_method ;
2017-08-07 12:17:31 +02:00
data . target_id = p_initial - > get_instance_id ( ) ;
2017-05-30 22:20:15 +02:00
data . target_key . push_back ( p_initial_method ) ;
2014-08-25 07:36:56 +02:00
data . initial_val = initial_val ;
data . final_val = p_final_val ;
2017-01-13 19:40:18 +01:00
data . duration = p_duration ;
2014-08-25 07:36:56 +02:00
data . trans_type = p_trans_type ;
data . ease_type = p_ease_type ;
data . delay = p_delay ;
2019-06-09 05:11:42 +02:00
// Ensure there is a valid delta
2020-03-06 08:40:40 +01:00
if ( ! _calc_delta_val ( data . initial_val , data . final_val , data . delta_val ) ) {
return ;
}
2014-08-25 07:36:56 +02:00
2019-06-09 05:11:42 +02:00
// Add the interpolation
2018-08-15 17:26:10 +02:00
_push_interpolate_data ( data ) ;
2014-08-25 07:36:56 +02:00
}
2014-08-20 06:01:41 +02:00
Tween : : Tween ( ) {
2019-06-09 05:11:42 +02:00
// Initialize tween attributes
2017-03-05 16:44:50 +01:00
tween_process_mode = TWEEN_PROCESS_IDLE ;
repeat = false ;
speed_scale = 1 ;
pending_update = 0 ;
2018-08-15 17:26:10 +02:00
uid = 0 ;
2014-08-20 06:01:41 +02:00
}
Tween : : ~ Tween ( ) {
}