bPreserveLocalTransform

bPreserveLocalTransform

#Overview

name: bPreserveLocalTransform

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 13 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of bPreserveLocalTransform is to control whether local transforms of bones should be preserved during animation import in Unreal Engine 5. This setting is primarily used in the animation and skeletal mesh import systems.

Based on the provided code references, this variable is utilized in the following Unreal Engine subsystems and modules:

  1. Interchange Editor Plugin
  2. UnrealEd module
  3. FBX import system

The value of this variable is typically set during the import process, either through user interface options or programmatically. It can be found in various import data classes such as UFbxAnimSequenceImportData and UFbxSceneImportOptionsSkeletalMesh.

This variable interacts with other import settings, particularly those related to animation and skeletal mesh import. It is often used in conjunction with other variables like bImportCustomAttribute, bRemoveRedundantKeys, and bSnapToClosestFrameBoundary.

Developers should be aware of the following when using this variable:

  1. Setting bPreserveLocalTransform to true will maintain the local transforms of bones as they are in the source file.
  2. Setting it to false (default) will recalculate the local transforms based on the global transforms and parent-child relationships.

Best practices when using this variable include:

  1. Consider the source of your animations and whether preserving local transforms is necessary for your specific use case.
  2. Be consistent in your usage across related assets to ensure proper animation behavior.
  3. Test the results with both true and false settings to determine which provides the best outcome for your specific animations and skeletal meshes.
  4. Document your choice and reasoning for future reference, especially if it deviates from the default setting.

#Setting Variables

#References In INI files

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

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/Interchange/Editor/Source/InterchangeEditor/Private/InterchangeFbxAssetImportDataConverter.cpp:494

Scope (from outer to inner):

file
namespace    UE::Interchange::Private
function     UAssetImportData* ConvertToLegacyFbx

Source code excerpt:

				DestinationAnimSequenceImportData->bImportCustomAttribute = GenericAssetPipeline->AnimationPipeline->bImportCustomAttribute;
				DestinationAnimSequenceImportData->bImportMeshesInBoneHierarchy = GenericAssetPipeline->CommonSkeletalMeshesAndAnimationsProperties->bImportMeshesInBoneHierarchy;
				DestinationAnimSequenceImportData->bPreserveLocalTransform = false;
				DestinationAnimSequenceImportData->bRemoveRedundantKeys = GenericAssetPipeline->AnimationPipeline->bRemoveCurveRedundantKeys;
				DestinationAnimSequenceImportData->bSetMaterialDriveParameterOnCustomAttribute = GenericAssetPipeline->AnimationPipeline->bSetMaterialDriveParameterOnCustomAttribute;
				DestinationAnimSequenceImportData->bSnapToClosestFrameBoundary = GenericAssetPipeline->AnimationPipeline->bSnapToClosestFrameBoundary;
				DestinationAnimSequenceImportData->bUseDefaultSampleRate = GenericAssetPipeline->AnimationPipeline->bUse30HzToBakeBoneAnimation;
				DestinationAnimSequenceImportData->CustomSampleRate = GenericAssetPipeline->AnimationPipeline->CustomBoneAnimationSampleRate;
				DestinationAnimSequenceImportData->FrameImportRange = GenericAssetPipeline->AnimationPipeline->FrameImportRange;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxAnimSequenceImportData.h:115

Scope (from outer to inner):

file
class        class UFbxAnimSequenceImportData : public UFbxAssetImportData

Source code excerpt:

	/** If enabled, this will import a curve within the animation */
	UPROPERTY(EditAnywhere, AdvancedDisplay, config, Category = ImportSettings)
	bool bPreserveLocalTransform;

	/** Gets or creates fbx import data for the specified anim sequence */
	static UNREALED_API UFbxAnimSequenceImportData* GetImportDataForAnimSequence(UAnimSequence* AnimSequence, UFbxAnimSequenceImportData* TemplateForCreation);

	UNREALED_API virtual bool CanEditChange(const FProperty* InProperty) const override;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxSceneImportOptionsSkeletalMesh.h:106

Scope (from outer to inner):

file
class        class UFbxSceneImportOptionsSkeletalMesh : public UObject

Source code excerpt:

	/** Type of asset to import from the FBX file */
	UPROPERTY(EditAnywhere, AdvancedDisplay, config, Category = Animation)
	bool bPreserveLocalTransform;

	/** Type of asset to import from the FBX file */
	UPROPERTY(EditAnywhere, AdvancedDisplay, config, Category = Animation)
	bool bDeleteExistingMorphTargetCurves;

	void FillSkeletalMeshInmportData(class UFbxSkeletalMeshImportData* SkeletalMeshImportData, class UFbxAnimSequenceImportData* AnimSequenceImportData, class UFbxSceneImportOptions* SceneImportOptions);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxAnimSequenceImportData.cpp:91

Scope (from outer to inner):

file
function     void UFbxAnimSequenceImportData::CopyAnimationValues

Source code excerpt:

	bImportCustomAttribute = Other->bImportCustomAttribute;
	bImportMeshesInBoneHierarchy = Other->bImportMeshesInBoneHierarchy;
	bPreserveLocalTransform = Other->bPreserveLocalTransform;
	bRemoveRedundantKeys = Other->bRemoveRedundantKeys;
	bSetMaterialDriveParameterOnCustomAttribute = Other->bSetMaterialDriveParameterOnCustomAttribute;
	bAddCurveMetadataToSkeleton = Other->bAddCurveMetadataToSkeleton;
	bUseDefaultSampleRate = Other->bUseDefaultSampleRate;
	CustomSampleRate = Other->CustomSampleRate;
	FrameImportRange = Other->FrameImportRange;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxMainImport.cpp:506

Scope (from outer to inner):

file
namespace    UnFbx
function     void ApplyImportUIToImportOptions

Source code excerpt:

		InOutImportOptions.ResampleRate					= ImportUI->AnimSequenceImportData->CustomSampleRate;
		InOutImportOptions.bSnapToClosestFrameBoundary	= ImportUI->AnimSequenceImportData->bSnapToClosestFrameBoundary;
		InOutImportOptions.bPreserveLocalTransform		= ImportUI->AnimSequenceImportData->bPreserveLocalTransform;
		InOutImportOptions.bDeleteExistingMorphTargetCurves = ImportUI->AnimSequenceImportData->bDeleteExistingMorphTargetCurves;
		InOutImportOptions.bRemoveRedundantKeys			= ImportUI->AnimSequenceImportData->bRemoveRedundantKeys;
		InOutImportOptions.bDoNotImportCurveWithZero	= ImportUI->AnimSequenceImportData->bDoNotImportCurveWithZero;
		InOutImportOptions.bImportCustomAttribute		= ImportUI->AnimSequenceImportData->bImportCustomAttribute;
		InOutImportOptions.bDeleteExistingCustomAttributeCurves = ImportUI->AnimSequenceImportData->bDeleteExistingCustomAttributeCurves;
		InOutImportOptions.bDeleteExistingNonCurveCustomAttributes = ImportUI->AnimSequenceImportData->bDeleteExistingNonCurveCustomAttributes;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxMainImport.cpp:1794

Scope (from outer to inner):

file
lambda-function

Source code excerpt:

							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt DeleteExistingCustomAttributeCurves"), CaptureImportOptions->bDeleteExistingCustomAttributeCurves));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt DeleteExistingNonCurveCustomAttributes"), CaptureImportOptions->bDeleteExistingNonCurveCustomAttributes));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt PreserveLocalTransform"), CaptureImportOptions->bPreserveLocalTransform));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt RemoveRedundantKeys"), CaptureImportOptions->bRemoveRedundantKeys));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt Resample"), CaptureImportOptions->bResample));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt SetMaterialDriveParameterOnCustomAttribute"), CaptureImportOptions->bSetMaterialDriveParameterOnCustomAttribute));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt MaterialCurveSuffixes"), CaptureImportOptions->MaterialCurveSuffixes));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt ResampleRate"), CaptureImportOptions->ResampleRate));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("AnimOpt SnapToClosestFrameBoundary"), CaptureImportOptions->bSnapToClosestFrameBoundary));

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportOptionsSkeletalMesh.cpp:32

Scope (from outer to inner):

file
function     UFbxSceneImportOptionsSkeletalMesh::UFbxSceneImportOptionsSkeletalMesh

Source code excerpt:

	, bDeleteExistingCustomAttributeCurves(false)
	, bDeleteExistingNonCurveCustomAttributes(false)
	, bPreserveLocalTransform(false)
	, bDeleteExistingMorphTargetCurves(false)
{
}

void UFbxSceneImportOptionsSkeletalMesh::FillSkeletalMeshInmportData(UFbxSkeletalMeshImportData* SkeletalMeshImportData, UFbxAnimSequenceImportData* AnimSequenceImportData, UFbxSceneImportOptions* SceneImportOptions)
{

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportOptionsSkeletalMesh.cpp:68

Scope (from outer to inner):

file
function     void UFbxSceneImportOptionsSkeletalMesh::FillSkeletalMeshInmportData

Source code excerpt:

	AnimSequenceImportData->bDeleteExistingCustomAttributeCurves = bDeleteExistingCustomAttributeCurves;
	AnimSequenceImportData->bDeleteExistingNonCurveCustomAttributes = bDeleteExistingNonCurveCustomAttributes;
	AnimSequenceImportData->bPreserveLocalTransform = bPreserveLocalTransform;
	AnimSequenceImportData->bUseDefaultSampleRate = bUseDefaultSampleRate;
	AnimSequenceImportData->CustomSampleRate = CustomSampleRate;
	AnimSequenceImportData->FrameImportRange = FrameImportRange;

	AnimSequenceImportData->bImportAsScene = true;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/SFbxSceneOptionWindow.cpp:1512

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopySkeletalMeshOptionsToFbxOptions

Source code excerpt:

	ImportSettings->bDeleteExistingCustomAttributeCurves = SkeletalMeshOptions->bDeleteExistingCustomAttributeCurves;
	ImportSettings->bDeleteExistingNonCurveCustomAttributes = SkeletalMeshOptions->bDeleteExistingNonCurveCustomAttributes;	
	ImportSettings->bPreserveLocalTransform = SkeletalMeshOptions->bPreserveLocalTransform;
	ImportSettings->bResample = !SkeletalMeshOptions->bUseDefaultSampleRate;
	ImportSettings->ResampleRate = SkeletalMeshOptions->CustomSampleRate;
	ImportSettings->bSnapToClosestFrameBoundary = SkeletalMeshOptions->bSnapToClosestFrameBoundary;	
	ImportSettings->AnimationRange.X = SkeletalMeshOptions->FrameImportRange.Min;
	ImportSettings->AnimationRange.Y = SkeletalMeshOptions->FrameImportRange.Max;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/SFbxSceneOptionWindow.cpp:1541

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopyFbxOptionsToSkeletalMeshOptions

Source code excerpt:

	SkeletalMeshOptions->bDeleteExistingCustomAttributeCurves = ImportSettings->bDeleteExistingCustomAttributeCurves;
	SkeletalMeshOptions->bDeleteExistingNonCurveCustomAttributes = ImportSettings->bDeleteExistingNonCurveCustomAttributes;	
	SkeletalMeshOptions->bPreserveLocalTransform = ImportSettings->bPreserveLocalTransform;
	SkeletalMeshOptions->bUseDefaultSampleRate = !ImportSettings->bResample;
	SkeletalMeshOptions->CustomSampleRate = ImportSettings->ResampleRate;
	SkeletalMeshOptions->FrameImportRange.Min = ImportSettings->AnimationRange.X;
	SkeletalMeshOptions->FrameImportRange.Max = ImportSettings->AnimationRange.Y;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SkeletalMeshEdit.cpp:2142

Scope (from outer to inner):

file
function     void UnFbx::FFbxImporter::ImportBoneTracks

Source code excerpt:

	OutTotalNumKeys = 0;
	UnFbx::FFbxImporter* FbxImporter = UnFbx::FFbxImporter::GetInstance();
	const bool bPreserveLocalTransform = FbxImporter->GetImportOptions()->bPreserveLocalTransform;

	UAnimSequence* DestSeq = AnimImportSettings.DestSeq;
	const FbxTimeSpan& AnimTimeSpan = AnimImportSettings.AnimTimeSpan;
	const bool bShouldTransact = bReimport;

	// Build additional transform matrix

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SkeletalMeshEdit.cpp:2240

Scope (from outer to inner):

file
function     void UnFbx::FFbxImporter::ImportBoneTracks

Source code excerpt:


				FTransform LocalTransform;
				if (!bPreserveLocalTransform && LinkParent)
				{
					// I can't rely on LocalMatrix. I need to recalculate quaternion/scale based on global transform if Parent exists
					FbxAMatrix ParentGlobalMatrix = Link->GetParent()->EvaluateGlobalTransform(CurTime);
					if (BoneTreeIndex != 0)
					{
						ParentGlobalMatrix = ParentGlobalMatrix * FFbxDataConverter::GetJointPostConversionMatrix();

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Public/FbxImporter.h:195

Scope (from outer to inner):

file
namespace    UnFbx

Source code excerpt:

	FIntPoint AnimationRange;
	FString AnimationName;
	bool	bPreserveLocalTransform;
	bool	bDeleteExistingMorphTargetCurves;
	bool	bImportCustomAttribute;
	bool	bDeleteExistingCustomAttributeCurves;
	bool	bDeleteExistingNonCurveCustomAttributes;
	bool	bImportBoneTracks;
	bool	bSetMaterialDriveParameterOnCustomAttribute;