Fix anim graph trace events debugging to include nodes path for nested graphs

This commit is contained in:
Wojtek Figat
2024-02-07 19:03:38 +01:00
parent e75902e900
commit a38d1ad7cc
6 changed files with 51 additions and 11 deletions

View File

@@ -115,16 +115,36 @@ namespace FlaxEditor.Surface
internal AnimGraphTraceEvent[] LastTraceEvents;
internal bool TryGetTraceEvent(SurfaceNode node, out AnimGraphTraceEvent traceEvent)
internal unsafe bool TryGetTraceEvent(SurfaceNode node, out AnimGraphTraceEvent traceEvent)
{
if (LastTraceEvents != null)
{
foreach (var e in LastTraceEvents)
{
// Node IDs must match
if (e.NodeId == node.ID)
{
traceEvent = e;
return true;
uint* nodePath = e.NodePath0;
// Get size of the path
int nodePathSize = 0;
while (nodePathSize < 8 && nodePath[nodePathSize] != 0)
nodePathSize++;
// Follow input node contexts path to verify if it matches with the path in the event
var c = node.Context;
for (int i = nodePathSize - 1; i >= 0 && c != null; i--)
{
if (c.OwnerNodeID != nodePath[i])
c = null;
else
c = c.Parent;
}
if (c != null)
{
traceEvent = e;
return true;
}
}
}
}

View File

@@ -62,6 +62,8 @@ namespace FlaxEditor.Surface
surfaceContext = CreateContext(_context, context);
_context?.Children.Add(surfaceContext);
_contextCache.Add(contextHandle, surfaceContext);
if (context is SurfaceNode asNode)
surfaceContext.OwnerNodeID = asNode.ID;
context.OnContextCreated(surfaceContext);

View File

@@ -156,6 +156,11 @@ namespace FlaxEditor.Surface
/// </summary>
public event Action<SurfaceControl> ControlDeleted;
/// <summary>
/// Identifier of the node that 'owns' this context (eg. State Machine which created this graph of state nodes).
/// </summary>
public uint OwnerNodeID;
/// <summary>
/// Initializes a new instance of the <see cref="VisjectSurfaceContext"/> class.
/// </summary>

View File

@@ -215,6 +215,7 @@ void AnimGraphExecutor::Update(AnimGraphInstanceData& data, float dt)
// Prepare context data for the evaluation
context.GraphStack.Clear();
context.GraphStack.Push((Graph*)&_graph);
context.NodePath.Clear();
context.Data = &data;
context.DeltaTime = dt;
context.CurrentFrameIndex = ++data.CurrentFrame;

View File

@@ -215,6 +215,8 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API AnimGraphTraceEvent
API_FIELD() float Value = 0;
// Identifier of the node in the graph.
API_FIELD() uint32 NodeId = 0;
// Ids of graph nodes (call of hierarchy).
API_FIELD(Internal, NoArray) uint32 NodePath[8] = {};
};
/// <summary>
@@ -796,6 +798,7 @@ struct AnimGraphContext
AnimGraphTransitionData TransitionData;
Array<VisjectExecutor::Node*, FixedAllocation<ANIM_GRAPH_MAX_CALL_STACK>> CallStack;
Array<VisjectExecutor::Graph*, FixedAllocation<32>> GraphStack;
Array<uint32, FixedAllocation<ANIM_GRAPH_MAX_CALL_STACK> > NodePath;
Dictionary<VisjectExecutor::Node*, VisjectExecutor::Graph*> Functions;
ChunkedArray<AnimGraphImpulse, 256> PoseCache;
int32 PoseCacheSize;
@@ -891,7 +894,7 @@ private:
Variant SampleAnimationsWithBlend(AnimGraphNode* node, bool loop, float length, float startTimePos, float prevTimePos, float& newTimePos, Animation* animA, Animation* animB, float speedA, float speedB, float alpha);
Variant SampleAnimationsWithBlend(AnimGraphNode* node, bool loop, float length, float startTimePos, float prevTimePos, float& newTimePos, Animation* animA, Animation* animB, Animation* animC, float speedA, float speedB, float speedC, float alphaA, float alphaB, float alphaC);
Variant Blend(AnimGraphNode* node, const Value& poseA, const Value& poseB, float alpha, AlphaBlendMode alphaMode);
Variant SampleState(AnimGraphNode* state);
Variant SampleState(AnimGraphContext& context, const AnimGraphNode* state);
void InitStateTransition(AnimGraphContext& context, AnimGraphInstanceData::StateMachineBucket& stateMachineBucket, AnimGraphStateTransition* transition = nullptr);
AnimGraphStateTransition* UpdateStateTransitions(AnimGraphContext& context, const AnimGraphNode::StateMachineData& stateMachineData, AnimGraphNode* state, AnimGraphNode* ignoreState = nullptr);
void UpdateStateTransitions(AnimGraphContext& context, const AnimGraphNode::StateMachineData& stateMachineData, AnimGraphInstanceData::StateMachineBucket& stateMachineBucket, const AnimGraphNode::StateBaseData& stateData);

