Multi-Layer Animation Setup
Texturge’s multi-layer system lets every glyph own multiple independent sets of animation curve data (FPerLayerCurves), with each layer combined into the final glyph animation state according to the specified ETextAnimationBlendMode.
NOTE
Texturge has no SDF threshold or pixel layer concepts. Multi-layer means multi-layer stacking and blending of the 21-channel curve data (Override / Additive / Multiply / CrossFade).
Core Concepts
- Each
FBakedGlyphinternally storesTArray<FPerLayerCurves> LayerCurves— the curve data of each layer for that glyph (LayerCurves[0]bottom →LayerCurves[N-1]top) FBakedGlyph::Evaluate()starts fromFGlyphAnimationState::Identity()and evaluates layers in order, combining perBlendMode; empty channels are skipped, preserving existing values- Layers do not affect each other: each layer owns a deep copy of the
UGlyphAnimationcurves (ExtractCurvesruns at creation), so sharing one asset across layers causes no interference
Creating Layer Assets
UGlyphAnimationLayer is created through static factories (animation asset and blend mode are required):
// Create from a schedule array
TArray<FGlyphScheduleInfo> Schedule = FAnimationCompiler::BuildScheduleInfos(Text);
UGlyphAnimationLayer* Layer = UGlyphAnimationLayer::CreateLayer(
AnimAsset, // UGlyphAnimation*
ETextAnimationBlendMode::Override, // blend mode (Override common for base layers)
Schedule, // schedule array
EPlayMode::Forward, // play direction (default)
1.0f, // play speed (default)
1 // loop count (default; 0 = infinite)
);
// Or create from text (schedule built automatically)
UGlyphAnimationLayer* LayerFromText = UGlyphAnimationLayer::CreateLayerFromText(
AnimAsset, Text, ETextAnimationBlendMode::Additive);
Configuring Layers
Play Mode
Layer->SetPlayMode(EPlayMode::PingPong); // play direction
Layer->SetPlayMode(EPlayMode::Forward, 2.0f, 3); // direction + speed + loop count
NOTE
EPlayModeonly has Forward / Reverse / PingPong. Looping is controlled by the third parameterNumberOfLoops(0 = infinite loop).
Scheduling (Index = -1 applies to all)
Layer->SetStartDelayAt(-1, 0.0f); // absolute start delay
Layer->SetDelayAt(-1, 0.05f); // per-glyph stagger (glyph i = 0 + i × 0.05)
Layer->SkipAt(-1); // skip all (then restore by classification)
Layer->SetSkipAnimationAt(3, false); // restore glyph 3
Layer->SetAnimationClipAt(0.1f, 0.2f); // front trim 0.1s, back trim 0.2s
Glyph Tweaks (Ordered Operation Steps)
10 properties × 5 operations (multiply / divide / add / subtract / clear steps) + clear all:
Layer->MultiplyScaleAt(0, FVector2D(1.2f, 1.2f)); // glyph 0 scale ×1.2
Layer->AddRotationAt(-1, 15.0f); // all glyphs rotation +15°
Layer->SubtractOpacityAt(2, 0.1f); // glyph 2 opacity -0.1
Layer->ClearGlyphOverridesAt(0); // clear all steps of glyph 0
Assembling the Factory
UGlyphAnimationFactory manages all layers and executes the merge bake:
// 1. Create a factory (needs a base layer + global schedule)
UGlyphAnimationFactory* Factory = UGlyphAnimationFactory::CreateFactory(BaseLayer, Schedule);
// or create from text
UGlyphAnimationFactory* FactoryFromText = UGlyphAnimationFactory::CreateFactoryFromText(BaseLayer, Text);
// 2. Add layers in order (later layers have higher priority, stack on top)
Factory->AddLayer(PositionLayer);
Factory->AddLayer(ColorAnimLayer);
Factory->AddLayer(ShadowLayer);
// 3. Run the bake (returns FBakedStage)
FBakedStage Stage = Factory->Bake();
Composing in BuildDefaultAnimation
BuildDefaultAnimation is the standard place to implement multi-layer logic. The C++ default implementation fully encapsulates the create → configure → bake flow:
FBakedStage UTextAnimInstance::BuildDefaultAnimation_Implementation(
int32 GlyphCount, const FString& Text)
{
TArray<FGlyphScheduleInfo> Schedule = BuildScheduleInfos(Text);
// Base layer: Override
UGlyphAnimationLayer* BaseLayer = CreateLayer(GlyphAnimations[0], ETextAnimationBlendMode::Override, Schedule);
BaseLayer->SetDelayAt(-1, 0.05f); // per-glyph stagger
BaseLayer->SkipAt(-1); // restore by classification (skip whitespace)
// Overlay layers: Additive
UGlyphAnimationFactory* Factory = CreateFactory(BaseLayer, Schedule);
for (int32 i = 1; i < GlyphAnimations.Num(); ++i)
{
UGlyphAnimationLayer* Layer = CreateLayer(GlyphAnimations[i], ETextAnimationBlendMode::Additive, Schedule);
Factory->AddLayer(Layer);
}
// Factory-level tweaks (applied to the final blended state)
Factory->MultiplyTranslationAt(-1, FVector2D(2.0f, 1.0f));
return Factory->Bake();
}
Final Data Shape
After baking, each FBakedGlyph contains:
FBakedGlyph
├── LayerCurves[0]: FPerLayerCurves (21 channels) + BlendMode::Override
├── LayerCurves[1]: FPerLayerCurves (21 channels) + BlendMode::Additive
├── LayerCurves[2]: FPerLayerCurves (21 channels) + BlendMode::Multiply
└── FactoryOverride: FGlyphCurveOverride (factory-level tweaks, applied once at evaluation)
At runtime FBakedGlyph::Evaluate() evaluates and combines layers in index order; FactoryOverride is applied once to the final state after all layers are blended (not per-layer stacking). Static glyphs (bIsStatic) do not get it applied.