From af2c5b3429e2062dee361c47dbd928171b8ef483 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 3 Dec 2021 15:38:21 +0100 Subject: [PATCH] Add batching the same function inputs in Anim Graph for better usability --- Source/Engine/Animations/Graph/AnimGraph.cpp | 2 +- .../Animations/Graph/AnimGroup.Animation.cpp | 26 +++------- .../Content/Assets/AnimationGraphFunction.cpp | 51 +++++++++++-------- .../Content/Assets/AnimationGraphFunction.h | 8 +-- 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/Source/Engine/Animations/Graph/AnimGraph.cpp b/Source/Engine/Animations/Graph/AnimGraph.cpp index ec126b88f..53af88ba5 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.cpp +++ b/Source/Engine/Animations/Graph/AnimGraph.cpp @@ -271,7 +271,7 @@ void AnimGraphExecutor::Update(AnimGraphInstanceData& data, float dt) case ValueType::Null: break; default: - LOG(Warning, "Invalid animation update result type {0}", result.Type.ToString()); + //LOG(Warning, "Invalid animation update result type {0}", result.Type.ToString()); break; } if (animResult == nullptr) diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp index f78dead13..2895f7931 100644 --- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp +++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp @@ -1545,22 +1545,12 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu } // State Output case 21: - { - if (box->HasConnection()) - value = eatBox(nodeBase, box->FirstConnection()); - else - value = Value::Null; + value = box->HasConnection() ? eatBox(nodeBase, box->FirstConnection()) : Value::Null; break; - } // Rule Output case 22: - { - if (box->HasConnection()) - value = eatBox(nodeBase, box->FirstConnection()); - else - value = Value::False; + value = box->HasConnection() ? eatBox(nodeBase, box->FirstConnection()) : Value::Null; break; - } // Transition Source State Anim case 23: { @@ -1637,7 +1627,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu // Evaluate the function output context.GraphStack.Push((Graph*)data.Graph); - value = tryGetValue(functionOutputBox, Value::Zero); + value = functionOutputBox && functionOutputBox->HasConnection() ? eatBox(nodeBase, functionOutputBox->FirstConnection()) : Value::Zero; context.GraphStack.Pop(); break; } @@ -1926,17 +1916,13 @@ void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& va // Peek the input box to use int32 inputIndex = -1; + const auto name = (StringView)node->Values[1]; for (int32 i = 0; i < function->Inputs.Count(); i++) { auto& input = function->Inputs[i]; - - // Pick the any nested graph that uses this input - AnimSubGraph* subGraph = data.Graph; - for (auto& graphIndex : input.GraphIndices) - subGraph = subGraph->SubGraphs[graphIndex]; - if (node->ID == subGraph->Nodes[input.NodeIndex].ID) + if (input.Name == name) { - inputIndex = i; + inputIndex = input.InputIndex; break; } } diff --git a/Source/Engine/Content/Assets/AnimationGraphFunction.cpp b/Source/Engine/Content/Assets/AnimationGraphFunction.cpp index 63d3dbfdf..0c20d34ac 100644 --- a/Source/Engine/Content/Assets/AnimationGraphFunction.cpp +++ b/Source/Engine/Content/Assets/AnimationGraphFunction.cpp @@ -30,7 +30,7 @@ Asset::LoadResult AnimationGraphFunction::load() // Load function signature // Note: search also the nested state machines graphs (state output and transition rule) - ProcessGraphForSignature(&graph, true, Array>()); + ProcessGraphForSignature(&graph, true); if (Inputs.Count() >= 16 || Outputs.Count() >= 16) { LOG(Error, "Too many function inputs/outputs in '{0}'. The limit is max 16 inputs and max 16 outputs.", ToString()); @@ -65,11 +65,14 @@ void AnimationGraphFunction::GetSignature(Array> { types.Resize(32); names.Resize(32); - for (int32 i = 0; i < Inputs.Count(); i++) + for (int32 i = 0, j = 0; i < Inputs.Count(); i++) { auto& input = Inputs[i]; - types[i] = input.Type; - names[i] = input.Name; + if (input.InputIndex != i) + continue; + types[j] = input.Type; + names[j] = input.Name; + j++; } for (int32 i = 0; i < Outputs.Count(); i++) { @@ -79,7 +82,7 @@ void AnimationGraphFunction::GetSignature(Array> } } -bool AnimationGraphFunction::SaveSurface(BytesContainer& data) +bool AnimationGraphFunction::SaveSurface(const BytesContainer& data) { // Wait for asset to be loaded or don't if last load failed if (LastLoadFailed()) @@ -113,7 +116,7 @@ bool AnimationGraphFunction::SaveSurface(BytesContainer& data) #endif -void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool canUseOutputs, const Array>& graphIndices) +void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool canUseOutputs) { for (int32 i = 0; i < graph->Nodes.Count(); i++) { @@ -123,13 +126,26 @@ void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool { if (Inputs.Count() < 16) { + // If there already is an input with that name just batch them together + int32 inputIndex = Inputs.Count(); + auto name = (StringView)node.Values[1]; + for (auto& e : Inputs) + { + if (e.Name == name) + { + inputIndex = e.InputIndex; + break; + } + } + auto& p = Inputs.AddOne(); + p.InputIndex = inputIndex; p.NodeIndex = i; - p.GraphIndices = graphIndices; #if USE_EDITOR p.Type = GetGraphFunctionTypeName_Deprecated(node.Values[0]); - p.Name = (StringView)node.Values[1]; #endif + p.Name = name; + } } else if (node.Type == GRAPH_NODE_MAKE_TYPE(16, 2)) // Function Output @@ -137,32 +153,26 @@ void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool if (Outputs.Count() < 16 && canUseOutputs) { auto& p = Outputs.AddOne(); + p.InputIndex = i; p.NodeIndex = i; - p.GraphIndices = graphIndices; #if USE_EDITOR p.Type = GetGraphFunctionTypeName_Deprecated(node.Values[0]); - p.Name = (StringView)node.Values[1]; #endif + p.Name = (StringView)node.Values[1]; } } else if (node.Type == GRAPH_NODE_MAKE_TYPE(9, 18)) // State Machine { if (node.Data.StateMachine.Graph) { - auto subGraph = graphIndices; - subGraph.Add(graph->SubGraphs.Find(node.Data.StateMachine.Graph)); - ASSERT(subGraph.Last() != -1); - ProcessGraphForSignature(node.Data.StateMachine.Graph, false, subGraph); + ProcessGraphForSignature(node.Data.StateMachine.Graph, false); } } else if (node.Type == GRAPH_NODE_MAKE_TYPE(9, 20)) // State { if (node.Data.State.Graph) { - auto subGraph = graphIndices; - subGraph.Add(graph->SubGraphs.Find(node.Data.State.Graph)); - ASSERT(subGraph.Last() != -1); - ProcessGraphForSignature(node.Data.State.Graph, false, subGraph); + ProcessGraphForSignature(node.Data.State.Graph, false); } } } @@ -170,10 +180,7 @@ void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool { if (stateTransition.RuleGraph) { - auto subGraph = graphIndices; - subGraph.Add(graph->SubGraphs.Find(stateTransition.RuleGraph)); - ASSERT(subGraph.Last() != -1); - ProcessGraphForSignature(stateTransition.RuleGraph, false, subGraph); + ProcessGraphForSignature(stateTransition.RuleGraph, false); } } } diff --git a/Source/Engine/Content/Assets/AnimationGraphFunction.h b/Source/Engine/Content/Assets/AnimationGraphFunction.h index 6a046ff9a..1da826a06 100644 --- a/Source/Engine/Content/Assets/AnimationGraphFunction.h +++ b/Source/Engine/Content/Assets/AnimationGraphFunction.h @@ -20,12 +20,12 @@ public: struct FunctionParameter { + int32 InputIndex; int32 NodeIndex; - Array> GraphIndices; #if USE_EDITOR String Type; - String Name; #endif + String Name; }; /// @@ -54,13 +54,13 @@ public: /// /// The surface graph data. /// True if cannot save it, otherwise false. - API_FUNCTION() bool SaveSurface(BytesContainer& data); + API_FUNCTION() bool SaveSurface(const BytesContainer& data); #endif private: - void ProcessGraphForSignature(AnimGraphBase* graph, bool canUseOutputs, const Array>& graphIndices); + void ProcessGraphForSignature(AnimGraphBase* graph, bool canUseOutputs); protected: