summaryrefslogtreecommitdiffstats
path: root/scene/animation/animation_tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/animation/animation_tree.cpp')
-rw-r--r--scene/animation/animation_tree.cpp149
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(&parameters);
+ 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() {