2018-08-30 04:38:13 +08:00
/**************************************************************************/
/* animation_tree.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
2022-07-24 05:41:51 +08:00
# ifndef ANIMATION_TREE_H
# define ANIMATION_TREE_H
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
# include "animation_mixer.h"
2018-06-19 09:10:48 +08:00
# include "scene/resources/animation.h"
2023-07-20 23:34:06 +08:00
# define HUGE_LENGTH 31540000 // 31540000 seconds mean 1 year... is it too long? It must be longer than any Animation length and Transition xfade time to prevent time inversion for AnimationNodeStateMachine.
2023-02-18 10:02:28 +08:00
2018-06-19 09:10:48 +08:00
class AnimationNodeBlendTree ;
2018-12-16 22:43:20 +08:00
class AnimationNodeStartState ;
class AnimationNodeEndState ;
2018-06-26 05:40:24 +08:00
class AnimationTree ;
2018-06-19 09:10:48 +08:00
class AnimationNode : public Resource {
2019-03-20 02:35:57 +08:00
GDCLASS ( AnimationNode , Resource ) ;
2018-06-19 09:10:48 +08:00
public :
2023-07-20 23:34:06 +08:00
friend class AnimationTree ;
2018-06-19 09:10:48 +08:00
enum FilterAction {
FILTER_IGNORE ,
FILTER_PASS ,
FILTER_STOP ,
FILTER_BLEND
} ;
struct Input {
String name ;
} ;
2023-07-20 23:34:06 +08:00
bool closable = false ;
2018-06-19 09:10:48 +08:00
Vector < Input > inputs ;
2024-05-29 22:08:54 +08:00
AHashMap < NodePath , bool > filter ;
2023-07-20 23:34:06 +08:00
bool filter_enabled = false ;
2018-06-19 09:10:48 +08:00
2024-01-08 05:08:10 +08:00
// To propagate information from upstream for use in estimation of playback progress.
// These values must be taken from the result of blend_node() or blend_input() and must be essentially read-only.
// For example, if you want to change the position, you need to change the pi.time value of PlaybackInfo passed to blend_input(pi) and get the result.
struct NodeTimeInfo {
// Retain the previous frame values. These are stored into the AnimationTree's Map and exposing them as read-only values.
double length = 0.0 ;
double position = 0.0 ;
double delta = 0.0 ;
// Needs internally to estimate remain time, the previous frame values are not retained.
Animation : : LoopMode loop_mode = Animation : : LOOP_NONE ;
2024-07-28 13:48:38 +08:00
bool will_end = false ; // For breaking loop, it is true when just looped.
2024-01-08 05:08:10 +08:00
bool is_infinity = false ; // For unpredictable state machine's end.
bool is_looping ( ) {
return loop_mode ! = Animation : : LOOP_NONE ;
}
double get_remain ( bool p_break_loop = false ) {
if ( ( is_looping ( ) & & ! p_break_loop ) | | is_infinity ) {
return HUGE_LENGTH ;
}
2024-07-28 13:48:38 +08:00
if ( is_looping ( ) & & p_break_loop & & will_end ) {
2024-01-08 05:08:10 +08:00
return 0 ;
}
2024-07-24 00:00:42 +08:00
double remain = length - position ;
if ( Math : : is_zero_approx ( remain ) ) {
return 0 ;
}
2024-07-15 07:44:20 +08:00
return remain ;
2024-01-08 05:08:10 +08:00
}
} ;
2023-07-20 23:34:06 +08:00
// Temporary state for blending process which needs to be stored in each AnimationNodes.
struct NodeState {
2024-05-29 22:08:54 +08:00
friend AnimationNode ;
private :
2023-07-20 23:34:06 +08:00
StringName base_path ;
2024-05-29 22:08:54 +08:00
public :
2023-07-20 23:34:06 +08:00
AnimationNode * parent = nullptr ;
Vector < StringName > connections ;
Vector < real_t > track_weights ;
2024-05-29 22:08:54 +08:00
const StringName get_base_path ( ) const {
return base_path ;
}
2023-07-20 23:34:06 +08:00
} node_state ;
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
// Temporary state for blending process which needs to be started in the AnimationTree, pass through the AnimationNodes, and then return to the AnimationTree.
struct ProcessState {
2021-02-08 05:29:31 +08:00
AnimationTree * tree = nullptr ;
2024-05-29 22:08:54 +08:00
const AHashMap < NodePath , int > * track_map ; // TODO: Is there a better way to manage filter/tracks?
2023-07-20 23:34:06 +08:00
bool is_testing = false ;
bool valid = false ;
2018-06-19 09:10:48 +08:00
String invalid_reasons ;
2021-02-08 05:29:31 +08:00
uint64_t last_pass = 0 ;
2023-07-20 23:34:06 +08:00
} * process_state = nullptr ;
2023-08-10 00:31:15 +08:00
2024-05-29 22:08:54 +08:00
private :
mutable AHashMap < StringName , int > property_cache ;
public :
void set_node_state_base_path ( const StringName p_base_path ) {
if ( p_base_path ! = node_state . base_path ) {
node_state . base_path = p_base_path ;
make_cache_dirty ( ) ;
}
}
void set_node_state_base_path ( const String p_base_path ) {
if ( p_base_path ! = node_state . base_path ) {
node_state . base_path = p_base_path ;
make_cache_dirty ( ) ;
}
}
const StringName get_node_state_base_path ( ) const {
return node_state . get_base_path ( ) ;
}
void make_cache_dirty ( ) {
property_cache . clear ( ) ;
}
2018-06-19 09:10:48 +08:00
Array _get_filters ( ) const ;
void _set_filters ( const Array & p_filters ) ;
2018-08-21 00:38:18 +08:00
friend class AnimationNodeBlendTree ;
2024-01-08 05:08:10 +08:00
// The time information is passed from upstream to downstream by AnimationMixer::PlaybackInfo::p_playback_info until AnimationNodeAnimation processes it.
// Conversely, AnimationNodeAnimation returns the processed result as NodeTimeInfo from downstream to upstream.
NodeTimeInfo _blend_node ( Ref < AnimationNode > p_node , const StringName & p_subpath , AnimationNode * p_new_parent , AnimationMixer : : PlaybackInfo p_playback_info , FilterAction p_filter = FILTER_IGNORE , bool p_sync = true , bool p_test_only = false , real_t * r_activity = nullptr ) ;
NodeTimeInfo _pre_process ( ProcessState * p_process_state , AnimationMixer : : PlaybackInfo p_playback_info , bool p_test_only = false ) ;
2018-06-19 09:10:48 +08:00
protected :
2024-01-08 05:08:10 +08:00
StringName current_length = " current_length " ;
StringName current_position = " current_position " ;
StringName current_delta = " current_delta " ;
virtual NodeTimeInfo process ( const AnimationMixer : : PlaybackInfo p_playback_info , bool p_test_only = false ) ; // To organize time information. Virtualizing for especially AnimationNodeAnimation needs to take "backward" into account.
virtual NodeTimeInfo _process ( const AnimationMixer : : PlaybackInfo p_playback_info , bool p_test_only = false ) ; // Main process.
2023-07-20 23:34:06 +08:00
void blend_animation ( const StringName & p_animation , AnimationMixer : : PlaybackInfo p_playback_info ) ;
2024-01-08 05:08:10 +08:00
NodeTimeInfo blend_node ( Ref < AnimationNode > p_node , const StringName & p_subpath , AnimationMixer : : PlaybackInfo p_playback_info , FilterAction p_filter = FILTER_IGNORE , bool p_sync = true , bool p_test_only = false ) ;
NodeTimeInfo blend_input ( int p_input , AnimationMixer : : PlaybackInfo p_playback_info , FilterAction p_filter = FILTER_IGNORE , bool p_sync = true , bool p_test_only = false ) ;
2023-02-18 10:02:28 +08:00
2023-07-20 23:34:06 +08:00
// Bind-able methods to expose for compatibility, moreover AnimationMixer::PlaybackInfo is not exposed.
void blend_animation_ex ( const StringName & p_animation , double p_time , double p_delta , bool p_seeked , bool p_is_external_seeking , real_t p_blend , Animation : : LoopedFlag p_looped_flag = Animation : : LOOPED_FLAG_NONE ) ;
double blend_node_ex ( const StringName & p_sub_path , Ref < AnimationNode > p_node , double p_time , bool p_seek , bool p_is_external_seeking , real_t p_blend , FilterAction p_filter = FILTER_IGNORE , bool p_sync = true , bool p_test_only = false ) ;
double blend_input_ex ( int p_input , double p_time , bool p_seek , bool p_is_external_seeking , real_t p_blend , FilterAction p_filter = FILTER_IGNORE , bool p_sync = true , bool p_test_only = false ) ;
2021-10-15 21:25:00 +08:00
2018-06-19 09:10:48 +08:00
void make_invalid ( const String & p_reason ) ;
2022-04-20 18:36:54 +08:00
AnimationTree * get_animation_tree ( ) const ;
2018-06-19 09:10:48 +08:00
static void _bind_methods ( ) ;
2022-08-13 04:57:11 +08:00
void _validate_property ( PropertyInfo & p_property ) const ;
2018-06-19 09:10:48 +08:00
2021-08-22 09:52:44 +08:00
GDVIRTUAL0RC ( Dictionary , _get_child_nodes )
GDVIRTUAL0RC ( Array , _get_parameter_list )
GDVIRTUAL1RC ( Ref < AnimationNode > , _get_child_by_name , StringName )
GDVIRTUAL1RC ( Variant , _get_parameter_default_value , StringName )
2023-01-12 20:51:03 +08:00
GDVIRTUAL1RC ( bool , _is_parameter_read_only , StringName )
2024-10-26 23:56:51 +08:00
GDVIRTUAL4R ( double , _process , double , bool , bool , bool )
2021-08-22 09:52:44 +08:00
GDVIRTUAL0RC ( String , _get_caption )
GDVIRTUAL0RC ( bool , _has_filter )
2018-06-19 09:10:48 +08:00
public :
2018-08-21 00:38:18 +08:00
virtual void get_parameter_list ( List < PropertyInfo > * r_list ) const ;
virtual Variant get_parameter_default_value ( const StringName & p_parameter ) const ;
2023-01-12 20:51:03 +08:00
virtual bool is_parameter_read_only ( const StringName & p_parameter ) const ;
2018-08-21 00:38:18 +08:00
void set_parameter ( const StringName & p_name , const Variant & p_value ) ;
Variant get_parameter ( const StringName & p_name ) const ;
2024-01-08 05:08:10 +08:00
void set_node_time_info ( const NodeTimeInfo & p_node_time_info ) ; // Wrapper of set_parameter().
virtual NodeTimeInfo get_node_time_info ( ) const ; // Wrapper of get_parameter().
2018-08-21 00:38:18 +08:00
struct ChildNode {
StringName name ;
Ref < AnimationNode > node ;
} ;
virtual void get_child_nodes ( List < ChildNode > * r_child_nodes ) ;
2018-06-19 09:10:48 +08:00
2018-06-22 02:45:44 +08:00
virtual String get_caption ( ) const ;
2018-06-19 09:10:48 +08:00
2023-01-29 22:54:13 +08:00
virtual bool add_input ( const String & p_name ) ;
virtual void remove_input ( int p_index ) ;
virtual bool set_input_name ( int p_input , const String & p_name ) ;
virtual String get_input_name ( int p_input ) const ;
2018-06-19 09:10:48 +08:00
int get_input_count ( ) const ;
2023-01-29 22:54:13 +08:00
int find_input ( const String & p_name ) const ;
2018-06-19 09:10:48 +08:00
void set_filter_path ( const NodePath & p_path , bool p_enable ) ;
bool is_path_filtered ( const NodePath & p_path ) const ;
void set_filter_enabled ( bool p_enable ) ;
bool is_filter_enabled ( ) const ;
2024-02-07 09:37:26 +08:00
void set_deletable ( bool p_closable ) ;
bool is_deletable ( ) const ;
2023-08-10 00:31:15 +08:00
2018-06-19 09:10:48 +08:00
virtual bool has_filter ( ) const ;
2024-01-07 00:23:25 +08:00
# ifdef TOOLS_ENABLED
virtual void get_argument_options ( const StringName & p_function , int p_idx , List < String > * r_options ) const override ;
# endif
2023-02-18 10:02:28 +08:00
virtual Ref < AnimationNode > get_child_by_name ( const StringName & p_name ) const ;
Ref < AnimationNode > find_node_by_path ( const String & p_name ) const ;
2018-06-19 09:10:48 +08:00
AnimationNode ( ) ;
} ;
VARIANT_ENUM_CAST ( AnimationNode : : FilterAction )
2023-07-20 23:34:06 +08:00
// Root node does not allow inputs.
2018-06-22 02:45:44 +08:00
class AnimationRootNode : public AnimationNode {
2019-03-20 02:35:57 +08:00
GDCLASS ( AnimationRootNode , AnimationNode ) ;
2023-02-04 23:29:34 +08:00
protected :
virtual void _tree_changed ( ) ;
virtual void _animation_node_renamed ( const ObjectID & p_oid , const String & p_old_name , const String & p_new_name ) ;
virtual void _animation_node_removed ( const ObjectID & p_oid , const StringName & p_node ) ;
2018-06-22 02:45:44 +08:00
public :
AnimationRootNode ( ) { }
} ;
2018-12-16 22:43:20 +08:00
class AnimationNodeStartState : public AnimationRootNode {
GDCLASS ( AnimationNodeStartState , AnimationRootNode ) ;
} ;
class AnimationNodeEndState : public AnimationRootNode {
GDCLASS ( AnimationNodeEndState , AnimationRootNode ) ;
} ;
2023-07-20 23:34:06 +08:00
class AnimationTree : public AnimationMixer {
GDCLASS ( AnimationTree , AnimationMixer ) ;
2023-05-17 23:22:26 +08:00
2023-07-20 23:34:06 +08:00
# ifndef DISABLE_DEPRECATED
2018-06-19 09:10:48 +08:00
public :
2021-02-19 02:52:29 +08:00
enum AnimationProcessCallback {
2018-06-19 09:10:48 +08:00
ANIMATION_PROCESS_PHYSICS ,
ANIMATION_PROCESS_IDLE ,
2018-08-02 15:22:24 +08:00
ANIMATION_PROCESS_MANUAL ,
2018-06-19 09:10:48 +08:00
} ;
2023-07-20 23:34:06 +08:00
# endif // DISABLE_DEPRECATED
2018-06-19 09:10:48 +08:00
private :
2023-07-20 23:34:06 +08:00
Ref < AnimationRootNode > root_animation_node ;
2022-04-20 18:36:54 +08:00
NodePath advance_expression_base_node = NodePath ( String ( " . " ) ) ;
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
AnimationNode : : ProcessState process_state ;
2021-02-08 05:29:31 +08:00
uint64_t process_pass = 1 ;
2018-06-19 09:10:48 +08:00
2021-02-08 05:29:31 +08:00
bool started = true ;
2018-06-19 09:10:48 +08:00
2018-08-21 00:38:18 +08:00
friend class AnimationNode ;
2023-07-20 23:34:06 +08:00
2018-08-21 00:38:18 +08:00
List < PropertyInfo > properties ;
2024-05-29 22:08:54 +08:00
AHashMap < StringName , AHashMap < StringName , StringName > > property_parent_map ;
AHashMap < ObjectID , StringName > property_reference_map ;
AHashMap < StringName , Pair < Variant , bool > > property_map ; // Property value and read-only flag.
2018-08-21 00:38:18 +08:00
2023-07-20 23:34:06 +08:00
bool properties_dirty = true ;
void _update_properties ( ) ;
void _update_properties_for_node ( const String & p_base_path , Ref < AnimationNode > p_node ) ;
void _tree_changed ( ) ;
void _animation_node_renamed ( const ObjectID & p_oid , const String & p_old_name , const String & p_new_name ) ;
void _animation_node_removed ( const ObjectID & p_oid , const StringName & p_node ) ;
2018-08-24 03:44:10 +08:00
struct Activity {
2021-02-08 05:29:31 +08:00
uint64_t last_pass = 0 ;
2021-08-10 06:15:17 +08:00
real_t activity = 0.0 ;
2018-08-24 03:44:10 +08:00
} ;
2020-03-17 14:33:00 +08:00
HashMap < StringName , Vector < Activity > > input_activity_map ;
2018-08-24 03:44:10 +08:00
HashMap < StringName , Vector < Activity > * > input_activity_map_get ;
2023-07-20 23:34:06 +08:00
NodePath animation_player ;
2018-08-21 00:38:18 +08:00
2023-07-20 23:34:06 +08:00
void _setup_animation_player ( ) ;
void _animation_player_changed ( ) ;
2018-08-24 22:41:04 +08:00
2018-08-21 00:38:18 +08:00
bool _set ( const StringName & p_name , const Variant & p_value ) ;
bool _get ( const StringName & p_name , Variant & r_ret ) const ;
void _get_property_list ( List < PropertyInfo > * p_list ) const ;
2023-07-20 23:34:06 +08:00
virtual void _validate_property ( PropertyInfo & p_property ) const override ;
2018-06-19 09:10:48 +08:00
void _notification ( int p_what ) ;
2023-07-20 23:34:06 +08:00
2018-06-19 09:10:48 +08:00
static void _bind_methods ( ) ;
2023-07-20 23:34:06 +08:00
virtual void _set_active ( bool p_active ) override ;
2022-07-26 17:48:08 +08:00
2023-07-20 23:34:06 +08:00
// Make animation instances.
2024-05-29 22:08:54 +08:00
virtual bool _blend_pre_process ( double p_delta , int p_track_count , const AHashMap < NodePath , int > & p_track_map ) override ;
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
# ifndef DISABLE_DEPRECATED
void _set_process_callback_bind_compat_80813 ( AnimationProcessCallback p_mode ) ;
AnimationProcessCallback _get_process_callback_bind_compat_80813 ( ) const ;
void _set_tree_root_bind_compat_80813 ( const Ref < AnimationNode > & p_root ) ;
Ref < AnimationNode > _get_tree_root_bind_compat_80813 ( ) const ;
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
static void _bind_compatibility_methods ( ) ;
# endif // DISABLE_DEPRECATED
2018-06-19 09:10:48 +08:00
2023-07-20 23:34:06 +08:00
public :
void set_animation_player ( const NodePath & p_path ) ;
2018-06-19 09:10:48 +08:00
NodePath get_animation_player ( ) const ;
2023-07-20 23:34:06 +08:00
void set_root_animation_node ( const Ref < AnimationRootNode > & p_animation_node ) ;
Ref < AnimationRootNode > get_root_animation_node ( ) const ;
2022-04-20 18:36:54 +08:00
2023-07-20 23:34:06 +08:00
void set_advance_expression_base_node ( const NodePath & p_path ) ;
NodePath get_advance_expression_base_node ( ) const ;
2023-01-28 02:25:49 +08:00
2024-02-18 02:03:21 +08:00
PackedStringArray get_configuration_warnings ( ) const override ;
2018-06-19 09:10:48 +08:00
bool is_state_invalid ( ) const ;
String get_invalid_state_reason ( ) const ;
2021-08-10 06:15:17 +08:00
real_t get_connection_activity ( const StringName & p_path , int p_connection ) const ;
2018-08-02 15:22:24 +08:00
2018-06-19 09:10:48 +08:00
uint64_t get_last_process_pass ( ) const ;
2023-07-20 23:34:06 +08:00
2018-06-26 05:40:24 +08:00
AnimationTree ( ) ;
~ AnimationTree ( ) ;
2018-06-19 09:10:48 +08:00
} ;
2023-07-20 23:34:06 +08:00
# ifndef DISABLE_DEPRECATED
VARIANT_ENUM_CAST ( AnimationTree : : AnimationProcessCallback ) ;
# endif // DISABLE_DEPRECATED
2018-06-19 09:10:48 +08:00
2022-07-24 05:41:51 +08:00
# endif // ANIMATION_TREE_H