Drawing debug lines to persona viewport from AnimNode

So I’ve been still wrestling with the SkelControl bone rotation issue I asked about in this question , and I figured that at the very least being able to draw the calculated rotation axis to the viewport would help me in debugging the issue.
Is it possible for me to access the viewport and draw some debugging lines, etc, to it, from inside my custom AnimNode/SkelControl? If so, where should I look in the documentation to find out how?

Edit: So, I found

void UAnimGraphNode_SkeletalControlBase::Draw( FPrimitiveDrawInterface* PDI, USkeletalMeshComponent * PreviewSkelMeshComp ) const;

There’s a caveat with that though. If I want to use it to draw data that’s generated during EvaluateBoneTransforms() on my runtime node, I need to cache that data so that Draw() can pull it out.
However the instance of my runtime node that is created inside the AnimGraph node

UPROPERTY(EditAnywhere, Category=Settings)

FAnimNode_Fabrik Node;

(as the documentation says I should), isn’t the same as the instance that is actually running, when I look at it in the debugger; all the values I’m caching aren’t present in the instance that Draw() can access. How should I be doing this instead?

Edit 2: More digging with the debugger shows that the constructor for my AnimGraphNode is being called at least 6 or 8 times during editor startup, as well as when I open the Anim Blueprint in the editor. I’m now even more confused.

So the persona Viewport is AnimationEditorViewportClient, which inherits from FViewportClient and that class has GetWorld() implemented.
The issue is that each node in the graph (the editor class) has a secondary class responsible for the actual calculations of each node (a runtime class) and it is the runtime class that needs to be able to draw the information. However it doesn’t have a reference to the Graph Node that is its parent, which makes sense because in runtime mode you wont have a parent graph node (the graph doesnt exist in the runtime context, just the editor context). The runtime class, which is a subclass of FAnimNode_SkeletalControlBase, doesn’t know anything about the world it is in, it’s just given skeletal data and told to update the bones it needs to.

So the issue is that I can confirm that the viewport has a world reference, but I cannot access the viewport from the runtime object, and while the editor node might be able to access the viewport, I cannot use it to pull the data from public variables on the runtime object, because the instance that the graph node has is not the instance actually performing the calculation.

#Persona Viewport World?

Is the Persona Viewport a world you can determine?

If so then you can use

Draw Debug Line

with that UWorld()

#Initialize(const FAnimationInitializeContext & Context)

UWorld * TheWorld = Context.AnimInstance->GetWorld();

I found a way to access the world context just fine in my Turn in Place Animation node, I have not fully updated it to UE4 though, but this is what worked in the Beta!

#Entire Source Code
Full code here:


void FAnimNode_VictoryTurnInPlace::Initialize(const FAnimationInitializeContext & Context) 
	//Init the Inputs
	//Get the Actor Owner
	OwningActor = Context.AnimInstance-> GetSkelMeshComponent()->GetOwner(); 
	//Editor or Game?
	UWorld * TheWorld = Context.AnimInstance->GetWorld();
	if (!TheWorld) return;
	WorldIsGame = (TheWorld->WorldType == EWorldType::Game);


It’s now called AnimNodeBase, not AnimNode_Base

This looks good. I’ll give it a shot as soon as I have a chance to sit down with the code again - I’m a bit surprised I missed the GetWorld function as being accessible in the animation context as I did go looking there, but it looks like its defined fairly high up in the class hierarchy so I didn’t look hard enough evidently. :slight_smile: I will return to mark this as resolved once I’ve tested it.

All good, its still AnimNode_Base in the codebase I’m using at present. But thanks for notifying me.

Caching the world reference in Initialize() and then calling DrawDebugLine() inside the EvaluateBoneTransforms() did the trick. Thanks :slight_smile: