Editor Customization

The Texturge editor achieves deep customization through IDetailCustomization, IPropertyTypeCustomization, FKismetCompilerContext extensions, and templated parameter helpers.

FAnimatedTextBlockDetails

Provides a custom Details panel for the UAnimatedTextBlock widget (IDetailCustomization).

class FAnimatedTextBlockDetails : public IDetailCustomization
{
    static TSharedRef<IDetailCustomization> MakeInstance();
    void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;

private:
    void BuildParameterRows(IDetailCategoryBuilder& AnimCat,
                            IDetailLayoutBuilder& DetailBuilder,
                            UAnimatedTextBlock* Widget,
                            TSharedPtr<IPropertyHandle> OverridesHandle);
    void SaveAllCDODefaults(UTextAnimInstance* CDO);
    UTextAnimInstance* GetTargetCDO() const;
    static bool IsUserParameter(FProperty* Prop);

    TWeakObjectPtr<UAnimatedTextBlock> TargetWidget;
    TMap<FName, TArray<uint8>> CDODefaultsForReset;
};

Parameter Row Generation Mechanism

  1. Attach UAnimParameterOverrides’s 6 override maps into the Details panel as external object properties via AddExternalObjectProperty
  2. Enumerate all properties on the UTextAnimInstance CDO generated by the associated UTextAnimationBlueprint, filtering IsUserParameter (CPF_BlueprintVisible and not a system property) Blueprint variables
  3. Generate one row per Blueprint variable: variable name + override value input + Reset button
  4. SaveAllCDODefaults caches CDO defaults when the panel opens; Reset removes the override entry via the AnimParamReset<UAnimParameterOverrides> template and writes back the CDO copy

NOTE

CDO copy approach: the panel edits a copy of the UTextAnimInstance CDO — native engine editor behavior; the Blueprint CDO is never modified. At bake time FAnimInstanceCustomizer injects into the bake temporary instance.

FTextAnimationInstanceDetails

Provides a custom Details panel for UTextAnimInstance (IDetailCustomization), controlling category sorting only without changing the property layout.

class FTextAnimationInstanceDetails : public IDetailCustomization
{
    static TSharedRef<IDetailCustomization> MakeInstance();
    void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
};

FAnimationEntryDetails

Provides custom Details for the FAnimationEntry struct (IPropertyTypeCustomization), active in the Entries array of UTextAnimationDataAsset.

class FAnimationEntryDetails : public IPropertyTypeCustomization
{
    static TSharedRef<IPropertyTypeCustomization> MakeInstance();
    void CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle,
                         FDetailWidgetRow& HeaderRow,
                         IPropertyTypeCustomizationUtils& CustomizationUtils) override;
    void CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle,
                           IDetailChildrenBuilder& ChildBuilder,
                           IPropertyTypeCustomizationUtils& CustomizationUtils) override;

private:
    TMap<FName, TArray<uint8>> CDODefaults;
};

Like the widget panel, entry-level parameter overrides (6 maps) are edited through the CDO copy + Reset mechanism, reusing the TAnimParamTraits<T, FAnimationEntry> specializations underneath.

UTextAnimationTrackProxy

A proxy object (UObject) for editing track properties in the Details panel, wrapping FTextAnimationTrack as editable properties:

UCLASS(meta = (DisplayName = "文本动画轨道代理"))
class UTextAnimationTrackProxy : public UObject
{
    UPROPERTY(EditAnywhere, Category = "轨道", meta = (DisplayName = "轨道属性"))
    FTextAnimationTrack Track;
};

FTextAnimationBlueprintCompilerContext

Kismet compiler extension responsible for compiling UTextAnimationBlueprint into UTextAnimationBlueprintGeneratedClass.

class FTextAnimationBlueprintCompilerContext : public FKismetCompilerContext
{
    // FKismetCompilerContext overrides
    virtual void SpawnNewClass(const FString& NewClassName) override;
    virtual void CleanAndSanitizeClass(UBlueprintGeneratedClass* ClassToClean, UObject*& InOutOldCDO) override;
    virtual void EnsureProperGeneratedClass(UClass*& InOutTargetClass) override;
    virtual void CreateClassVariablesFromBlueprint() override;
    virtual void CreateFunctionList() override;
    virtual void FinishCompilingClass(UClass* Class) override;
    virtual bool ValidateGeneratedClass(UBlueprintGeneratedClass* Class) override;
    virtual void PreCompile() override;

private:
    void ValidateTrackData();   // track data integrity validation (5 rules)
    FGuid FixupVariableGUIDs(UTextAnimationBlueprint*, const FName&);
    void CopyAssetDataToClass(UTextAnimationBlueprintGeneratedClass* OutClass);
};

Compilation Pipeline

StepOverrideBehavior
1PreCompilepre-compile preparation
2CreateClassVariablesFromBlueprintensures variable injection before base class scanning (2026-07 refactor fix: variable injection moved before the base class call)
3FixupVariableGUIDsmaintains stable GUIDs for Blueprint variables (looks up VariableNameToGuidMap; if not found, generates a deterministic GUID from the path name and writes it back)
4ValidateTrackDatavalidates Tracks array integrity (5 rules)
5FinishCompilingClassCopyAssetDataToClass copies asset data such as Tracks, computing CompiledTotalDuration = max(StartTime + Duration)
6CompileCountincrements on every compile, participates in the Blueprint fingerprint hash, guaranteeing cache invalidation after compilation

Compile output is written into UTextAnimationBlueprintGeneratedClass (CompiledTracks / CompiledFrameRate / CompiledTotalDuration / CompiledCharacterInterval).

Templated Parameter Helpers

AnimParamTraitsHelpers.h (Editor module, header-only) provides 3 shared template functions:

TemplateDescription
AnimParamNeedsReset<Owner>(Ovr, PropName, EAnimParamType, DefVal)determines whether the current override value deviates from the CDO default (decides the Reset button display)
AnimParamReset<Owner>(Ovr, CDOCopy, PropName, Prop, EAnimParamType, DefVal)removes the override entry and restores the CDO copy default
AnimParamSync<Owner>(Ovr, CDOCopy, PropName, EAnimParamType)syncs CDO copy property values into the override map

The underlying mapping comes from the runtime module’s TAnimParamTraits<T, Owner> specializations (DECLARE_ANIM_PARAM_TRAIT in AnimatedTextBlock.h and DECLARE_ENTRY_TRAIT in AnimationEntry.h).

Extending Custom Details Panels

The plugin supports registering external custom Details panels:

  1. Create a class inheriting IDetailCustomization and implement CustomizeDetails(IDetailLayoutBuilder&)
  2. Register in the module’s StartupModule():
FPropertyEditorModule& PropertyModule =
    FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.RegisterCustomClassLayout(
    UYourClass::StaticClass()->GetFName(),
    FOnGetDetailCustomizationInstance::CreateStatic(&FYourDetails::MakeInstance));
  1. Call UnregisterCustomClassLayout in ShutdownModule() to unregister

All built-in Details customizations bind through the same mechanism, ensuring standardization with the engine’s Details panel.

images/editor-customization.png — Detail panel customization overview: left shows UAnimatedTextBlock property panel (TextAnimationBlueprint, ParameterOverrides with per-variable override inputs and Reset buttons), right shows UTextAnimationDataAsset Entries array editor (each FAnimationEntry with TagName, blueprint reference and six parameter override maps)