diff options
Diffstat (limited to 'scene/animation/animation_blend_tree.cpp')
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 520 |
1 files changed, 285 insertions, 235 deletions
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 65904410d3..10bab3ce38 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -3,6 +3,7 @@ void AnimationNodeAnimation::set_animation(const StringName &p_name) { animation = p_name; + _change_notify("animation"); } StringName AnimationNodeAnimation::get_animation() const { @@ -13,43 +14,36 @@ float AnimationNodeAnimation::get_playback_time() const { return time; } +Vector<String> (*AnimationNodeAnimation::get_editable_animation_list)() = NULL; + void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const { - if (property.name == "animation") { - AnimationTree *gp = get_tree(); - if (gp && gp->has_node(gp->get_animation_player())) { - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player())); - if (ap) { - List<StringName> names; - ap->get_animation_list(&names); - String anims; - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - if (E != names.front()) { - anims += ","; - } - anims += String(E->get()); - } - if (anims != String()) { - property.hint = PROPERTY_HINT_ENUM; - property.hint_string = anims; - } + if (property.name == "animation" && get_editable_animation_list) { + Vector<String> names = get_editable_animation_list(); + String anims; + for (int i = 0; i < names.size(); i++) { + + if (i > 0) { + anims += ","; } + anims += String(names[i]); + } + if (anims != String()) { + property.hint = PROPERTY_HINT_ENUM; + property.hint_string = anims; } } - - AnimationRootNode::_validate_property(property); } float AnimationNodeAnimation::process(float p_time, bool p_seek) { - AnimationPlayer *ap = get_player(); + AnimationPlayer *ap = state->player; ERR_FAIL_COND_V(!ap, 0); - Ref<Animation> anim = ap->get_animation(animation); - if (!anim.is_valid()) { + if (!ap->has_animation(animation)) { - Ref<AnimationNodeBlendTree> tree = get_parent(); - if (tree.is_valid()) { + AnimationNodeBlendTree *tree = Object::cast_to<AnimationNodeBlendTree>(parent); + if (tree) { String name = tree->get_node_name(Ref<AnimationNodeAnimation>(this)); make_invalid(vformat(RTR("On BlendTree node '%s', animation not found: '%s'"), name, animation)); @@ -60,6 +54,8 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) { return 0; } + Ref<Animation> anim = ap->get_animation(animation); + if (p_seek) { time = p_time; step = 0; @@ -108,6 +104,20 @@ AnimationNodeAnimation::AnimationNodeAnimation() { //////////////////////////////////////////////////////// +void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::BOOL, active)); + r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::REAL, remaining, PROPERTY_HINT_NONE, "", 0)); +} +Variant AnimationNodeOneShot::get_parameter_default_value(const StringName &p_parameter) const { + if (p_parameter == active || p_parameter == prev_active) { + return false; + } else { + return 0.0; + } +} + void AnimationNodeOneShot::set_fadein_time(float p_time) { fade_in = p_time; @@ -162,18 +172,6 @@ AnimationNodeOneShot::MixMode AnimationNodeOneShot::get_mix_mode() const { return mix; } -void AnimationNodeOneShot::start() { - active = true; - do_start = true; -} -void AnimationNodeOneShot::stop() { - active = false; -} -bool AnimationNodeOneShot::is_active() const { - - return active; -} - String AnimationNodeOneShot::get_caption() const { return "OneShot"; } @@ -184,8 +182,16 @@ bool AnimationNodeOneShot::has_filter() const { float AnimationNodeOneShot::process(float p_time, bool p_seek) { + bool active = get_parameter(this->active); + bool prev_active = get_parameter(this->prev_active); + float time = get_parameter(this->time); + float remaining = get_parameter(this->remaining); + if (!active) { //make it as if this node doesn't exist, pass input 0 by. + if (prev_active) { + set_parameter(this->prev_active, false); + } return blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); } @@ -193,9 +199,12 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) { if (p_seek) time = p_time; + bool do_start = !prev_active; + if (do_start) { time = 0; os_seek = true; + set_parameter(this->prev_active, true); } float blend; @@ -233,10 +242,15 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) { if (!p_seek) { time += p_time; remaining = os_rem; - if (remaining <= 0) - active = false; + if (remaining <= 0) { + set_parameter(this->active, false); + set_parameter(this->prev_active, false); + } } + set_parameter(this->time, time); + set_parameter(this->remaining, remaining); + return MAX(main_rem, remaining); } void AnimationNodeOneShot::set_use_sync(bool p_sync) { @@ -269,10 +283,6 @@ void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mix_mode", "mode"), &AnimationNodeOneShot::set_mix_mode); ClassDB::bind_method(D_METHOD("get_mix_mode"), &AnimationNodeOneShot::get_mix_mode); - ClassDB::bind_method(D_METHOD("start"), &AnimationNodeOneShot::start); - ClassDB::bind_method(D_METHOD("stop"), &AnimationNodeOneShot::stop); - ClassDB::bind_method(D_METHOD("is_active"), &AnimationNodeOneShot::is_active); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync); @@ -297,26 +307,27 @@ AnimationNodeOneShot::AnimationNodeOneShot() { add_input("in"); add_input("shot"); - time = 0; fade_in = 0.1; fade_out = 0.1; autorestart = false; autorestart_delay = 1; - autorestart_remaining = 0; + mix = MIX_MODE_BLEND; - active = false; - do_start = false; sync = false; + + active = "active"; + prev_active = "prev_active"; + time = "time"; + remaining = "remaining"; } //////////////////////////////////////////////// -void AnimationNodeAdd2::set_amount(float p_amount) { - amount = p_amount; +void AnimationNodeAdd2::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, add_amount, PROPERTY_HINT_RANGE, "0,1,0.01")); } - -float AnimationNodeAdd2::get_amount() const { - return amount; +Variant AnimationNodeAdd2::get_parameter_default_value(const StringName &p_parameter) const { + return 0; } String AnimationNodeAdd2::get_caption() const { @@ -339,6 +350,7 @@ bool AnimationNodeAdd2::has_filter() const { float AnimationNodeAdd2::process(float p_time, bool p_seek) { + float amount = get_parameter(add_amount); float rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync); @@ -347,32 +359,27 @@ float AnimationNodeAdd2::process(float p_time, bool p_seek) { void AnimationNodeAdd2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeAdd2::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeAdd2::get_amount); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd2::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd2::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd2::AnimationNodeAdd2() { + add_amount = "add_amount"; add_input("in"); add_input("add"); - amount = 0; sync = false; } //////////////////////////////////////////////// -void AnimationNodeAdd3::set_amount(float p_amount) { - amount = p_amount; +void AnimationNodeAdd3::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, add_amount, PROPERTY_HINT_RANGE, "-1,1,0.01")); } - -float AnimationNodeAdd3::get_amount() const { - return amount; +Variant AnimationNodeAdd3::get_parameter_default_value(const StringName &p_parameter) const { + return 0; } String AnimationNodeAdd3::get_caption() const { @@ -395,6 +402,7 @@ bool AnimationNodeAdd3::has_filter() const { float AnimationNodeAdd3::process(float p_time, bool p_seek) { + float amount = get_parameter(add_amount); blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_PASS, !sync); float rem0 = blend_input(1, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_PASS, !sync); @@ -404,39 +412,37 @@ float AnimationNodeAdd3::process(float p_time, bool p_seek) { void AnimationNodeAdd3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeAdd3::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeAdd3::get_amount); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd3::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd3::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd3::AnimationNodeAdd3() { + add_amount = "add_amount"; add_input("-add"); add_input("in"); add_input("+add"); - amount = 0; sync = false; } ///////////////////////////////////////////// -void AnimationNodeBlend2::set_amount(float p_amount) { - amount = p_amount; +void AnimationNodeBlend2::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, blend_amount, PROPERTY_HINT_RANGE, "0,1,0.01")); } - -float AnimationNodeBlend2::get_amount() const { - return amount; +Variant AnimationNodeBlend2::get_parameter_default_value(const StringName &p_parameter) const { + return 0; //for blend amount } + String AnimationNodeBlend2::get_caption() const { return "Blend2"; } float AnimationNodeBlend2::process(float p_time, bool p_seek) { + float amount = get_parameter(blend_amount); + float rem0 = blend_input(0, p_time, p_seek, 1.0 - amount, FILTER_BLEND, !sync); float rem1 = blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync); @@ -459,31 +465,25 @@ bool AnimationNodeBlend2::has_filter() const { } void AnimationNodeBlend2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeBlend2::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeBlend2::get_amount); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend2::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend2::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend2::AnimationNodeBlend2() { + blend_amount = "blend_amount"; add_input("in"); add_input("blend"); sync = false; - - amount = 0; } ////////////////////////////////////// -void AnimationNodeBlend3::set_amount(float p_amount) { - amount = p_amount; +void AnimationNodeBlend3::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, blend_amount, PROPERTY_HINT_RANGE, "-1,1,0.01")); } - -float AnimationNodeBlend3::get_amount() const { - return amount; +Variant AnimationNodeBlend3::get_parameter_default_value(const StringName &p_parameter) const { + return 0; //for blend amount } String AnimationNodeBlend3::get_caption() const { @@ -502,6 +502,7 @@ bool AnimationNodeBlend3::is_using_sync() const { float AnimationNodeBlend3::process(float p_time, bool p_seek) { + float amount = get_parameter(blend_amount); float rem0 = blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_IGNORE, !sync); float rem1 = blend_input(1, p_time, p_seek, 1.0 - ABS(amount), FILTER_IGNORE, !sync); float rem2 = blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_IGNORE, !sync); @@ -511,31 +512,26 @@ float AnimationNodeBlend3::process(float p_time, bool p_seek) { void AnimationNodeBlend3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeBlend3::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeBlend3::get_amount); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend3::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend3::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend3::AnimationNodeBlend3() { + blend_amount = "blend_amount"; add_input("-blend"); add_input("in"); add_input("+blend"); sync = false; - amount = 0; } ///////////////////////////////// -void AnimationNodeTimeScale::set_scale(float p_scale) { - scale = p_scale; +void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, scale, PROPERTY_HINT_RANGE, "0,32,0.01,or_greater")); } - -float AnimationNodeTimeScale::get_scale() const { - return scale; +Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const { + return 1.0; //initial timescale } String AnimationNodeTimeScale::get_caption() const { @@ -544,6 +540,7 @@ String AnimationNodeTimeScale::get_caption() const { float AnimationNodeTimeScale::process(float p_time, bool p_seek) { + float scale = get_parameter(this->scale); if (p_seek) { return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false); } else { @@ -552,25 +549,19 @@ float AnimationNodeTimeScale::process(float p_time, bool p_seek) { } void AnimationNodeTimeScale::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_scale", "scale"), &AnimationNodeTimeScale::set_scale); - ClassDB::bind_method(D_METHOD("get_scale"), &AnimationNodeTimeScale::get_scale); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,32,0.01,or_greater"), "set_scale", "get_scale"); } AnimationNodeTimeScale::AnimationNodeTimeScale() { + scale = "scale"; add_input("in"); - scale = 1.0; } //////////////////////////////////// -void AnimationNodeTimeSeek::set_seek_pos(float p_seek_pos) { - seek_pos = p_seek_pos; +void AnimationNodeTimeSeek::get_parameter_list(List<PropertyInfo> *r_list) const { + r_list->push_back(PropertyInfo(Variant::REAL, seek_pos, PROPERTY_HINT_RANGE, "-1,3600,0.01,or_greater")); } - -float AnimationNodeTimeSeek::get_seek_pos() const { - return seek_pos; +Variant AnimationNodeTimeSeek::get_parameter_default_value(const StringName &p_parameter) const { + return 1.0; //initial timescale } String AnimationNodeTimeSeek::get_caption() const { @@ -579,11 +570,12 @@ String AnimationNodeTimeSeek::get_caption() const { float AnimationNodeTimeSeek::process(float p_time, bool p_seek) { + float seek_pos = get_parameter(this->seek_pos); if (p_seek) { return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false); } else if (seek_pos >= 0) { float ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false); - seek_pos = -1; + set_parameter(this->seek_pos, -1.0); //reset _change_notify("seek_pos"); return ret; } else { @@ -592,19 +584,41 @@ float AnimationNodeTimeSeek::process(float p_time, bool p_seek) { } void AnimationNodeTimeSeek::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_seek_pos", "seek_pos"), &AnimationNodeTimeSeek::set_seek_pos); - ClassDB::bind_method(D_METHOD("get_seek_pos"), &AnimationNodeTimeSeek::get_seek_pos); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "seek_pos", PROPERTY_HINT_RANGE, "-1,3600,0.01,or_greater"), "set_seek_pos", "get_seek_pos"); } + AnimationNodeTimeSeek::AnimationNodeTimeSeek() { add_input("in"); - seek_pos = -1; + seek_pos = "seek_position"; } ///////////////////////////////////////////////// +void AnimationNodeTransition::get_parameter_list(List<PropertyInfo> *r_list) const { + + String anims; + for (int i = 0; i < enabled_inputs; i++) { + if (i > 0) { + anims += ","; + } + anims += inputs[i].name; + } + + r_list->push_back(PropertyInfo(Variant::INT, current, PROPERTY_HINT_ENUM, anims)); + r_list->push_back(PropertyInfo(Variant::INT, prev_current, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::INT, prev, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::REAL, prev_xfading, PROPERTY_HINT_NONE, "", 0)); +} +Variant AnimationNodeTransition::get_parameter_default_value(const StringName &p_parameter) const { + if (p_parameter == time || p_parameter == prev_xfading) { + return 0.0; + } else if (p_parameter == prev || p_parameter == prev_current) { + return -1; + } else { + return 0; + } +} + String AnimationNodeTransition::get_caption() const { return "Transition"; } @@ -650,18 +664,12 @@ String AnimationNodeTransition::get_input_caption(int p_input) const { return inputs[p_input].name; } -void AnimationNodeTransition::set_current(int p_current) { - - if (current == p_current) - return; - ERR_FAIL_INDEX(p_current, enabled_inputs); - +#if 0 Ref<AnimationNodeBlendTree> tree = get_parent(); if (tree.is_valid() && current >= 0) { prev = current; - prev_xfading = xfade; - prev_time = time; + prev_xfading = xfade; time = 0; current = p_current; switched = true; @@ -669,11 +677,8 @@ void AnimationNodeTransition::set_current(int p_current) { } else { current = p_current; } -} +#endif -int AnimationNodeTransition::get_current() const { - return current; -} void AnimationNodeTransition::set_cross_fade_time(float p_fade) { xfade = p_fade; } @@ -684,9 +689,34 @@ float AnimationNodeTransition::get_cross_fade_time() const { float AnimationNodeTransition::process(float p_time, bool p_seek) { + int current = get_parameter(this->current); + int prev = get_parameter(this->prev); + int prev_current = get_parameter(this->prev_current); + + float time = get_parameter(this->time); + float prev_xfading = get_parameter(this->prev_xfading); + + bool switched = current != prev_current; + + if (switched) { + set_parameter(this->prev_current, current); + set_parameter(this->prev, prev_current); + + prev = prev_current; + prev_xfading = xfade; + time = 0; + switched = true; + } + + if (current < 0 || current >= enabled_inputs || prev >= enabled_inputs) { + return 0; + } + + float rem = 0; + if (prev < 0) { // process current animation, check for transition - float rem = blend_input(current, p_time, p_seek, 1.0, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, 1.0, FILTER_IGNORE, false); if (p_seek) time = p_time; @@ -695,16 +725,13 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) { if (inputs[current].auto_advance && rem <= xfade) { - set_current((current + 1) % enabled_inputs); + set_parameter(this->current, (current + 1) % enabled_inputs); } - return rem; } else { // cross-fading from prev to current float blend = xfade ? (prev_xfading / xfade) : 1; - float rem; - if (!p_seek && switched) { //just switched, seek to start of current rem = blend_input(current, 0, true, 1.0 - blend, FILTER_IGNORE, false); @@ -723,28 +750,19 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) { time += p_time; prev_xfading -= p_time; if (prev_xfading < 0) { - prev = -1; + set_parameter(this->prev, -1); } } - - return rem; } + + set_parameter(this->time, time); + set_parameter(this->prev_xfading, prev_xfading); + + return rem; } void AnimationNodeTransition::_validate_property(PropertyInfo &property) const { - if (property.name == "current" && enabled_inputs > 0) { - property.hint = PROPERTY_HINT_ENUM; - String anims; - for (int i = 0; i < enabled_inputs; i++) { - if (i > 0) { - anims += ","; - } - anims += inputs[i].name; - } - property.hint_string = anims; - } - if (property.name.begins_with("input_")) { String n = property.name.get_slicec('/', 0).get_slicec('_', 1); if (n != "count") { @@ -769,14 +787,10 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_input_caption", "input", "caption"), &AnimationNodeTransition::set_input_caption); ClassDB::bind_method(D_METHOD("get_input_caption", "input"), &AnimationNodeTransition::get_input_caption); - ClassDB::bind_method(D_METHOD("set_current", "index"), &AnimationNodeTransition::set_current); - ClassDB::bind_method(D_METHOD("get_current"), &AnimationNodeTransition::get_current); - ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time); ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time); ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current", PROPERTY_HINT_RANGE, "0,64,1"), "set_current", "get_current"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01"), "set_cross_fade_time", "get_cross_fade_time"); for (int i = 0; i < MAX_INPUTS; i++) { @@ -786,13 +800,15 @@ void AnimationNodeTransition::_bind_methods() { } AnimationNodeTransition::AnimationNodeTransition() { + + prev_xfading = "prev_xfading"; + prev = "prev"; + time = "time"; + current = "current"; + prev_current = "prev_current"; + ; + enabled_inputs = 0; - xfade = 0; - current = -1; - prev = -1; - prev_time = 0; - prev_xfading = 0; - switched = false; for (int i = 0; i < MAX_INPUTS; i++) { inputs[i].auto_advance = false; inputs[i].name = itos(i + 1); @@ -814,69 +830,102 @@ AnimationNodeOutput::AnimationNodeOutput() { } /////////////////////////////////////////////////////// -void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNode> p_node) { +void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position) { ERR_FAIL_COND(nodes.has(p_name)); ERR_FAIL_COND(p_node.is_null()); - ERR_FAIL_COND(p_node->get_parent().is_valid()); - ERR_FAIL_COND(p_node->get_tree() != NULL); ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output); ERR_FAIL_COND(String(p_name).find("/") != -1); - nodes[p_name] = p_node; - p_node->set_parent(this); - p_node->set_tree(get_tree()); + Node n; + n.node = p_node; + n.position = p_position; + n.connections.resize(n.node->get_input_count()); + nodes[p_name] = n; emit_changed(); + emit_signal("tree_changed"); + + p_node->connect("tree_changed", this, "_tree_changed", varray(), CONNECT_REFERENCE_COUNTED); + p_node->connect("changed", this, "_node_changed", varray(p_name), CONNECT_REFERENCE_COUNTED); } Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) const { ERR_FAIL_COND_V(!nodes.has(p_name), Ref<AnimationNode>()); - return nodes[p_name]; + return nodes[p_name].node; } StringName AnimationNodeBlendTree::get_node_name(const Ref<AnimationNode> &p_node) const { - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - if (E->get() == p_node) { + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + if (E->get().node == p_node) { return E->key(); } } ERR_FAIL_V(StringName()); } + +void AnimationNodeBlendTree::set_node_position(const StringName &p_node, const Vector2 &p_position) { + ERR_FAIL_COND(!nodes.has(p_node)); + nodes[p_node].position = p_position; +} + +Vector2 AnimationNodeBlendTree::get_node_position(const StringName &p_node) const { + ERR_FAIL_COND_V(!nodes.has(p_node), Vector2()); + return nodes[p_node].position; +} + +void AnimationNodeBlendTree::get_child_nodes(List<ChildNode> *r_child_nodes) { + Vector<StringName> ns; + + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + ns.push_back(E->key()); + } + + ns.sort_custom<StringName::AlphCompare>(); + + for (int i = 0; i < ns.size(); i++) { + ChildNode cn; + cn.name = ns[i]; + cn.node = nodes[cn.name].node; + r_child_nodes->push_back(cn); + } +} + bool AnimationNodeBlendTree::has_node(const StringName &p_name) const { return nodes.has(p_name); } +Vector<StringName> AnimationNodeBlendTree::get_node_connection_array(const StringName &p_name) const { + + ERR_FAIL_COND_V(!nodes.has(p_name), Vector<StringName>()); + return nodes[p_name].connections; +} void AnimationNodeBlendTree::remove_node(const StringName &p_name) { ERR_FAIL_COND(!nodes.has(p_name)); ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output); //can't delete output { - //erase node connections - Ref<AnimationNode> node = nodes[p_name]; - for (int i = 0; i < node->get_input_count(); i++) { - node->set_input_connection(i, StringName()); - } - node->set_parent(NULL); - node->set_tree(NULL); + Ref<AnimationNode> node = nodes[p_name].node; + node->disconnect("tree_changed", this, "_tree_changed"); + node->disconnect("changed", this, "_node_changed"); } nodes.erase(p_name); //erase connections to name - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - for (int i = 0; i < node->get_input_count(); i++) { - if (node->get_input_connection(i) == p_name) { - node->set_input_connection(i, StringName()); + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().connections.size(); i++) { + if (E->get().connections[i] == p_name) { + E->get().connections.write[i] = StringName(); } } } emit_changed(); + emit_signal("tree_changed"); } void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringName &p_new_name) { @@ -886,18 +935,24 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output); ERR_FAIL_COND(p_new_name == SceneStringNames::get_singleton()->output); + nodes[p_name].node->disconnect("changed", this, "_node_changed"); + nodes[p_new_name] = nodes[p_name]; nodes.erase(p_name); //rename connections - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - for (int i = 0; i < node->get_input_count(); i++) { - if (node->get_input_connection(i) == p_name) { - node->set_input_connection(i, p_new_name); + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + + for (int i = 0; i < E->get().connections.size(); i++) { + if (E->get().connections[i] == p_name) { + E->get().connections.write[i] = p_new_name; } } } + //connection must be done with new name + nodes[p_new_name].node->connect("changed", this, "_node_changed", varray(p_new_name), CONNECT_REFERENCE_COUNTED); + + emit_signal("tree_changed"); } void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) { @@ -907,18 +962,18 @@ void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_ ERR_FAIL_COND(p_output_node == SceneStringNames::get_singleton()->output); ERR_FAIL_COND(p_input_node == p_output_node); - Ref<AnimationNode> input = nodes[p_input_node]; - ERR_FAIL_INDEX(p_input_index, input->get_input_count()); + Ref<AnimationNode> input = nodes[p_input_node].node; + ERR_FAIL_INDEX(p_input_index, nodes[p_input_node].connections.size()); - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - for (int i = 0; i < node->get_input_count(); i++) { - StringName output = node->get_input_connection(i); + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().connections.size(); i++) { + StringName output = E->get().connections[i]; ERR_FAIL_COND(output == p_output_node); } } - input->set_input_connection(p_input_index, p_output_node); + nodes[p_input_node].connections.write[p_input_index] = p_output_node; + emit_changed(); } @@ -926,20 +981,10 @@ void AnimationNodeBlendTree::disconnect_node(const StringName &p_node, int p_inp ERR_FAIL_COND(!nodes.has(p_node)); - Ref<AnimationNode> input = nodes[p_node]; - ERR_FAIL_INDEX(p_input_index, input->get_input_count()); + Ref<AnimationNode> input = nodes[p_node].node; + ERR_FAIL_INDEX(p_input_index, nodes[p_node].connections.size()); - input->set_input_connection(p_input_index, StringName()); -} - -float AnimationNodeBlendTree::get_connection_activity(const StringName &p_input_node, int p_input_index) const { - - ERR_FAIL_COND_V(!nodes.has(p_input_node), 0); - - Ref<AnimationNode> input = nodes[p_input_node]; - ERR_FAIL_INDEX_V(p_input_index, input->get_input_count(), 0); - - return input->get_input_activity(p_input_index); + nodes[p_node].connections.write[p_input_index] = StringName(); } AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) const { @@ -956,20 +1001,19 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node return CONNECTION_ERROR_SAME_NODE; } - Ref<AnimationNode> input = nodes[p_input_node]; + Ref<AnimationNode> input = nodes[p_input_node].node; - if (p_input_index < 0 || p_input_index >= input->get_input_count()) { + if (p_input_index < 0 || p_input_index >= nodes[p_input_node].connections.size()) { return CONNECTION_ERROR_NO_INPUT_INDEX; } - if (input->get_input_connection(p_input_index) != StringName()) { + if (nodes[p_input_node].connections[p_input_index] != StringName()) { return CONNECTION_ERROR_CONNECTION_EXISTS; } - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - for (int i = 0; i < node->get_input_count(); i++) { - StringName output = node->get_input_connection(i); + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().connections.size(); i++) { + StringName output = E->get().connections[i]; if (output == p_output_node) { return CONNECTION_ERROR_CONNECTION_EXISTS; } @@ -980,10 +1024,9 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node void AnimationNodeBlendTree::get_node_connections(List<NodeConnection> *r_connections) const { - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - for (int i = 0; i < node->get_input_count(); i++) { - StringName output = node->get_input_connection(i); + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().connections.size(); i++) { + StringName output = E->get().connections[i]; if (output != StringName()) { NodeConnection nc; nc.input_node = E->key(); @@ -1001,13 +1044,13 @@ String AnimationNodeBlendTree::get_caption() const { float AnimationNodeBlendTree::process(float p_time, bool p_seek) { - Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output]; - return blend_node(output, p_time, p_seek, 1.0); + Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node; + return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, 1.0); } void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) { - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { r_list->push_back(E->key()); } } @@ -1022,14 +1065,8 @@ Vector2 AnimationNodeBlendTree::get_graph_offset() const { return graph_offset; } -void AnimationNodeBlendTree::set_tree(AnimationTree *p_player) { - - AnimationNode::set_tree(p_player); - - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - Ref<AnimationNode> node = E->get(); - node->set_tree(p_player); - } +Ref<AnimationNode> AnimationNodeBlendTree::get_child_by_name(const StringName &p_name) { + return get_node(p_name); } bool AnimationNodeBlendTree::_set(const StringName &p_name, const Variant &p_value) { @@ -1051,7 +1088,7 @@ bool AnimationNodeBlendTree::_set(const StringName &p_name, const Variant &p_val if (what == "position") { if (nodes.has(node_name)) { - nodes[node_name]->set_position(p_value); + nodes[node_name].position = p_value; } return true; } @@ -1078,7 +1115,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons if (what == "node") { if (nodes.has(node_name)) { - r_ret = nodes[node_name]; + r_ret = nodes[node_name].node; return true; } } @@ -1086,7 +1123,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons if (what == "position") { if (nodes.has(node_name)) { - r_ret = nodes[node_name]->get_position(); + r_ret = nodes[node_name].position; return true; } } @@ -1113,7 +1150,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) const { List<StringName> names; - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { + for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { names.push_back(E->key()); } names.sort_custom<StringName::AlphCompare>(); @@ -1121,7 +1158,7 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons for (List<StringName>::Element *E = names.front(); E; E = E->next()) { String name = E->get(); if (name != "output") { - p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR)); } p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } @@ -1129,9 +1166,19 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } +void AnimationNodeBlendTree::_tree_changed() { + emit_signal("tree_changed"); +} + +void AnimationNodeBlendTree::_node_changed(const StringName &p_node) { + + ERR_FAIL_COND(!nodes.has(p_node)); + nodes[p_node].connections.resize(nodes[p_node].node->get_input_count()); +} + void AnimationNodeBlendTree::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_node", "name", "node"), &AnimationNodeBlendTree::add_node); + ClassDB::bind_method(D_METHOD("add_node", "name", "node", "position"), &AnimationNodeBlendTree::add_node, DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("get_node", "name"), &AnimationNodeBlendTree::get_node); ClassDB::bind_method(D_METHOD("remove_node", "name"), &AnimationNodeBlendTree::remove_node); ClassDB::bind_method(D_METHOD("rename_node", "name", "new_name"), &AnimationNodeBlendTree::rename_node); @@ -1139,9 +1186,15 @@ void AnimationNodeBlendTree::_bind_methods() { ClassDB::bind_method(D_METHOD("connect_node", "input_node", "input_index", "output_node"), &AnimationNodeBlendTree::connect_node); ClassDB::bind_method(D_METHOD("disconnect_node", "input_node", "input_index"), &AnimationNodeBlendTree::disconnect_node); + ClassDB::bind_method(D_METHOD("set_node_position", "name", "position"), &AnimationNodeBlendTree::set_node_position); + ClassDB::bind_method(D_METHOD("get_node_position", "name"), &AnimationNodeBlendTree::get_node_position); + ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeBlendTree::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeBlendTree::get_graph_offset); + ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendTree::_tree_changed); + ClassDB::bind_method(D_METHOD("_node_changed", "node"), &AnimationNodeBlendTree::_node_changed); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); BIND_CONSTANT(CONNECTION_OK); @@ -1156,15 +1209,12 @@ AnimationNodeBlendTree::AnimationNodeBlendTree() { Ref<AnimationNodeOutput> output; output.instance(); - output->set_position(Vector2(300, 150)); - output->set_parent(this); - nodes["output"] = output; + Node n; + n.node = output; + n.position = Vector2(300, 150); + n.connections.resize(1); + nodes["output"] = n; } AnimationNodeBlendTree::~AnimationNodeBlendTree() { - - for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) { - E->get()->set_parent(NULL); - E->get()->set_tree(NULL); - } } |