bUsePercentageBasedScaling

bUsePercentageBasedScaling

#Overview

name: bUsePercentageBasedScaling

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 19 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of bUsePercentageBasedScaling is to control the scaling method used for actors in the Unreal Engine editor. It determines whether to use the old-style multiplicative/percentage scaling method or the new additive/fraction method when scaling actors in the viewport.

This setting variable is primarily used by the Level Editor and Actor manipulation systems within Unreal Engine. It affects how actors respond to scaling operations in the editor viewport.

The value of this variable is set in the LevelEditorViewportSettings class, which is part of the UnrealEd module. It can be accessed and modified through the editor settings.

bUsePercentageBasedScaling interacts with various actor scaling functions, particularly EditorApplyScale methods of different actor types. These methods use this variable to determine how to calculate the new scale values.

Developers must be aware that:

  1. This is considered a temporary solution, as indicated by comments in the code suggesting it might be removed in the future.
  2. It affects the behavior of the editor’s scaling tools, which could impact level design and actor placement workflows.
  3. Different actor types (like lights, triggers, landscapes) have custom implementations that use this variable, so changing it may have wide-ranging effects.

Best practices when using this variable include:

  1. Consistently use one scaling method throughout a project to avoid confusion and inconsistencies.
  2. Be cautious when changing this setting, as it may affect existing levels and actor placements.
  3. Communicate any changes to this setting with the entire development team to ensure everyone is aware of how scaling behavior will work.
  4. Consider the implications on different actor types, as some have custom scaling logic that uses this variable.
  5. Keep an eye on future Unreal Engine updates, as this feature may be deprecated or replaced with a more permanent solution.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEditorPerProjectUserSettings.ini:419, section: [/Script/UnrealEd.LevelEditorViewportSettings]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Settings/LevelEditorViewportSettings.h:447

Scope (from outer to inner):

file
class        class ULevelEditorViewportSettings : public UObject

Source code excerpt:

	/** If enabled, use the old-style multiplicative/percentage scaling method instead of the new additive/fraction method */
	UPROPERTY(EditAnywhere, config, Category=GridSnapping)
	uint32 bUsePercentageBasedScaling:1;

public:

	/** If enabled, new Actors that you drag into the viewport snap to the active 2D layer. */
	UPROPERTY(EditAnywhere, config, Category=GridSnapping, meta=(DisplayName = "Enable 2D Layer Snapping"))
	uint32 bEnableLayerSnap:1;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Settings/LevelEditorViewportSettings.h:659

Scope (from outer to inner):

file
class        class ULevelEditorViewportSettings : public UObject
function     bool UsePercentageBasedScaling

Source code excerpt:

	bool UsePercentageBasedScaling( ) const
	{
		return bUsePercentageBasedScaling;
	}

public:

	/**
	 * Returns an event delegate that is executed when a setting has changed.

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Elements/Actor/ActorElementEditorViewportInteractionCustomization.cpp:158

Scope (from outer to inner):

file
function     void FActorElementEditorViewportInteractionCustomization::GizmoManipulationDeltaUpdate

Source code excerpt:

		// Flag actors to use old-style scaling or not
		// @todo: Remove this hack once we have decided on the scaling method to use.
		AActor::bUsePercentageBasedScaling = GEditor->UsePercentageBasedScaling();

		RootActor->EditorApplyScale(
			ModifiedScale,
			&InPivotLocation,
			InInputState.bAltKeyDown,
			InInputState.bShiftKeyDown,

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Elements/Actor/ActorElementEditorViewportInteractionCustomization.cpp:455

Scope (from outer to inner):

file
function     void FActorElementEditorViewportInteractionCustomization::ApplyDeltaToActor

Source code excerpt:

				// Flag actors to use old-style scaling or not
				// @todo: Remove this hack once we have decided on the scaling method to use.
				AActor::bUsePercentageBasedScaling = GEditor->UsePercentageBasedScaling();

				InActor->EditorApplyScale(
					ModifiedScale,
					&InPivotLocation,
					InInputState.bAltKeyDown,
					InInputState.bShiftKeyDown,

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/GameFramework/Actor.h:2409

Scope (from outer to inner):

file
class        class AActor : public UObject

Source code excerpt:

#if WITH_EDITOR
	/** @todo: Remove this flag once it is decided that additive interactive scaling is what we want */
	static ENGINE_API bool bUsePercentageBasedScaling;

	/**
	 * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation.
	 * The default implementation is simply to translate the actor's location.
	 */
	ENGINE_API virtual void EditorApplyTranslation(const FVector& DeltaTranslation, bool bAltDown, bool bShiftDown, bool bCtrlDown);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ActorEditor.cpp:795

