Raxol. Effects. BorderBeam. Effect behaviour
(Raxol v2.6.0)
View Source
Contract + shared helpers for border-effect implementations.
Each effect (Stroke, Pulse, Flames, Electric, Clouds) implements
apply/4, taking a cell map, the box bounds, the hint opts, and the
current monotonic time in milliseconds. Effects return a new cell map
with style and/or character mutations applied.
Cell representation
A cell_map is %{{x, y} => {x, y, char, fg, bg, attrs}} -- the same
six-tuple shape produced by Raxol.UI.Renderer, indexed by coordinate
for O(1) modification. Raxol.Effects.BorderBeam.CellApplier builds the
index, dispatches to the effect by :type, and unrolls back to a list.
Time-based determinism
Animation progress is derived from now_ms only. No effect maintains
state between calls; the same now_ms always produces the same output
for a given hint+bounds. For random-looking effects (flames, electric),
use time_bucket/2 + bucket_hash/3 to produce reproducible-per-tick
noise.
Summary
Callbacks
Apply the effect to the cell map.
Functions
Reproducible non-negative integer hash from a {bucket, x, y} triple.
Use to drive char/color choices that should be stable within a bucket
but vary across cells and time.
Maps an intensity (0.0-1.0) to terminal style attrs. :bold for bright,
plain for mid-range, :dim for low. Strips any pre-existing intensity
attrs so re-applying is idempotent.
Returns the perimeter as a tuple for O(1) elem/2 access. Order is
clockwise from the top-left corner: top edge, right edge, bottom edge
(right-to-left), left edge (bottom-to-top).
Replace the character, foreground, and intensity attrs of a cell.
Replace the foreground color and intensity attrs of a cell.
Returns a discrete time bucket for the given millisecond clock and
bucket size. Used to keep random-but-deterministic effects stable for
~bucket_ms between changes.
Types
@type bounds() :: %{ x: non_neg_integer(), y: non_neg_integer(), width: pos_integer(), height: pos_integer() }
@type cell() :: {non_neg_integer(), non_neg_integer(), String.t(), any(), any(), list()}
@type cell_map() :: %{required({non_neg_integer(), non_neg_integer()}) => cell()}
Callbacks
@callback apply( cells :: cell_map(), bounds :: bounds(), opts :: map(), now_ms :: integer() ) :: cell_map()
Apply the effect to the cell map.
cellsis the keyed cell index produced byCellApplier.boundsare the positioned box dimensions.optsis the raw hint map (:variant,:strength, plus per-effect keys).now_msis the monotonic millisecond clock at frame time.
Functions
@spec bucket_hash(integer(), integer(), integer()) :: non_neg_integer()
Reproducible non-negative integer hash from a {bucket, x, y} triple.
Use to drive char/color choices that should be stable within a bucket
but vary across cells and time.
Maps an intensity (0.0-1.0) to terminal style attrs. :bold for bright,
plain for mid-range, :dim for low. Strips any pre-existing intensity
attrs so re-applying is idempotent.
Empty-attrs fast path skips the Enum.reject allocation, which is the
vast majority of cells in a freshly rendered border.
@spec perimeter(bounds()) :: {tuple(), pos_integer()}
Returns the perimeter as a tuple for O(1) elem/2 access. Order is
clockwise from the top-left corner: top edge, right edge, bottom edge
(right-to-left), left edge (bottom-to-top).
Replace the character, foreground, and intensity attrs of a cell.
Used by char-replacing effects (flames, electric). No-op if the cell does not exist.
Replace the foreground color and intensity attrs of a cell.
Returns the cell map unchanged if no cell exists at {x, y}.
@spec time_bucket(integer(), pos_integer()) :: integer()
Returns a discrete time bucket for the given millisecond clock and
bucket size. Used to keep random-but-deterministic effects stable for
~bucket_ms between changes.