Hi.
To give some context, I’m create a sort of ‘guide’ sphere component for use when making a level. It’s a sphere used to indicate the distance from which a camera will view an object (can be changed on the object properties.) I have this sphere created automatically. I use PostLoad, PostLoadSubojects and PostEditChangeProperty to trigger the sphere being created/resized. This all works fine.
The issue arises with the scale of the spheres. I want the sphere to be a constant size, not depending on the scale of the object itself. I have since discovered bAbsoluteScale - this does not change the nature of the bug.
The issue is that after PostLoad and PostLoadSubojects the scale of components is 1,1,1 (I checked this via a breakpoint in VS.) None of the actors loaded in to the map have that scale. I’ve tried GetActorScale() and scanning the actor components for primitive components (and checking they are not my sphere components) and getting the scale directly from RelativeScale3D. Still 1,1,1. Changing the camera distance (and triggering the PostEditChangeProperty method) returns the correct scale.
Relevant code:
#if WITH_EDITOR
void ABCSpaceBody::PostEditChangeProperty( FPropertyChangedEvent& stPropertyChangedEvent )
{
Super::PostEditChangeProperty( stPropertyChangedEvent );
if ( stPropertyChangedEvent.Property == NULL )
return;
if ( stPropertyChangedEvent.Property->GetName() == "fCameraDistanceMin" || stPropertyChangedEvent.Property->GetName() == "RelativeScale3D" )
UpdateCameraDistanceSpheres();
}
void ABCSpaceBody::PostLoad()
{
Super::PostLoad();
InitCameraSpheres();
}
void ABCSpaceBody::PostLoadSubobjects( FObjectInstancingGraph* oOuterInstanceGraph )
{
Super::PostLoadSubobjects( oOuterInstanceGraph );
InitCameraSpheres();
}
#endif // WITH_EDITOR
void ABCSpaceBody::PostInitializeComponents()
{
Super::PostInitializeComponents();
InitCameraSpheres();
}
void ABCSpaceBody::InitCameraSpheres()
{
UWorld* oWorld = GetWorld();
if ( oWorld == NULL )
oWorld = GWorld;
if ( oWorld == NULL )
return;
switch ( oWorld->WorldType )
{
case EWorldType::Game:
case EWorldType::PIE:
if ( cCameraDistanceMinComponent != NULL )
cCameraDistanceMinComponent->DestroyComponent();
if ( cCameraDistanceMaxComponent != NULL )
cCameraDistanceMaxComponent->DestroyComponent();
break;
#if WITH_EDITOR
case EWorldType::Editor:
case EWorldType::Preview:
UpdateCameraDistanceSpheres();
break;
#endif
}
}
#if WITH_EDITOR
void ABCSpaceBody::UpdateCameraDistanceSpheres()
{
// *****
// When triggered from PostLoad and PostLoadSubojects, always returns 1,1,1
// Works fine from PostEditChangeProperty
// *****
FVector vScale = GetActorScale();
// Invert object scale
vScale.X = 1.f / vScale.X;
vScale.Y = 1.f / vScale.Y;
vScale.Z = 1.f / vScale.Z;
if ( cCameraDistanceMinComponent == NULL )
{
NewObjectAssign( cCameraDistanceMinComponent, USphereComponent, "Camera Min Distance Sphere" );
cCameraDistanceMinComponent->AttachTo( GetRootComponent(), NAME_None, EAttachLocation::SnapToTarget );
cCameraDistanceMinComponent->InitSphereRadius( 10.f );
cCameraDistanceMinComponent->bDrawOnlyIfSelected = true;
}
cCameraDistanceMinComponent->SetSphereRadius( max( 10.f, fCameraDistanceMin ) );
cCameraDistanceMinComponent->SetRelativeScale3D( vScale );
if ( cCameraDistanceMaxComponent == NULL )
{
NewObjectAssign( cCameraDistanceMaxComponent, USphereComponent, "Camera Max Distance Sphere" );
cCameraDistanceMaxComponent->AttachTo( GetRootComponent(), NAME_None, EAttachLocation::SnapToTarget );
cCameraDistanceMaxComponent->InitSphereRadius( 10.f );
cCameraDistanceMaxComponent->bDrawOnlyIfSelected = true;
}
vScale *= BC_CAMERA_ORBIT_MAX_ZOOM_OUT;
cCameraDistanceMaxComponent->SetSphereRadius( max( 10.f, fCameraDistanceMin ) );
cCameraDistanceMaxComponent->SetRelativeScale3D( vScale );
}