Scope: file

Source code excerpt:


// @todo: Remove this hack once we have decided on the scaling method to use.
bool AActor::bUsePercentageBasedScaling = false;

void AActor::EditorApplyTranslation(const FVector& DeltaTranslation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	if( RootComponent != NULL )
	{
		FTransform NewTransform = GetRootComponent()->GetComponentTransform();

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ActorEditor.cpp:863

Scope (from outer to inner):

file
function     void AActor::EditorApplyScale

Source code excerpt:

		FVector ScaleToApply;

		if( AActor::bUsePercentageBasedScaling )
		{
			ScaleToApply = CurrentScale * (FVector(1.0f) + DeltaScale);
		}
		else
		{
			ScaleToApply = CurrentScale + DeltaScale;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/ReflectionCaptureComponent.cpp:243

Scope (from outer to inner):

file
function     void ASphereReflectionCapture::EditorApplyScale

Source code excerpt:

	USphereReflectionCaptureComponent* SphereComponent = Cast<USphereReflectionCaptureComponent>(GetCaptureComponent());
	check(SphereComponent);
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 5000.0f : 50.0f );
	FMath::ApplyScaleToFloat(SphereComponent->InfluenceRadius, ModifiedScale);
	GetCaptureComponent()->InvalidateLightingCache();
	PostEditChange();
}

void APlaneReflectionCapture::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/ReflectionCaptureComponent.cpp:253

Scope (from outer to inner):

file
function     void APlaneReflectionCapture::EditorApplyScale

Source code excerpt:

	UPlaneReflectionCaptureComponent* PlaneComponent = Cast<UPlaneReflectionCaptureComponent>(GetCaptureComponent());
	check(PlaneComponent);
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 5000.0f : 50.0f );
	FMath::ApplyScaleToFloat(PlaneComponent->InfluenceRadiusScale, ModifiedScale);
	GetCaptureComponent()->InvalidateLightingCache();
	PostEditChange();
}
#endif

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SceneCaptureComponent.cpp:988

Scope (from outer to inner):

file
function     void APlanarReflection::EditorApplyScale

Source code excerpt:

	UPlanarReflectionComponent* ReflectionComponent = GetPlanarReflectionComponent();
	check(ReflectionComponent);
	const FVector ModifiedScale = FVector(0, 0, DeltaScale.Z) * ( AActor::bUsePercentageBasedScaling ? 500.0f : 50.0f );
	FMath::ApplyScaleToFloat(ReflectionComponent->DistanceFromPlaneFadeoutStart, ModifiedScale);
	FMath::ApplyScaleToFloat(ReflectionComponent->DistanceFromPlaneFadeoutEnd, ModifiedScale);
	PostEditChange();
}

#endif

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DecalActor.cpp:119

Scope (from outer to inner):

file
function     void ADecalActor::EditorApplyScale

Source code excerpt:

	}

	const FVector ModifiedScale = Mul * DeltaScale * (AActor::bUsePercentageBasedScaling ? DecalEditorConstants::PercentageScalingMultiplier : DecalEditorConstants::AdditiveScalingMultiplier);

	Super::EditorApplyScale(ModifiedScale, PivotLocation, bAltDown, bShiftDown, bCtrlDown);
}

