Class TextEffectBase
Base class for text effects. Owns the timing, the region, the lifecycle and the clamped write helpers, leaving subclasses to implement only what an effect actually draws.
Inheritance
Inherited Members
Namespace: Scylla.TextMode
Assembly: ScyllaTextMode.dll
Syntax
public abstract class TextEffectBase : ITextEffect, IDisposable
Remarks
Timing is a plain accumulator rather than a tween. An effect needs a per-cell progress value, computed from the global progress and that cell's threshold, so a tween's single scalar would be driving one number that then gets recomputed per cell anyway. The easing itself still comes from Core: Evaluate(EaseType, float) supplies every curve, so the whole family of easings is available without a tween instance, its pooling rules or its allocation per restart.
Subclasses implement OnEffectStart() to capture what they need, OnEffectTick(float, float) to draw a frame, and optionally OnEffectFinish(bool) and OnEffectRelease(). They write through TryPutChar(int, int, uint, Color32, Color32, CellAttributes) and TryWriteCell(int, int, in Cell), which take coordinates relative to the region and silently reject anything outside it, so an effect cannot scribble on cells it does not own even if its own arithmetic is wrong.
Properties
CellDuration
Gets or sets how much of the effect's running time each individual cell takes, from just above 0 to 1.
Declaration
public float CellDuration { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
Remarks
At 1 every cell animates for the whole duration, so the mask has no visible effect and the region changes as one. Lower values give each cell a shorter window and spread those windows out along the mask's ordering, so 0.25 means a cell animates over a quarter of the timeline while the wave of activity crosses the region. Very small values approach a hard edge sweeping across, which is what a crisp wipe wants.
CompletedLoops
Gets how many times the effect has been round so far.
Declaration
public int CompletedLoops { get; }
Property Value
| Type | Description |
|---|---|
| int |
Context
Gets the host supplying the grid, glyph cache and pooled storage. Null until the effect is handed to a player.
Declaration
protected ITextEffectContext Context { get; }
Property Value
| Type | Description |
|---|---|
| ITextEffectContext |
Delay
Gets or sets how long the effect waits before it begins advancing, in seconds. The effect writes nothing while it waits.
Declaration
public float Delay { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
DeltaSinceLastTick
Gets the scaled time in seconds that the most recent tick advanced the effect by.
Declaration
protected float DeltaSinceLastTick { get; }
Property Value
| Type | Description |
|---|---|
| float |
Remarks
Already multiplied by Speed, so an effect timing something of its own against it stays in step with the effect's own playback. Useful for work that runs on its own cadence rather than on progress, such as re-rolling scrambled glyphs a fixed number of times per second.
Duration
Gets or sets the playback duration in seconds, clamped to the supported range. A duration of zero makes the effect finish on its first tick.
Declaration
public float Duration { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
Ease
Gets or sets the easing curve applied to linear progress.
Declaration
public EaseType Ease { get; set; }
Property Value
| Type | Description |
|---|---|
| EaseType |
EasedProgress
Gets progress with the easing curve applied, which is the value most subclasses should drive their appearance from.
Declaration
protected float EasedProgress { get; }
Property Value
| Type | Description |
|---|---|
| float |
IsComplete
Gets whether the effect reached its final state. This is true after natural completion and after Skip(), and false for an effect that was stopped part-way.
Declaration
public bool IsComplete { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsRunning
Gets whether the effect has been started and has not yet finished. This stays true while the effect is waiting out a start delay and while it is paused.
Declaration
public bool IsRunning { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Loops
Gets or sets how many extra times the effect repeats. Zero plays it once, and a negative value repeats it until something stops it.
Declaration
public int Loops { get; set; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
A repeating effect never completes on its own, so nothing chained to its completion will run. That is the point for an ambient effect, which is meant to carry on until the screen it decorates goes away.
Mask
Gets or sets the ordering the effect applies across its region.
Declaration
public CellMask Mask { get; set; }
Property Value
| Type | Description |
|---|---|
| CellMask |
Remarks
Only meaningful for effects that treat their cells separately. The default reaches every cell at once, so an effect staggers only once a mask is chosen.
Name
Gets a short name identifying this effect, used in log messages and in the events it publishes. Defaults to the effect's type name.
Declaration
public string Name { get; set; }
Property Value
| Type | Description |
|---|---|
| string |
PingPong
Gets or sets whether repeats alternate forwards and backwards rather than restarting.
Declaration
public bool PingPong { get; set; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
This is what makes a repeating effect seamless. A brightness pulse that restarts jumps from its brightest back to its dimmest; running the second pass backwards instead makes it breathe.
Progress
Gets progress through the effect, from 0 at the start to 1 when finished. This is linear progress; the easing curve is applied on top of it internally.
Declaration
public float Progress { get; }
Property Value
| Type | Description |
|---|---|
| float |
Region
Gets the block of cells this effect writes to, clamped to the target grid. This resolves when the effect starts, so before then it may still be the unresolved request.
Declaration
public CellRect Region { get; }
Property Value
| Type | Description |
|---|---|
| CellRect |
RequestedRegion
Gets or sets the region this effect writes to. An empty rectangle means the whole grid, which is resolved when the effect starts.
Declaration
public CellRect RequestedRegion { get; set; }
Property Value
| Type | Description |
|---|---|
| CellRect |
ResolvedRegion
Gets the region actually written to, clamped to the grid. Valid from OnEffectStart() onward.
Declaration
protected CellRect ResolvedRegion { get; }
Property Value
| Type | Description |
|---|---|
| CellRect |
Seed
Gets or sets the seed behind the random choices an effect makes, such as the order a dissolve reaches cells in or which glyphs a scramble cycles through.
Declaration
public int Seed { get; set; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
Setting this pins the effect: every run from then on plays out identically, which is what a replay, a cutscene that must match a recording, or a test needs.
Leave it alone and each run picks a fresh seed instead, so a dissolve does not settle in the same order every time and a decode does not end on the same few characters. Randomness inside a single run is always reproducible from its seed either way; the only question is whether the next run reuses it.
Speed
Gets or sets the playback speed multiplier, clamped to the supported range. This scales the start delay as well as the duration.
Declaration
public float Speed { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
State
Gets the current lifecycle state.
Declaration
public TextEffectState State { get; }
Property Value
| Type | Description |
|---|---|
| TextEffectState |
TimeMode
Gets which clock the effect advances on, which is what the player uses to choose a delta time.
Declaration
public TextEffectTimeMode TimeMode { get; set; }
Property Value
| Type | Description |
|---|---|
| TextEffectTimeMode |
Methods
CellProgress(float, int, int)
Gets how far a single cell has progressed, given the effect's overall progress.
Declaration
protected float CellProgress(float easedProgress, int localRow, int localColumn)
Parameters
| Type | Name | Description |
|---|---|---|
| float | easedProgress | The effect's overall progress, after easing. |
| int | localRow | Row relative to the region's top edge. |
| int | localColumn | Column relative to the region's left edge. |
Returns
| Type | Description |
|---|---|
| float | Progress for that cell, from 0 to 1. |
Remarks
Each cell waits until the wave of activity reaches it, then animates over CellDuration of the timeline. A cell whose ordering value is 0 starts immediately and a cell at 1 finishes exactly as the effect does, which is why the mask normalizes its values.
CellThreshold(int, int)
Gets a cell's raw position in the mask's ordering, from 0 for the earliest to 1 for the latest.
Declaration
protected float CellThreshold(int localRow, int localColumn)
Parameters
| Type | Name | Description |
|---|---|---|
| int | localRow | Row relative to the region's top edge. |
| int | localColumn | Column relative to the region's left edge. |
Returns
| Type | Description |
|---|---|
| float | The cell's place in the ordering, or 0.5 when there is no mask to read. |
Remarks
This is the mask value itself rather than the cell's animation progress. Use it for one-off per-cell decisions, such as when a cell swaps its character, where CellProgress(float, int, int) would be wrong: at a cell duration of 1 every cell animates over the whole run, so its progress is the same everywhere and carries no ordering at all.
Dispose()
Declaration
public void Dispose()
EnsureThresholds()
Rents and fills the per-cell ordering values for the current region.
Declaration
protected void EnsureThresholds()
Remarks
Call from OnEffectStart() in any effect that staggers. The values are computed once here rather than per frame, and released by ReleaseThresholds(), which the effect must call from OnEffectRelease().
MarkRegionDirty()
Marks every row the region covers as needing a GPU upload.
Declaration
protected void MarkRegionDirty()
Remarks
Writing through TryPutChar(int, int, uint, Color32, Color32, CellAttributes) or TryWriteCell(int, int, in Cell) already marks rows, so this is only needed by effects that reach into the grid directly.
OnEffectFinish(bool)
Called when the effect finishes, whether it completed, was skipped or was stopped.
Declaration
protected virtual void OnEffectFinish(bool completed)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | completed | True when the effect reached its final state. |
Remarks
The default implementation does nothing. Override it to restore state an effect borrowed, which is what a corrupting effect needs so the grid is not left damaged.
OnEffectRelease()
Called when the effect is disposed. Return anything rented from the context here.
Declaration
protected virtual void OnEffectRelease()
OnEffectStart()
Called when the effect starts, after the region is resolved and before any tick. Capture whatever the effect needs from the grid here.
Declaration
protected abstract void OnEffectStart()
OnEffectTick(float, float)
Called once per tick to draw the effect at the given progress.
Declaration
protected abstract void OnEffectTick(float progress, float easedProgress)
Parameters
| Type | Name | Description |
|---|---|---|
| float | progress | Linear progress from 0 to 1. |
| float | easedProgress | Progress with the easing curve applied. |
Pause()
Suspends the effect, keeping its progress and everything it has written so far.
Declaration
public void Pause()
ReleaseThresholds()
Returns the per-cell ordering values to the context.
Declaration
protected void ReleaseThresholds()
ResolveDrawableGlyphs(string)
Reduces a set of candidate characters to those the current font can actually draw.
Declaration
protected uint[] ResolveDrawableGlyphs(string candidates)
Parameters
| Type | Name | Description |
|---|---|---|
| string | candidates | The characters the effect would like to use. |
Returns
| Type | Description |
|---|---|
| uint[] | The codepoints from that set which are safe to draw. |
Remarks
Only the primary atlas page is bound when the grid is rendered, so a character living on another page would be drawn as whatever happens to sit at those coordinates on the first one. Any effect picking characters at random has to filter its set, or it will occasionally show nonsense.
The check is skipped when no font has been loaded, since then every character would be reported missing and the warning would be noise. A set with nothing usable falls back to a space, which at least looks deliberate.
Resume()
Resumes a paused effect from where it left off.
Declaration
public void Resume()
SetDefaultMask(in CellMask)
Supplies a default mask for an effect whose documented behavior is a non-uniform ordering, without overriding a mask the caller chose.
Declaration
protected void SetDefaultMask(in CellMask mask)
Parameters
| Type | Name | Description |
|---|---|---|
| CellMask | mask | The ordering to use when the caller did not pick one. |
Skip()
Jumps straight to the finished state, writing the final result into the grid.
Declaration
public void Skip()
Remarks
This is what a "press any key to skip" control should call, because it leaves the screen looking as though the effect had played out and still raises OnCompleted, so anything chained off completion still runs.
Start()
Starts the effect, or restarts it from the beginning if it already ran.
Declaration
public void Start()
Remarks
Starting captures whatever the effect needs from the target grid, so the grid must already hold the content the effect works from. A typewriter captures nothing, but a fade or a transition captures the region as it looks right now.
Stop()
Stops the effect before it finishes, leaving the grid exactly as it looks at this moment.
Declaration
public void Stop()
Tick(float)
Advances the effect by one step and writes the resulting cells.
Declaration
public void Tick(float deltaTime)
Parameters
| Type | Name | Description |
|---|---|---|
| float | deltaTime | Seconds elapsed since the previous tick. |
TryPutChar(int, int, uint, Color32, Color32, CellAttributes)
Writes a character into the region, stamping it with glyph atlas data.
Declaration
protected bool TryPutChar(int localRow, int localColumn, uint codepoint, Color32 foreground, Color32 background, CellAttributes attributes = CellAttributes.None)
Parameters
| Type | Name | Description |
|---|---|---|
| int | localRow | Row relative to the region's top edge. |
| int | localColumn | Column relative to the region's left edge. |
| uint | codepoint | Unicode codepoint to write. |
| Color32 | foreground | Foreground color. |
| Color32 | background | Background color. |
| CellAttributes | attributes | Cell attributes to apply. |
Returns
| Type | Description |
|---|---|
| bool | True if the cell was written, false if the coordinate lies outside the region. |
Remarks
Coordinates are relative to the region's top-left corner, and anything outside the region is rejected rather than clamped, so an off-by-one in an effect shows up as a missing cell instead of corrupting a neighbor.
TryReadCell(int, int, out Cell)
Reads a cell from the region without modifying it.
Declaration
protected bool TryReadCell(int localRow, int localColumn, out Cell cell)
Parameters
| Type | Name | Description |
|---|---|---|
| int | localRow | Row relative to the region's top edge. |
| int | localColumn | Column relative to the region's left edge. |
| Cell | cell | The cell that was read, or a default cell when the coordinate is outside the region. |
Returns
| Type | Description |
|---|---|
| bool | True if the coordinate lies inside the region and the cell was read. |
Remarks
Useful for checking whether a cell still holds what this effect last wrote there. Nothing stops another effect, or game code, from writing into a region while an effect owns it, so an effect that erases its own decorations should confirm they are still present rather than blanking whatever it finds.
TryWriteCell(int, int, in Cell)
Writes a whole cell into the region, preserving its already-stamped glyph data.
Declaration
protected bool TryWriteCell(int localRow, int localColumn, in Cell cell)
Parameters
| Type | Name | Description |
|---|---|---|
| int | localRow | Row relative to the region's top edge. |
| int | localColumn | Column relative to the region's left edge. |
| Cell | cell | The cell to write. |
Returns
| Type | Description |
|---|---|
| bool | True if the cell was written, false if the coordinate lies outside the region. |
Remarks
This is the fast path for effects that move or recolor content they captured earlier, because a captured cell already carries its atlas and metrics fields and needs no glyph cache lookup.
WarnIfMaskIsIgnored()
Warns when a caller assigned a mask to an effect that does not consult one.
Declaration
protected void WarnIfMaskIsIgnored()
Remarks
Mask and CellDuration are inherited by every effect, but only effects
that call EnsureThresholds and read CellProgress act on them. Setting one
on an effect that does not is silent and does nothing, which is a trap for anyone
reading the shared surface and assuming it applies uniformly. Called from the start
hook of the effects that ignore it, so the warning appears only when something was
actually set.
Events
OnCompleted
Raised when the effect reaches its final state, either by running out its duration or through Skip().
Declaration
public event Action OnCompleted
Event Type
| Type | Description |
|---|---|
| Action |
OnStarted
Raised when the effect begins advancing, after any start delay has elapsed.
Declaration
public event Action OnStarted
Event Type
| Type | Description |
|---|---|
| Action |
OnStopped
Raised when the effect is stopped before reaching its final state.
Declaration
public event Action OnStopped
Event Type
| Type | Description |
|---|---|
| Action |