This is documentation for EmbersTextAPI 2.9.4. View the latest version

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


FieldTypeDefaultDescription
xfloat0.0Horizontal pixel offset from the character’s natural position
yfloat0.0Vertical pixel offset
rotfloat0.0Rotation angle in radians
scalefloat1.0Scale multiplier

Effects modify these to move, rotate, or resize individual characters.


FieldTypeDefaultDescription
rfloat1.0Red channel (0.0–1.0)
gfloat1.0Green channel (0.0–1.0)
bfloat1.0Blue channel (0.0–1.0)
afloat1.0Alpha / opacity (0.0 = invisible, 1.0 = fully opaque)

Color effects (rainbow, gradient) write r, g, b. Transparency effects (fade, typewriter) write a.


These fields provide information about the character being rendered. Effects read these but should not modify them.

FieldTypeDescription
indexintCharacter index within the current span (0-based)
absoluteIndexintGlobal character index across all spans in the message
codepointintUnicode codepoint of the character
isShadowbooleantrue if this is the shadow rendering pass
shadowOffsetfloatDistance between shadow and main text

FieldTypeDescription
typewriterTrackTypewriterTrackActive typewriter animation state (package: effects.animation)
typewriterIndexintGlobal position offset for typewriter ordering
obfuscateKeyObjectCache key for obfuscation tracking
obfuscateStableKeyObjectStable cache key (for tooltips that re-render)
obfuscateTrackObfuscateTrackActive obfuscation animation state
obfuscateSpanStartintSpan-local start index
obfuscateSpanLengthintSpan-local length
useRandomGlyphbooleanIf true, render a random glyph instead of the real character

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.


FieldTypeDefaultDescription
maskTopfloat0.0Fraction of the character masked from the top (0.0 = nothing masked)
maskBottomfloat0.0Fraction masked from the bottom

Used by glitch effects to split characters into horizontal bands.


/** 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()

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.


Effects that should not modify the shadow pass check isShadow:

@Override
public 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.


For effects that need to render additional copies of a character:

@Override
public 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.