View File

@@ -227,6 +227,9 @@ void AnimGraphExecutor::ProcessAnimation(AnimGraphImpulse* nodes, AnimGraphNode*
trace.Asset = anim;
trace.Value = animPos;
trace.NodeId = node->ID;
auto* nodePath = context.NodePath.Get();
for (int32 i = 0; i < context.NodePath.Count(); i++)
trace.NodePath[i] = nodePath[i];
}
// Evaluate nested animations
@@ -494,14 +497,17 @@ Variant AnimGraphExecutor::Blend(AnimGraphNode* node, const Value& poseA, const
return nodes;
}
Variant AnimGraphExecutor::SampleState(AnimGraphNode* state)
Variant AnimGraphExecutor::SampleState(AnimGraphContext& context, const AnimGraphNode* state)
{
auto& data = state->Data.State;
if (data.Graph == nullptr || data.Graph->GetRootNode() == nullptr)
return Value::Null;
ANIM_GRAPH_PROFILE_EVENT("Evaluate State");
context.NodePath.Add(state->ID);
auto rootNode = data.Graph->GetRootNode();
return eatBox((Node*)rootNode, &rootNode->Boxes[0]);
auto result = eatBox((Node*)rootNode, &rootNode->Boxes[0]);
context.NodePath.Pop();
return result;
}
void AnimGraphExecutor::InitStateTransition(AnimGraphContext& context, AnimGraphInstanceData::StateMachineBucket& stateMachineBucket, AnimGraphStateTransition* transition)
@@ -537,7 +543,7 @@ AnimGraphStateTransition* AnimGraphExecutor::UpdateStateTransitions(AnimGraphCon
}
// Evaluate source state transition data (position, length, etc.)
const Value sourceStatePtr = SampleState(state);
const Value sourceStatePtr = SampleState(context, state);
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))
{
@@ -1660,6 +1666,8 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
bucket.CurrentState = bucket.ActiveTransition->Destination; \
InitStateTransition(context, bucket)
context.NodePath.Push(node->ID);
// Update the active transition
if (bucket.ActiveTransition)
{
@@ -1767,11 +1775,11 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
if (bucket.BaseTransitionState)
{
// Sample the other state (eg. when blending from interrupted state to the another state from the old destination)
value = SampleState(bucket.BaseTransitionState);
value = SampleState(context, bucket.BaseTransitionState);
if (bucket.BaseTransition)
{
// Evaluate the base pose from the time when transition was interrupted
const auto destinationState = SampleState(bucket.BaseTransition->Destination);
const auto destinationState = SampleState(context, bucket.BaseTransition->Destination);
const float alpha = bucket.BaseTransitionPosition / bucket.BaseTransition->BlendDuration;
value = Blend(node, value, destinationState, alpha, bucket.BaseTransition->BlendMode);
}
@@ -1779,14 +1787,14 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
else
{
// Sample the current state
value = SampleState(bucket.CurrentState);
value = SampleState(context, bucket.CurrentState);
}
// Handle active transition blending
if (bucket.ActiveTransition)
{
// Sample the active transition destination state
const auto destinationState = SampleState(bucket.ActiveTransition->Destination);
const auto destinationState = SampleState(context, bucket.ActiveTransition->Destination);
// Perform blending
const float alpha = bucket.TransitionPosition / bucket.ActiveTransition->BlendDuration;
@@ -1794,6 +1802,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
}
bucket.LastUpdateFrame = context.CurrentFrameIndex;
context.NodePath.Pop();
#undef END_TRANSITION
break;
}