bool ADecalActor::GetReferencedContentObjects(TArray<UObject*>& Objects) const
{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Light.cpp:339

Scope (from outer to inner):

file
function     void APointLight::EditorApplyScale

Source code excerpt:

void APointLight::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 10000.0f : 100.0f );

	FMath::ApplyScaleToFloat( PointLightComponent->AttenuationRadius, ModifiedScale, 1.0f );
	PostEditChange();
}
#endif

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/RadialForceComponent.cpp:266

Scope (from outer to inner):

file
function     void ARadialForceActor::EditorApplyScale

Source code excerpt:

void ARadialForceActor::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 500.0f : 5.0f );

	const float Multiplier = ( ModifiedScale.X > 0.0f || ModifiedScale.Y > 0.0f || ModifiedScale.Z > 0.0f ) ? 1.0f : -1.0f;
	if(ForceComponent)
	{
		ForceComponent->Radius += Multiplier * ModifiedScale.Size();
		ForceComponent->Radius = FMath::Max( 0.f, ForceComponent->Radius );

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/RectLight.cpp:17

Scope (from outer to inner):

file
function     void ARectLight::EditorApplyScale

Source code excerpt:

void ARectLight::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 10000.0f : 100.0f );

	FMath::ApplyScaleToFloat( RectLightComponent->AttenuationRadius, ModifiedScale, 1.0f );

	PostEditChange();
}
#endif

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SpotLight.cpp:104

Scope (from outer to inner):

file
function     void ASpotLight::EditorApplyScale

Source code excerpt:

void ASpotLight::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 10000.0f : 100.0f );

	if ( bCtrlDown )
	{
		FMath::ApplyScaleToFloat( SpotLightComponent->OuterConeAngle, ModifiedScale, 0.01f );
		SpotLightComponent->OuterConeAngle = FMath::Min( 89.0f, SpotLightComponent->OuterConeAngle );
		SpotLightComponent->InnerConeAngle = FMath::Min( SpotLightComponent->OuterConeAngle, SpotLightComponent->InnerConeAngle );

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/TriggerActors.cpp:61

Scope (from outer to inner):

file
function     void ATriggerCapsule::EditorApplyScale

Source code excerpt:

void ATriggerCapsule::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 500.0f : 5.0f );

	UCapsuleComponent * CapsuleComponent = CastChecked<UCapsuleComponent>(GetRootComponent());
	if ( bCtrlDown )
	{
		// CTRL+Scaling modifies trigger collision height.  This is for convenience, so that height
		// can be changed without having to use the non-uniform scaling widget (which is

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/TriggerActors.cpp:147

Scope (from outer to inner):

file
function     void ATriggerBox::EditorApplyScale

Source code excerpt:

void ATriggerBox::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 500.0f : 5.0f );

	UBoxComponent * BoxComponent = CastChecked<UBoxComponent>(GetRootComponent());
	if ( bCtrlDown )
	{
		// CTRL+Scaling modifies trigger collision height.  This is for convenience, so that height
		// can be changed without having to use the non-uniform scaling widget (which is

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/TriggerActors.cpp:209

Scope (from outer to inner):

file
function     void ATriggerSphere::EditorApplyScale

Source code excerpt:

void ATriggerSphere::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown)
{
	const FVector ModifiedScale = DeltaScale * ( AActor::bUsePercentageBasedScaling ? 500.0f : 5.0f );

	USphereComponent * SphereComponent = CastChecked<USphereComponent>(GetRootComponent());
	SphereComponent->SetSphereRadius(FMath::Max<float>(0.0f, SphereComponent->GetUnscaledSphereRadius() + ModifiedScale.X));
}
#endif	//WITH_EDITOR

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeEdit.cpp:4901

Scope (from outer to inner):

file
function     void ALandscapeProxy::EditorApplyScale

Source code excerpt:

	bool bFavorX = (XYDeltaScaleAbs.X > XYDeltaScaleAbs.Y);

	if (AActor::bUsePercentageBasedScaling)
	{
		// Correct for attempts to scale to 0 on any axis
		double XYDeltaScale = bFavorX ? DeltaScale.X : DeltaScale.Y;
		if (XYDeltaScale == -1.0f)
		{
			XYDeltaScale = -(CurrentScale.X - 1) / CurrentScale.X;