diff options
Diffstat (limited to 'scene/animation/animation_tree.cpp')
-rw-r--r-- | scene/animation/animation_tree.cpp | 149 |
1 files changed, 107 insertions, 42 deletions
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 2c2d8387f3..d4061ab167 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -34,7 +34,6 @@ #include "animation_blend_tree.h" #include "core/config/engine.h" #include "scene/animation/animation_player.h" -#include "scene/scene_string_names.h" void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const { Array parameters; @@ -46,6 +45,10 @@ void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const { r_list->push_back(PropertyInfo::from_dict(d)); } } + + r_list->push_back(PropertyInfo(Variant::FLOAT, current_length, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY)); + r_list->push_back(PropertyInfo(Variant::FLOAT, current_position, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY)); + r_list->push_back(PropertyInfo(Variant::FLOAT, current_delta, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY)); } Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const { @@ -56,8 +59,15 @@ Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter bool AnimationNode::is_parameter_read_only(const StringName &p_parameter) const { bool ret = false; - GDVIRTUAL_CALL(_is_parameter_read_only, p_parameter, ret); - return ret; + if (GDVIRTUAL_CALL(_is_parameter_read_only, p_parameter, ret) && ret) { + return true; + } + + if (p_parameter == current_length || p_parameter == current_position || p_parameter == current_delta) { + return true; + } + + return false; } void AnimationNode::set_parameter(const StringName &p_name, const Variant &p_value) { @@ -81,6 +91,20 @@ Variant AnimationNode::get_parameter(const StringName &p_name) const { return process_state->tree->property_map[path].first; } +void AnimationNode::set_node_time_info(const NodeTimeInfo &p_node_time_info) { + set_parameter(current_length, p_node_time_info.length); + set_parameter(current_position, p_node_time_info.position); + set_parameter(current_delta, p_node_time_info.delta); +} + +AnimationNode::NodeTimeInfo AnimationNode::get_node_time_info() const { + NodeTimeInfo nti; + nti.length = get_parameter(current_length); + nti.position = get_parameter(current_position); + nti.delta = get_parameter(current_delta); + return nti; +} + void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) { Dictionary cn; if (GDVIRTUAL_CALL(_get_child_nodes, cn)) { @@ -101,11 +125,11 @@ void AnimationNode::blend_animation(const StringName &p_animation, AnimationMixe process_state->tree->make_animation_instance(p_animation, p_playback_info); } -double AnimationNode::_pre_process(ProcessState *p_process_state, AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { +AnimationNode::NodeTimeInfo AnimationNode::_pre_process(ProcessState *p_process_state, AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { process_state = p_process_state; - double t = process(p_playback_info, p_test_only); + NodeTimeInfo nti = process(p_playback_info, p_test_only); process_state = nullptr; - return t; + return nti; } void AnimationNode::make_invalid(const String &p_reason) { @@ -122,11 +146,11 @@ AnimationTree *AnimationNode::get_animation_tree() const { return process_state->tree; } -double AnimationNode::blend_input(int p_input, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only) { - ERR_FAIL_INDEX_V(p_input, inputs.size(), 0); +AnimationNode::NodeTimeInfo AnimationNode::blend_input(int p_input, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only) { + ERR_FAIL_INDEX_V(p_input, inputs.size(), NodeTimeInfo()); AnimationNodeBlendTree *blend_tree = Object::cast_to<AnimationNodeBlendTree>(node_state.parent); - ERR_FAIL_NULL_V(blend_tree, 0); + ERR_FAIL_NULL_V(blend_tree, NodeTimeInfo()); // Update connections. StringName current_name = blend_tree->get_node_name(Ref<AnimationNode>(this)); @@ -136,32 +160,31 @@ double AnimationNode::blend_input(int p_input, AnimationMixer::PlaybackInfo p_pl StringName node_name = node_state.connections[p_input]; if (!blend_tree->has_node(node_name)) { make_invalid(vformat(RTR("Nothing connected to input '%s' of node '%s'."), get_input_name(p_input), current_name)); - return 0; + return NodeTimeInfo(); } Ref<AnimationNode> node = blend_tree->get_node(node_name); - ERR_FAIL_COND_V(node.is_null(), 0); + ERR_FAIL_COND_V(node.is_null(), NodeTimeInfo()); real_t activity = 0.0; Vector<AnimationTree::Activity> *activity_ptr = process_state->tree->input_activity_map.getptr(node_state.base_path); - double ret = _blend_node(node, node_name, nullptr, p_playback_info, p_filter, p_sync, p_test_only, &activity); + NodeTimeInfo nti = _blend_node(node, node_name, nullptr, p_playback_info, p_filter, p_sync, p_test_only, &activity); if (activity_ptr && p_input < activity_ptr->size()) { activity_ptr->write[p_input].last_pass = process_state->last_pass; activity_ptr->write[p_input].activity = activity; } - return ret; + return nti; } -double AnimationNode::blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only) { - ERR_FAIL_COND_V(p_node.is_null(), 0); - +AnimationNode::NodeTimeInfo AnimationNode::blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only) { + ERR_FAIL_COND_V(p_node.is_null(), NodeTimeInfo()); p_node->node_state.connections.clear(); return _blend_node(p_node, p_subpath, this, p_playback_info, p_filter, p_sync, p_test_only, nullptr); } -double AnimationNode::_blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationNode *p_new_parent, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only, real_t *r_activity) { - ERR_FAIL_NULL_V(process_state, 0); +AnimationNode::NodeTimeInfo AnimationNode::_blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationNode *p_new_parent, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only, real_t *r_activity) { + ERR_FAIL_NULL_V(process_state, NodeTimeInfo()); int blend_count = node_state.track_weights.size(); @@ -261,7 +284,7 @@ double AnimationNode::_blend_node(Ref<AnimationNode> p_node, const StringName &p new_parent = p_new_parent; new_path = String(node_state.base_path) + String(p_subpath) + "/"; } else { - ERR_FAIL_NULL_V(node_state.parent, 0); + ERR_FAIL_NULL_V(node_state.parent, NodeTimeInfo()); new_parent = node_state.parent; new_path = String(new_parent->node_state.base_path) + String(p_subpath) + "/"; } @@ -271,7 +294,7 @@ double AnimationNode::_blend_node(Ref<AnimationNode> p_node, const StringName &p p_node->node_state.base_path = new_path; p_node->node_state.parent = new_parent; if (!p_playback_info.seeked && !p_sync && !any_valid) { - p_playback_info.time = 0.0; + p_playback_info.delta = 0.0; return p_node->_pre_process(process_state, p_playback_info, p_test_only); } return p_node->_pre_process(process_state, p_playback_info, p_test_only); @@ -328,15 +351,31 @@ int AnimationNode::find_input(const String &p_name) const { return idx; } -double AnimationNode::process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { +AnimationNode::NodeTimeInfo AnimationNode::process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { process_state->is_testing = p_test_only; - return _process(p_playback_info, p_test_only); + + AnimationMixer::PlaybackInfo pi = p_playback_info; + if (p_playback_info.seeked) { + pi.delta = get_node_time_info().position - p_playback_info.time; + } else { + pi.time = get_node_time_info().position + p_playback_info.delta; + } + + NodeTimeInfo nti = _process(pi, p_test_only); + + if (!p_test_only) { + set_node_time_info(nti); + } + + return nti; } -double AnimationNode::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { - double ret = 0; - GDVIRTUAL_CALL(_process, p_playback_info.time, p_playback_info.seeked, p_playback_info.is_external_seeking, p_test_only, ret); - return ret; +AnimationNode::NodeTimeInfo AnimationNode::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { + double r_ret = 0.0; + GDVIRTUAL_CALL(_process, p_playback_info.time, p_playback_info.seeked, p_playback_info.is_external_seeking, p_test_only, r_ret); + NodeTimeInfo nti; + nti.delta = r_ret; + return nti; } void AnimationNode::set_filter_path(const NodePath &p_path, bool p_enable) { @@ -355,11 +394,11 @@ bool AnimationNode::is_filter_enabled() const { return filter_enabled; } -void AnimationNode::set_closable(bool p_closable) { +void AnimationNode::set_deletable(bool p_closable) { closable = p_closable; } -bool AnimationNode::is_closable() const { +bool AnimationNode::is_deletable() const { return closable; } @@ -432,7 +471,8 @@ double AnimationNode::blend_node_ex(const StringName &p_sub_path, Ref<AnimationN info.seeked = p_seek; info.is_external_seeking = p_is_external_seeking; info.weight = p_blend; - return blend_node(p_node, p_sub_path, info, p_filter, p_sync, p_test_only); + NodeTimeInfo nti = blend_node(p_node, p_sub_path, info, p_filter, p_sync, p_test_only); + return nti.length - nti.position; } double AnimationNode::blend_input_ex(int p_input, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter, bool p_sync, bool p_test_only) { @@ -441,9 +481,38 @@ double AnimationNode::blend_input_ex(int p_input, double p_time, bool p_seek, bo info.seeked = p_seek; info.is_external_seeking = p_is_external_seeking; info.weight = p_blend; - return blend_input(p_input, info, p_filter, p_sync, p_test_only); + NodeTimeInfo nti = blend_input(p_input, info, p_filter, p_sync, p_test_only); + return nti.length - nti.position; } +#ifdef TOOLS_ENABLED +void AnimationNode::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + const String pf = p_function; + if (p_idx == 0) { + if (pf == "find_input") { + for (const AnimationNode::Input &E : inputs) { + r_options->push_back(E.name.quote()); + } + } else if (pf == "get_parameter" || pf == "set_parameter") { + bool is_setter = pf == "set_parameter"; + List<PropertyInfo> parameters; + get_parameter_list(¶meters); + for (const PropertyInfo &E : parameters) { + if (is_setter && is_parameter_read_only(E.name)) { + continue; + } + r_options->push_back(E.name.quote()); + } + } else if (pf == "set_filter_path" || pf == "is_path_filtered") { + for (const KeyValue<NodePath, bool> &E : filter) { + r_options->push_back(String(E.key).quote()); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} +#endif + void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("add_input", "name"), &AnimationNode::add_input); ClassDB::bind_method(D_METHOD("remove_input", "index"), &AnimationNode::remove_input); @@ -557,7 +626,7 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const for (int i = 0; i < p_track_count; i++) { src_blendsw[i] = 1.0; // By default all go to 1 for the root input. } - root_animation_node->node_state.base_path = SceneStringNames::get_singleton()->parameters_base_path; + root_animation_node->node_state.base_path = SceneStringName(parameters_base_path); root_animation_node->node_state.parent = nullptr; } @@ -568,11 +637,12 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const if (started) { // If started, seek. pi.seeked = true; + pi.delta = p_delta; root_animation_node->_pre_process(&process_state, pi, false); started = false; } else { pi.seeked = false; - pi.time = p_delta; + pi.delta = p_delta; root_animation_node->_pre_process(&process_state, pi, false); } } @@ -717,7 +787,7 @@ void AnimationTree::_update_properties() { input_activity_map_get.clear(); if (root_animation_node.is_valid()) { - _update_properties_for_node(SceneStringNames::get_singleton()->parameters_base_path, root_animation_node); + _update_properties_for_node(SceneStringName(parameters_base_path), root_animation_node); } properties_dirty = false; @@ -739,15 +809,12 @@ void AnimationTree::_notification(int p_what) { void AnimationTree::set_animation_player(const NodePath &p_path) { animation_player = p_path; if (p_path.is_empty()) { - set_root_node(SceneStringNames::get_singleton()->path_pp); + set_root_node(SceneStringName(path_pp)); while (animation_libraries.size()) { remove_animation_library(animation_libraries[0].name); } } -#ifdef TOOLS_ENABLED emit_signal(SNAME("animation_player_changed")); // Needs to unpin AnimationPlayerEditor. - emit_signal(SNAME("mixer_updated")); -#endif // TOOLS_ENABLED _setup_animation_player(); notify_property_list_changed(); } @@ -786,10 +853,10 @@ void AnimationTree::_setup_animation_player() { } List<StringName> list; player->get_animation_library_list(&list); - for (int i = 0; i < list.size(); i++) { - Ref<AnimationLibrary> lib = player->get_animation_library(list[i]); + for (const StringName &E : list) { + Ref<AnimationLibrary> lib = player->get_animation_library(E); if (lib.is_valid()) { - add_animation_library(list[i], lib); + add_animation_library(E, lib); } } } @@ -893,9 +960,7 @@ void AnimationTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "advance_expression_base_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node"), "set_advance_expression_base_node", "get_advance_expression_base_node"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player"); -#ifdef TOOLS_ENABLED ADD_SIGNAL(MethodInfo(SNAME("animation_player_changed"))); -#endif // TOOLS_ENABLED } AnimationTree::AnimationTree() { |