EffectSettings
EffectSettings is the mutable state object that represents how a single character will be rendered. It is created fresh for each character and passed sequentially through every effect applied to that character’s span.
Package: net.tysontheember.emberstextapi.immersivemessages.effects
Position and Transform
Section titled “Position and Transform”| Field | Type | Default | Description |
|---|---|---|---|
x | float | 0.0 | Horizontal pixel offset from the character’s natural position |
y | float | 0.0 | Vertical pixel offset |
rot | float | 0.0 | Rotation angle in radians |
scale | float | 1.0 | Scale multiplier |
Effects modify these to move, rotate, or resize individual characters.
Color and Transparency
Section titled “Color and Transparency”| Field | Type | Default | Description |
|---|---|---|---|
r | float | 1.0 | Red channel (0.0–1.0) |
g | float | 1.0 | Green channel (0.0–1.0) |
b | float | 1.0 | Blue channel (0.0–1.0) |
a | float | 1.0 | Alpha / opacity (0.0 = invisible, 1.0 = fully opaque) |
Color effects (rainbow, gradient) write r, g, b. Transparency effects (fade, typewriter) write a.
Character Context (Read-Only)
Section titled “Character Context (Read-Only)”These fields provide information about the character being rendered. Effects read these but should not modify them.
| Field | Type | Description |
|---|---|---|
index | int | Character index within the current span (0-based) |
absoluteIndex | int | Global character index across all spans in the message |
codepoint | int | Unicode codepoint of the character |
isShadow | boolean | true if this is the shadow rendering pass |
shadowOffset | float | Distance between shadow and main text |
Animation State
Section titled “Animation State”| Field | Type | Description |
|---|---|---|
typewriterTrack | TypewriterTrack | Active typewriter animation state (package: effects.animation) |
typewriterIndex | int | Global position offset for typewriter ordering |
obfuscateKey | Object | Cache key for obfuscation tracking |
obfuscateStableKey | Object | Stable cache key (for tooltips that re-render) |
obfuscateTrack | ObfuscateTrack | Active obfuscation animation state |
obfuscateSpanStart | int | Span-local start index |
obfuscateSpanLength | int | Span-local length |
useRandomGlyph | boolean | If true, render a random glyph instead of the real character |
Multi-Layer Support (Siblings)
Section titled “Multi-Layer Support (Siblings)”Some effects (neon, glitch) render additional character layers — glow rings, displaced slices, chromatic fringes. They do this by adding “sibling” EffectSettings objects.
/** Get or create the siblings list (lazy initialization). */List<EffectSettings> getSiblings()
/** Add a sibling layer. */void addSibling(EffectSettings sibling)
/** Check if any siblings were added (without creating the list). */boolean hasSiblings()
/** Safe iteration — returns empty list if no siblings (does NOT create the list). */List<EffectSettings> getSiblingsOrEmpty()Each sibling is rendered as an additional glyph pass after the main character.
Vertical Masking
Section titled “Vertical Masking”| Field | Type | Default | Description |
|---|---|---|---|
maskTop | float | 0.0 | Fraction of the character masked from the top (0.0 = nothing masked) |
maskBottom | float | 0.0 | Fraction masked from the bottom |
Used by glitch effects to split characters into horizontal bands.
Utility Methods
Section titled “Utility Methods”/** Create a deep copy of this settings object. */EffectSettings copy()
/** Reset position, color, and transform to defaults (preserves context fields). */void reset()
/** Clamp all RGBA values to the 0.0–1.0 range. */void clampColors()
/** Get the packed ARGB color as an integer. */int getPackedColor()How Effects Use EffectSettings
Section titled “How Effects Use EffectSettings”A concrete example — the wave effect:
public class WaveEffect extends BaseEffect { private final float amplitude; private final float frequency;
public WaveEffect(Params params) { super(params); this.amplitude = params.getDouble("a").map(Number::floatValue).orElse(1.0f); this.frequency = params.getDouble("f").map(Number::floatValue).orElse(1.0f); }
@Override public void apply(EffectSettings settings) { // Read: character index (for phase offset between characters) float phase = settings.index * 0.2f;
// Read: current time float time = Util.getMillis() * 0.002f * frequency;
// Write: vertical offset settings.y += Math.sin(time + phase) * amplitude; }}The effect reads index for phase offset and writes y for displacement. It leaves color, alpha, and rotation unchanged.
Shadow Layer
Section titled “Shadow Layer”Effects that should not modify the shadow pass check isShadow:
@Overridepublic void apply(EffectSettings settings) { if (settings.isShadow) { return; // Skip shadow — shadows keep their original color/position } // ... modify settings normally}Color effects (rainbow, gradient, color) all skip the shadow layer.
Creating Sibling Layers
Section titled “Creating Sibling Layers”For effects that need to render additional copies of a character:
@Overridepublic void apply(EffectSettings settings) { // Create a glow layer EffectSettings glow = settings.copy(); glow.r = 1.0f; glow.g = 1.0f; glow.b = 1.0f; glow.a *= 0.3f; // Semi-transparent glow.scale *= 1.2f; // Slightly larger
settings.addSibling(glow);
// Main character renders with original settings (unchanged)}Siblings are rendered after the main character.