Refactor AnimGraph to support asynchronous execution
This commit is contained in:
@@ -14,7 +14,7 @@ int32 AnimGraphExecutor::GetRootNodeIndex(Animation* anim)
|
||||
if (anim->Data.RootNodeName.HasChars())
|
||||
{
|
||||
auto& skeleton = _graph.BaseModel->Skeleton;
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < skeleton.Nodes.Count(); i++)
|
||||
{
|
||||
if (skeleton.Nodes[i].Name == anim->Data.RootNodeName)
|
||||
{
|
||||
@@ -119,7 +119,7 @@ float GetAnimSamplePos(float length, Animation* anim, float pos, float speed)
|
||||
// Also, scale the animation to fit the total animation node length without cut in a middle
|
||||
const auto animLength = anim->GetLength();
|
||||
const int32 cyclesCount = Math::FloorToInt(length / animLength);
|
||||
const float cycleLength = animLength * cyclesCount;
|
||||
const float cycleLength = animLength * (float)cyclesCount;
|
||||
const float adjustRateScale = length / cycleLength;
|
||||
auto animPos = pos * speed * adjustRateScale;
|
||||
while (animPos > animLength)
|
||||
@@ -152,10 +152,11 @@ Variant AnimGraphExecutor::SampleAnimation(AnimGraphNode* node, bool loop, float
|
||||
nodes->Position = pos;
|
||||
nodes->Length = length;
|
||||
const auto mapping = anim->GetMapping(_graph.BaseModel);
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
const auto emptyNodes = GetEmptyNodes();
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
const int32 nodeToChannel = mapping->At(i);
|
||||
InitNode(nodes, i);
|
||||
nodes->Nodes[i] = emptyNodes->Nodes[i];
|
||||
if (nodeToChannel != -1)
|
||||
{
|
||||
// Calculate the animated node transformation
|
||||
@@ -197,7 +198,7 @@ Variant AnimGraphExecutor::SampleAnimationsWithBlend(AnimGraphNode* node, bool l
|
||||
nodes->Length = length;
|
||||
const auto mappingA = animA->GetMapping(_graph.BaseModel);
|
||||
const auto mappingB = animB->GetMapping(_graph.BaseModel);
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
const int32 nodeToChannelA = mappingA->At(i);
|
||||
const int32 nodeToChannelB = mappingB->At(i);
|
||||
@@ -286,12 +287,13 @@ Variant AnimGraphExecutor::SampleAnimationsWithBlend(AnimGraphNode* node, bool l
|
||||
const auto mappingB = animB->GetMapping(_graph.BaseModel);
|
||||
const auto mappingC = animC->GetMapping(_graph.BaseModel);
|
||||
Transform tmp, t;
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
const auto emptyNodes = GetEmptyNodes();
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
const int32 nodeToChannelA = mappingA->At(i);
|
||||
const int32 nodeToChannelB = mappingB->At(i);
|
||||
const int32 nodeToChannelC = mappingC->At(i);
|
||||
tmp = t = GetEmptyNodes()->Nodes[i];
|
||||
tmp = t = emptyNodes->Nodes[i];
|
||||
|
||||
// Calculate the animated node transformations
|
||||
if (nodeToChannelA != -1)
|
||||
@@ -384,7 +386,7 @@ Variant AnimGraphExecutor::Blend(AnimGraphNode* node, const Value& poseA, const
|
||||
if (!ANIM_GRAPH_IS_VALID_PTR(poseB))
|
||||
nodesB = GetEmptyNodes();
|
||||
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]);
|
||||
}
|
||||
@@ -443,6 +445,7 @@ void ComputeMultiBlendLength(float& length, AnimGraphNode* node)
|
||||
|
||||
void AnimGraphExecutor::ProcessGroupParameters(Box* box, Node* node, Value& value)
|
||||
{
|
||||
auto& context = Context.Get();
|
||||
switch (node->TypeID)
|
||||
{
|
||||
// Get
|
||||
@@ -453,7 +456,7 @@ void AnimGraphExecutor::ProcessGroupParameters(Box* box, Node* node, Value& valu
|
||||
const auto param = _graph.GetParameter((Guid)node->Values[0], paramIndex);
|
||||
if (param)
|
||||
{
|
||||
value = _data->Parameters[paramIndex].Value;
|
||||
value = context.Data->Parameters[paramIndex].Value;
|
||||
switch (param->Type.Type)
|
||||
{
|
||||
case VariantType::Vector2:
|
||||
@@ -523,19 +526,20 @@ void AnimGraphExecutor::ProcessGroupParameters(Box* box, Node* node, Value& valu
|
||||
|
||||
void AnimGraphExecutor::ProcessGroupTools(Box* box, Node* nodeBase, Value& value)
|
||||
{
|
||||
auto& context = Context.Get();
|
||||
auto node = (AnimGraphNode*)nodeBase;
|
||||
switch (node->TypeID)
|
||||
{
|
||||
// Time
|
||||
case 5:
|
||||
{
|
||||
auto& bucket = _data->State[node->BucketIndex].Animation;
|
||||
if (bucket.LastUpdateFrame != _currentFrameIndex)
|
||||
auto& bucket = context.Data->State[node->BucketIndex].Animation;
|
||||
if (bucket.LastUpdateFrame != context.CurrentFrameIndex)
|
||||
{
|
||||
bucket.TimePosition += _deltaTime;
|
||||
bucket.LastUpdateFrame = _currentFrameIndex;
|
||||
bucket.TimePosition += context.DeltaTime;
|
||||
bucket.LastUpdateFrame = context.CurrentFrameIndex;
|
||||
}
|
||||
value = box->ID == 0 ? bucket.TimePosition : _deltaTime;
|
||||
value = box->ID == 0 ? bucket.TimePosition : context.DeltaTime;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -546,13 +550,10 @@ void AnimGraphExecutor::ProcessGroupTools(Box* box, Node* nodeBase, Value& value
|
||||
|
||||
void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Value& value)
|
||||
{
|
||||
auto box = (AnimGraphBox*)boxBase;
|
||||
if (box->IsCacheValid())
|
||||
{
|
||||
// Return cache
|
||||
value = box->Cache;
|
||||
auto& context = Context.Get();
|
||||
if (context.ValueCache.TryGet(boxBase, value))
|
||||
return;
|
||||
}
|
||||
auto box = (AnimGraphBox*)boxBase;
|
||||
auto node = (AnimGraphNode*)nodeBase;
|
||||
switch (node->TypeID)
|
||||
{
|
||||
@@ -569,7 +570,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
case 2:
|
||||
{
|
||||
const auto anim = node->Assets[0].As<Animation>();
|
||||
auto& bucket = _data->State[node->BucketIndex].Animation;
|
||||
auto& bucket = context.Data->State[node->BucketIndex].Animation;
|
||||
const float speed = (float)tryGetValue(node->GetBox(5), node->Values[1]);
|
||||
const bool loop = (bool)tryGetValue(node->GetBox(6), node->Values[2]);
|
||||
const float startTimePos = (float)tryGetValue(node->GetBox(7), node->Values[3]);
|
||||
@@ -584,17 +585,17 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
const float length = anim ? anim->GetLength() : 0.0f;
|
||||
|
||||
// Calculate new time position
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < _currentFrameIndex - 1)
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < context.CurrentFrameIndex - 1)
|
||||
{
|
||||
// If speed is negative and it's the first node update then start playing from end
|
||||
bucket.TimePosition = length;
|
||||
}
|
||||
float newTimePos = bucket.TimePosition + _deltaTime * speed;
|
||||
float newTimePos = bucket.TimePosition + context.DeltaTime * speed;
|
||||
|
||||
value = SampleAnimation(node, loop, length, startTimePos, bucket.TimePosition, newTimePos, anim, 1.0f);
|
||||
|
||||
bucket.TimePosition = newTimePos;
|
||||
bucket.LastUpdateFrame = _currentFrameIndex;
|
||||
bucket.LastUpdateFrame = context.CurrentFrameIndex;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -615,7 +616,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// Is Playing
|
||||
case 4:
|
||||
// If anim was updated during this or a previous frame
|
||||
value = bucket.LastUpdateFrame >= _currentFrameIndex - 1;
|
||||
value = bucket.LastUpdateFrame >= context.CurrentFrameIndex - 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -643,7 +644,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
value = Value::Null;
|
||||
if (inputBox->HasConnection())
|
||||
value = eatBox(nodeBase, inputBox->FirstConnection());
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
return;
|
||||
}
|
||||
const auto nodeIndex = _graph.BaseModel->Skeleton.Bones[boneIndex].NodeIndex;
|
||||
@@ -690,7 +691,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
|
||||
// Transform every node
|
||||
const auto& skeleton = BaseModel->Skeleton;
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
const int32 parentIndex = skeleton.Nodes[i].ParentIndex;
|
||||
if (parentIndex != -1)
|
||||
@@ -729,7 +730,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
|
||||
// Inv transform every node
|
||||
const auto& skeleton = BaseModel->Skeleton;
|
||||
for (int32 i = _skeletonNodesCount - 1; i >= 0; i--)
|
||||
for (int32 i = nodes->Nodes.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
const int32 parentIndex = skeleton.Nodes[i].ParentIndex;
|
||||
if (parentIndex != -1)
|
||||
@@ -775,7 +776,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
{
|
||||
// Pass through the input
|
||||
value = input;
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -836,7 +837,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
if (!ANIM_GRAPH_IS_VALID_PTR(valueB))
|
||||
nodesB = GetEmptyNodes();
|
||||
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]);
|
||||
}
|
||||
@@ -876,7 +877,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
const auto nodesA = static_cast<AnimGraphImpulse*>(valueA.AsPointer);
|
||||
const auto nodesB = static_cast<AnimGraphImpulse*>(valueB.AsPointer);
|
||||
Transform t, tA, tB;
|
||||
for (int32 i = 0; i < _skeletonNodesCount; i++)
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
tA = nodesA->Nodes[i];
|
||||
tB = nodesB->Nodes[i];
|
||||
@@ -921,7 +922,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// Blend all nodes masked by the user
|
||||
Transform tA, tB;
|
||||
auto& nodesMask = mask->GetNodesMask();
|
||||
for (int32 nodeIndex = 0; nodeIndex < _skeletonNodesCount; nodeIndex++)
|
||||
for (int32 nodeIndex = 0; nodeIndex < nodes->Nodes.Count(); nodeIndex++)
|
||||
{
|
||||
tA = nodesA->Nodes[nodeIndex];
|
||||
if (nodesMask[nodeIndex])
|
||||
@@ -956,7 +957,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// [1]: Guid Animation
|
||||
|
||||
// Prepare
|
||||
auto& bucket = _data->State[node->BucketIndex].MultiBlend;
|
||||
auto& bucket = context.Data->State[node->BucketIndex].MultiBlend;
|
||||
const auto range = node->Values[0].AsVector4();
|
||||
const auto speed = (float)tryGetValue(node->GetBox(1), node->Values[1]);
|
||||
const auto loop = (bool)tryGetValue(node->GetBox(2), node->Values[2]);
|
||||
@@ -988,12 +989,12 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
// Calculate new time position
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < _currentFrameIndex - 1)
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < context.CurrentFrameIndex - 1)
|
||||
{
|
||||
// If speed is negative and it's the first node update then start playing from end
|
||||
bucket.TimePosition = data.Length;
|
||||
}
|
||||
float newTimePos = bucket.TimePosition + _deltaTime * speed;
|
||||
float newTimePos = bucket.TimePosition + context.DeltaTime * speed;
|
||||
|
||||
ANIM_GRAPH_PROFILE_EVENT("Multi Blend 1D");
|
||||
|
||||
@@ -1035,7 +1036,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
bucket.TimePosition = newTimePos;
|
||||
bucket.LastUpdateFrame = _currentFrameIndex;
|
||||
bucket.LastUpdateFrame = context.CurrentFrameIndex;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1054,7 +1055,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// [1]: Guid Animation
|
||||
|
||||
// Prepare
|
||||
auto& bucket = _data->State[node->BucketIndex].MultiBlend;
|
||||
auto& bucket = context.Data->State[node->BucketIndex].MultiBlend;
|
||||
const auto range = node->Values[0].AsVector4();
|
||||
const auto speed = (float)tryGetValue(node->GetBox(1), node->Values[1]);
|
||||
const auto loop = (bool)tryGetValue(node->GetBox(2), node->Values[2]);
|
||||
@@ -1090,12 +1091,12 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
// Calculate new time position
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < _currentFrameIndex - 1)
|
||||
if (speed < 0.0f && bucket.LastUpdateFrame < context.CurrentFrameIndex - 1)
|
||||
{
|
||||
// If speed is negative and it's the first node update then start playing from end
|
||||
bucket.TimePosition = data.Length;
|
||||
}
|
||||
float newTimePos = bucket.TimePosition + _deltaTime * speed;
|
||||
float newTimePos = bucket.TimePosition + context.DeltaTime * speed;
|
||||
|
||||
ANIM_GRAPH_PROFILE_EVENT("Multi Blend 2D");
|
||||
|
||||
@@ -1227,7 +1228,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
bucket.TimePosition = newTimePos;
|
||||
bucket.LastUpdateFrame = _currentFrameIndex;
|
||||
bucket.LastUpdateFrame = context.CurrentFrameIndex;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1246,7 +1247,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// [3]: AlphaBlendMode Mode
|
||||
|
||||
// Prepare
|
||||
auto& bucket = _data->State[node->BucketIndex].BlendPose;
|
||||
auto& bucket = context.Data->State[node->BucketIndex].BlendPose;
|
||||
const int32 poseIndex = (int32)tryGetValue(node->GetBox(1), node->Values[0]);
|
||||
const float blendDuration = (float)tryGetValue(node->GetBox(2), node->Values[1]);
|
||||
const int32 poseCount = Math::Clamp(node->Values[2].AsInt, 0, MaxBlendPoses);
|
||||
@@ -1259,7 +1260,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
// Check if transition is not active (first update, pose not changing or transition ended)
|
||||
bucket.TransitionPosition += _deltaTime;
|
||||
bucket.TransitionPosition += context.DeltaTime;
|
||||
if (bucket.PreviousBlendPoseIndex == -1 || bucket.PreviousBlendPoseIndex == poseIndex || bucket.TransitionPosition >= blendDuration || blendDuration <= ANIM_GRAPH_BLEND_THRESHOLD)
|
||||
{
|
||||
bucket.TransitionPosition = 0.0f;
|
||||
@@ -1356,11 +1357,11 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
ANIM_GRAPH_PROFILE_EVENT("State Machine");
|
||||
|
||||
// Prepare
|
||||
auto& bucket = _data->State[node->BucketIndex].StateMachine;
|
||||
auto& bucket = context.Data->State[node->BucketIndex].StateMachine;
|
||||
auto& data = node->Data.StateMachine;
|
||||
int32 transitionsLeft = maxTransitionsPerUpdate == 0 ? MAX_uint16 : maxTransitionsPerUpdate;
|
||||
bool isFirstUpdate = bucket.LastUpdateFrame == 0 || bucket.CurrentState == nullptr;
|
||||
if (bucket.LastUpdateFrame != _currentFrameIndex - 1 && reinitializeOnBecomingRelevant)
|
||||
if (bucket.LastUpdateFrame != context.CurrentFrameIndex - 1 && reinitializeOnBecomingRelevant)
|
||||
{
|
||||
// Reset on becoming relevant
|
||||
isFirstUpdate = true;
|
||||
@@ -1384,19 +1385,19 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
bucket.TransitionPosition = 0.0f;
|
||||
|
||||
// Reset all state buckets pof the graphs and nodes included inside the state machine
|
||||
ResetBuckets(data.Graph);
|
||||
ResetBuckets(context, data.Graph);
|
||||
}
|
||||
|
||||
// Update the active transition
|
||||
if (bucket.ActiveTransition)
|
||||
{
|
||||
bucket.TransitionPosition += _deltaTime;
|
||||
bucket.TransitionPosition += context.DeltaTime;
|
||||
|
||||
// Check ofr transition end
|
||||
// Check for transition end
|
||||
if (bucket.TransitionPosition >= bucket.ActiveTransition->BlendDuration)
|
||||
{
|
||||
// End transition
|
||||
ResetBuckets(bucket.CurrentState->Data.State.Graph);
|
||||
ResetBuckets(context, bucket.CurrentState->Data.State.Graph);
|
||||
bucket.CurrentState = bucket.ActiveTransition->Destination;
|
||||
bucket.ActiveTransition = nullptr;
|
||||
bucket.TransitionPosition = 0.0f;
|
||||
@@ -1422,7 +1423,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
|
||||
// Evaluate source state transition data (position, length, etc.)
|
||||
const Value sourceStatePtr = SampleState(bucket.CurrentState);
|
||||
auto& transitionData = _transitionData; // Note: this could support nested transitions but who uses state machine inside transition rule?
|
||||
auto& transitionData = context.TransitionData; // Note: this could support nested transitions but who uses state machine inside transition rule?
|
||||
if (ANIM_GRAPH_IS_VALID_PTR(sourceStatePtr))
|
||||
{
|
||||
// Use source state as data provider
|
||||
@@ -1475,7 +1476,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
if (bucket.ActiveTransition && bucket.ActiveTransition->BlendDuration <= ZeroTolerance)
|
||||
{
|
||||
// End transition
|
||||
ResetBuckets(bucket.CurrentState->Data.State.Graph);
|
||||
ResetBuckets(context, bucket.CurrentState->Data.State.Graph);
|
||||
bucket.CurrentState = bucket.ActiveTransition->Destination;
|
||||
bucket.ActiveTransition = nullptr;
|
||||
bucket.TransitionPosition = 0.0f;
|
||||
@@ -1498,7 +1499,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
}
|
||||
|
||||
// Update bucket
|
||||
bucket.LastUpdateFrame = _currentFrameIndex;
|
||||
bucket.LastUpdateFrame = context.CurrentFrameIndex;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1537,7 +1538,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// Transition Source State Anim
|
||||
case 23:
|
||||
{
|
||||
const AnimGraphTransitionData& transitionsData = _transitionData;
|
||||
const AnimGraphTransitionData& transitionsData = context.TransitionData;
|
||||
switch (box->ID)
|
||||
{
|
||||
// Length
|
||||
@@ -1587,7 +1588,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
if (callFunc == function)
|
||||
{
|
||||
value = Value::Zero;
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1606,12 +1607,12 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
Box* functionOutputBox = functionOutputNode->TryGetBox(0);
|
||||
|
||||
// Cache relation between current node in the call stack to the actual function graph
|
||||
_functions[nodeBase] = (Graph*)data.Graph;
|
||||
context.Functions[nodeBase] = (Graph*)data.Graph;
|
||||
|
||||
// Evaluate the function output
|
||||
_graphStack.Push((Graph*)data.Graph);
|
||||
context.GraphStack.Push((Graph*)data.Graph);
|
||||
value = functionOutputBox && functionOutputBox->HasConnection() ? eatBox(nodeBase, functionOutputBox->FirstConnection()) : Value::Zero;
|
||||
_graphStack.Pop();
|
||||
context.GraphStack.Pop();
|
||||
break;
|
||||
}
|
||||
// Transform Bone (local/model space)
|
||||
@@ -1635,7 +1636,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
value = Value::Null;
|
||||
if (inputBox->HasConnection())
|
||||
value = eatBox(nodeBase, inputBox->FirstConnection());
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
return;
|
||||
}
|
||||
const auto nodes = node->GetNodes(this);
|
||||
@@ -1704,7 +1705,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
{
|
||||
// Pass through the input
|
||||
value = input;
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1859,18 +1860,14 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
default:
|
||||
break;
|
||||
}
|
||||
box->Cache = value;
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
}
|
||||
|
||||
void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& value)
|
||||
{
|
||||
auto box = (AnimGraphBox*)boxBase;
|
||||
if (box->IsCacheValid())
|
||||
{
|
||||
// Return cache
|
||||
value = box->Cache;
|
||||
auto& context = Context.Get();
|
||||
if (context.ValueCache.TryGet(boxBase, value))
|
||||
return;
|
||||
}
|
||||
switch (node->TypeID)
|
||||
{
|
||||
// Function Input
|
||||
@@ -1878,13 +1875,13 @@ void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& va
|
||||
{
|
||||
// Find the function call
|
||||
AnimGraphNode* functionCallNode = nullptr;
|
||||
ASSERT(_graphStack.Count() >= 2);
|
||||
ASSERT(context.GraphStack.Count() >= 2);
|
||||
Graph* graph;
|
||||
for (int32 i = _callStack.Count() - 1; i >= 0; i--)
|
||||
for (int32 i = context.CallStack.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
if (_callStack[i]->Type == GRAPH_NODE_MAKE_TYPE(9, 24) && _functions.TryGet(_callStack[i], graph) && _graphStack[_graphStack.Count() - 1] == (Graph*)graph)
|
||||
if (context.CallStack[i]->Type == GRAPH_NODE_MAKE_TYPE(9, 24) && context.Functions.TryGet(context.CallStack[i], graph) && context.GraphStack.Last() == (Graph*)graph)
|
||||
{
|
||||
functionCallNode = (AnimGraphNode*)_callStack[i];
|
||||
functionCallNode = (AnimGraphNode*)context.CallStack[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1926,19 +1923,19 @@ void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& va
|
||||
if (functionCallBox && functionCallBox->HasConnection())
|
||||
{
|
||||
// Use provided input value from the function call
|
||||
_graphStack.Pop();
|
||||
context.GraphStack.Pop();
|
||||
value = eatBox(node, functionCallBox->FirstConnection());
|
||||
_graphStack.Push(graph);
|
||||
context.GraphStack.Push(graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default value from the function graph
|
||||
value = tryGetValue(node->TryGetBox(1), Value::Zero);
|
||||
}
|
||||
context.ValueCache.Add(boxBase, value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
box->Cache = value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user