Fix anim graph trace events debugging to include nodes path for nested graphs
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user