Saturday, August 24, 2019

selection - How to handle focus on a custom actor in Unreal Engine?


I created a custom actor, placed it on my scene and selected it.


When I press "F" to focus on it, the camera zoom back very far from the scene, probably because I didn't implement the method supposed to return the bounding box of my actor.


How can I do that?


Update



I implemented a custom component which delegates all drawing functions to an internal ULineBatchComponent member. I unregistered this ULineBatchComponent member. The custom component is not even attached to the actor root component.


But its bounding box is still taken into account when focusing on the actor.


UPBLineBatchComponent.h


UCLASS()
class UPBLineBatchComponent : public UObject
{
GENERATED_UCLASS_BODY()
public:
virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const;
void SetTransform(const FTransform &Transform);

virtual void DrawLine(...);
virtual void DrawPoint(...);
void Flush();
ULineBatchComponent* LineBatchComponent;
FBox LocalBounds;
};

UPBLineBatchComponent.cpp


UPBLineBatchComponent::UPBLineBatchComponent( const FObjectInitializer& ObjectInitializer )
: Super( ObjectInitializer )

{
LineBatchComponent = CreateDefaultSubobject(TEXT("LineBatcher"));
LineBatchComponent->UnregisterComponent();
LocalBounds = FBox(0);
LineBatchComponent->Bounds = FBoxSphereBounds(EForceInit::ForceInitToZero);
}

FBoxSphereBounds UPBLineBatchComponent::CalcBounds(const FTransform& LocalToWorld) const
{
LineBatchComponent->Bounds = FBoxSphereBounds(LocalBounds.TransformBy(LocalToWorld));

return FBoxSphereBounds(LocalBounds.TransformBy(LocalToWorld));
}

void UPBLineBatchComponent::SetTransform(const FTransform& Transform)
{
LocalBounds = LocalBounds.TransformBy(Transform);
LineBatchComponent->Bounds = FBoxSphereBounds(LocalBounds);

bool bDirty = false;
for (FBatchedLine& Line : LineBatchComponent->BatchedLines)

{
Line.Start = Transform.TransformPosition(Line.Start);
Line.End = Transform.TransformPosition(Line.End);
bDirty = true;
}

for (FBatchedPoint& Point : LineBatchComponent->BatchedPoints)
{
Point.Position = Transform.TransformPosition(Point.Position);
bDirty = true;

}

for (FBatchedMesh& Mesh : LineBatchComponent->BatchedMeshes)
{
for (FVector& Vert : Mesh.MeshVerts)
{
Vert = Transform.TransformPosition(Vert);
bDirty = true;
}
}


if (bDirty)
{
LineBatchComponent->MarkRenderStateDirty();
}
}

void UPBLineBatchComponent::DrawLine(const FVector &Start, const FVector &End, const FLinearColor &Color, uint8 DepthPriority, float Thickness, float LifeTime)
{
LineBatchComponent->DrawLine(Start, End, Color, DepthPriority, Thickness, LifeTime);

LocalBounds += Start;
LocalBounds += End;
LineBatchComponent->Bounds = FBoxSphereBounds(LocalBounds);
}

void UPBLineBatchComponent::DrawPoint(const FVector &Position, const FLinearColor &Color, float PointSize, uint8 DepthPriority, float LifeTime)
{
LineBatchComponent->DrawPoint(Position, Color, PointSize, DepthPriority, LifeTime);
LocalBounds += Position;
LineBatchComponent->Bounds = FBoxSphereBounds(LocalBounds);

}

void UPBLineBatchComponent::Flush()
{
LineBatchComponent->Flush();
LocalBounds = FBox(0);
LineBatchComponent->Bounds = FBoxSphereBounds(EForceInit::ForceInitToZero);
}

Update 2



If I use


LineBatchComponent = NewObject();

instead of


LineBatchComponent = CreateDefaultSubobject(TEXT("LineBatcher"));

I can focus properly on the actor, but I can't see the lines anymore.



Answer



I've never experienced the problem you're describing with any custom actor types. You shouldn't need to do anything explicitly, or implement any methods, yourself.


The "focus" command is handled in EditorServer.cpp (the link requires access to Epic's private Unreal Engine GitHub, which can be obtained by registering an account with Epic); specifically UEditorEngine::MoveViewportCamerasToActor.



This method computes a bounding box for the viewable region based on the bounding boxes of the individual selected actors and their components.


Based on your problem description, it is likely that your actor, or one of its components, has an improperly initialized or overly-large bounding box assigned. The other possibility would be that your actor has no components, and is configured such that all other code paths computing the bounding box are skipped (certain types of actors, et cetera), resulting in a zero box.


However the subsequent call that actually focuses the viewport on a box will early-out if given a zero box, so it's quite likely the case is the first one: one of your actor's components has an overly-large or malformed non-zero bounding box.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...