From 75a8606b8335bb6e16b13909fa7f7ae09bed3882 Mon Sep 17 00:00:00 2001 From: SaracenOne Date: Wed, 20 Apr 2022 11:36:54 +0100 Subject: Add AnimationTree Advance Expressions Allows specifying an expression as a condition for state machine transitions. This gives much greater flexibility for creating complex state machines. By directly interfacing with the script code, it is possible to create complex animation advance condition for switching between states. Ensure assigning AnimationTreeStateMachineTransition base expression node in editor is relative to current AnimationTree node. Allow setting an expression base node on the AnimationTree itself. Co-Authored-By: reduz --- scene/animation/animation_node_state_machine.cpp | 66 +++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) (limited to 'scene/animation/animation_node_state_machine.cpp') diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 8dcf538b8f..2ee7f4fa43 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -68,6 +68,34 @@ StringName AnimationNodeStateMachineTransition::get_advance_condition_name() con return advance_condition_name; } +void AnimationNodeStateMachineTransition::set_advance_expression(const String &p_expression) { + advance_expression = p_expression; + + String advance_expression_stripped = advance_expression.strip_edges(); + if (advance_expression_stripped == String()) { + expression.unref(); + return; + } + + if (expression.is_null()) { + expression.instantiate(); + } + + expression->parse(advance_expression_stripped); +} + +String AnimationNodeStateMachineTransition::get_advance_expression() const { + return advance_expression; +} + +void AnimationNodeStateMachineTransition::set_advance_expression_base_node(const NodePath &p_expression_base_node) { + advance_expression_base_node = p_expression_base_node; +} + +NodePath AnimationNodeStateMachineTransition::get_advance_expression_base_node() const { + return advance_expression_base_node; +} + void AnimationNodeStateMachineTransition::set_xfade_time(float p_xfade) { ERR_FAIL_COND(p_xfade < 0); xfade = p_xfade; @@ -115,11 +143,22 @@ void AnimationNodeStateMachineTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_priority", "priority"), &AnimationNodeStateMachineTransition::set_priority); ClassDB::bind_method(D_METHOD("get_priority"), &AnimationNodeStateMachineTransition::get_priority); + ClassDB::bind_method(D_METHOD("set_advance_expression", "text"), &AnimationNodeStateMachineTransition::set_advance_expression); + ClassDB::bind_method(D_METHOD("get_advance_expression"), &AnimationNodeStateMachineTransition::get_advance_expression); + + ClassDB::bind_method(D_METHOD("set_advance_expression_base_node", "path"), &AnimationNodeStateMachineTransition::set_advance_expression_base_node); + ClassDB::bind_method(D_METHOD("get_advance_expression_base_node"), &AnimationNodeStateMachineTransition::get_advance_expression_base_node); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority"); + ADD_GROUP("Switch", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_advance"), "set_auto_advance", "has_auto_advance"); + ADD_GROUP("Advance", "advance_"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "advance_condition"), "set_advance_condition", "get_advance_condition"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "advance_expression", PROPERTY_HINT_EXPRESSION, ""), "set_advance_expression", "get_advance_expression"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "advance_expression_base_node"), "set_advance_expression_base_node", "get_advance_expression_base_node"); + ADD_GROUP("Disabling", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); BIND_ENUM_CONSTANT(SWITCH_MODE_IMMEDIATE); @@ -577,6 +616,29 @@ bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Refexpression.is_valid()) { + AnimationTree *tree_base = state_machine->get_animation_tree(); + ERR_FAIL_COND_V(tree_base == nullptr, false); + + NodePath advance_expression_base_node_path; + if (!transition->advance_expression_base_node.is_empty()) { + advance_expression_base_node_path = transition->advance_expression_base_node; + } else { + advance_expression_base_node_path = tree_base->get_advance_expression_base_node(); + } + + Node *expression_base = tree_base->get_node_or_null(advance_expression_base_node_path); + if (expression_base) { + Ref exp = transition->expression; + bool ret = exp->execute(Array(), tree_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls. + if (!exp->has_execute_failed()) { + if (ret) { + return true; + } + } + } + } + return false; } -- cgit v1.2.3