import { D as DisplayContainer, E as EffectsHost, C as ColorValue, B as BlendMode, M as MaskFactory, a as MaskHandle, b as DestroyOptions, c as DisplaySprite, T as TextureRef, G as GraphicsContext, d as DisplayText, e as DisplayBitmapText, f as TextStyle, g as DisplaySplitText, h as DisplaySplitBitmapText, L as LayerSortFn, S as SceneRenderTree, i as GradientFill, j as TextureSliceOptions, k as DisplayAnimatedSprite, l as SceneRenderTreeProvider, m as TextureInput, n as BitmapFontHandle, N as NineSliceSprite, o as TextureResource, R as RendererAsset, p as TextureHandle, W as WebFontHandle, q as EffectScope, r as EffectHandle, s as EffectFactory, F as Filter, t as Mask } from './api-COFaMdt3.js'; export { A as Application, u as ApplicationOptions, v as BitmapFontResource, w as CanvasRect, x as CreateLayerOptions, y as CreateTextureOptions, z as Effect, H as EffectDefinition, I as EffectTarget, J as EnsureLayerOptions, K as FitMode, O as LayerDef, P as LayerSpace, Q as Particle, U as ParticleContainer, V as PointLike, X as RenderLayer, Y as RenderLayerManager, Z as RenderTargetHandle, _ as RenderTargetOptions, $ as RendererConfig, a0 as RendererFitOptions, a1 as RendererKey, a2 as RendererPlugin, a3 as SceneRenderTreeKey, a4 as SceneRenderTreeProviderKey, a5 as VirtualRect, a6 as WebFontResource, a7 as defineEffect } from './api-COFaMdt3.js'; import { InspectorFacetContributor, Component, Vec2, Vec2Like, Entity, Transform, Vec2Buffer, EasingFunction, System, Phase, EngineContext, ProcessSystem, Scene, SceneTransition, SceneTransitionContext, AssetHandle, ScopedProcessQueue } from '@yagejs/core'; import { TextOptions, Texture, Spritesheet } from 'pixi.js'; /** * Derived, read-only rendered-geometry and visibility facet for a graphical * component, computed on demand from its live display object. For a * typewriter, this reports the glyphs and bounds actually painted rather than * only the component's declared full string. * * Owned by `@yagejs/renderer`: the renderer publishes it into the Inspector * snapshot through the generic {@link InspectorFacetContributor} seam (see * {@link RenderFacetContributor}), so `@yagejs/core` stays agnostic of any * rendering concept. * * `bounds` / `visible` are the cross-cutting fields. A component reporting * richer, mode-specific state (e.g. per-glyph visibility for split text) widens * the shape via the `Extra` parameter on its own side. */ type RenderFacetSnapshot = { /** * Axis-aligned bounding box of the component's geometry, in world space (the * same coordinate space the Inspector reports for `entity.transform` — pixels, * before camera/viewport projection). Measured from the geometry itself, so a * sized-but-hidden object still reports its real box; `null` means there is no * measurable geometry at all (an empty `Graphics`, a zero-area object), NOT * that the object is hidden. Read {@link RenderFacetSnapshot.visible} for the * hidden/shown state. */ bounds: { x: number; y: number; width: number; height: number; } | null; /** * The component's own (local, non-inherited) visibility flag at snapshot * time. A hidden ancestor (e.g. a parent/layer container set invisible) is * NOT folded in — read the relevant parent separately if you need the fully * resolved on-screen state. */ visible: boolean; } & Extra; /** * Renderer-internal contract a graphical component implements to publish its * render facet. {@link RenderFacetContributor} duck-types this off each * component when building an Inspector snapshot. */ interface RenderInspectable { inspectRender(): RenderFacetSnapshot; } declare module "@yagejs/core" { interface InspectorFacets { /** * Rendered geometry (world-space bounds) + local visibility, contributed by * the renderer. `SplitTextComponent` publishes a wider * {@link import("./SplitTextComponent.js").SplitTextRenderFacet} under this * same key — cast when you need its `glyphs` / `visibleText` extras. */ render?: RenderFacetSnapshot; } } /** * Publishes each graphical component's {@link RenderFacetSnapshot} into the * Inspector snapshot via the generic facet-contributor seam. Registered by * {@link import("./RendererPlugin.js").RendererPlugin} on install and removed on * teardown — the renderer owns the "render" namespace and the policy for which * component represents an entity, keeping `@yagejs/core` free of any rendering * concept. */ declare class RenderFacetContributor implements InspectorFacetContributor { readonly namespace = "render"; /** * Duck-type the renderer-internal `inspectRender()` contract off a component. * Returns `undefined` for components that don't paint (no hook). A hook that * throws is caught by the Inspector, which omits the facet. */ inspectComponent(component: Component): RenderFacetSnapshot | undefined; /** * Surface the first painted component's facet at the entity level — the * common single-sprite/text case. `componentFacets` arrives in component * insertion order (with `undefined` gaps for non-graphical components). */ inspectEntity(componentFacets: readonly unknown[]): RenderFacetSnapshot | undefined; } /** Initial values for one transform contribution. */ interface VisualTransformModifierOptions { /** Additive offset in the render layer's coordinate space. Default: `{ x: 0, y: 0 }`. */ position?: Vec2Like; /** Additive rotation in radians. Default: `0`. */ rotation?: number; /** Multiplicative scale. A number applies to both axes. Default: `1`. */ scale?: number | Vec2Like; } /** Removable transform contribution owned by a {@link VisualModifierHost}. */ interface VisualTransformModifierHandle { /** Whether this contribution is still active. */ readonly active: boolean; /** Replace this contribution's additive position offset. */ setPosition(offset: Vec2Like): void; /** Replace this contribution's additive rotation offset. */ setRotation(radians: number): void; /** Replace this contribution's multiplicative scale factor. */ setScale(scale: number | Vec2Like): void; /** Remove only this contribution. Safe to call more than once. */ remove(): void; } /** Removable opacity contribution owned by a {@link VisualModifierHost}. */ interface VisualOpacityModifierHandle { /** Whether this contribution is still active. */ readonly active: boolean; /** Replace this contribution's multiplicative opacity factor. */ setFactor(factor: number): void; /** Remove only this contribution. Safe to call more than once. */ remove(): void; } /** Removable visibility contribution owned by a {@link VisualModifierHost}. */ interface VisualVisibilityModifierHandle { /** Whether this contribution is still active. */ readonly active: boolean; /** Replace whether this contribution permits the visual to be shown. */ setVisible(visible: boolean): void; /** Remove only this contribution. Safe to call more than once. */ remove(): void; } /** * Transient render-only contributions for one visual component. * * The host stores offsets and factors, never the component's base values. * `DisplaySystem` combines the current world transform with these values every * render, so gameplay and physics remain authoritative while modifiers are * active. */ declare class VisualModifierHost { private readonly appearanceChanged?; private readonly transforms; private readonly opacities; private readonly visibilities; private _positionOffset; private _rotationOffset; private _scaleFactor; private _opacityFactor; private _visible; private destroyed; constructor(appearanceChanged?: (() => void) | undefined); /** Combined additive position offset. */ get positionOffset(): Vec2; /** Combined additive rotation offset in radians. */ get rotationOffset(): number; /** Combined multiplicative scale factor. */ get scaleFactor(): Vec2; /** Combined multiplicative opacity factor. */ get opacityFactor(): number; /** Whether every active visibility contribution permits drawing. */ get visible(): boolean; /** Number of active contributions across every visual property. */ get size(): number; /** Whether at least one transform contribution is active. */ get hasTransformModifiers(): boolean; /** Add one independently removable transform contribution. */ addTransform(options?: VisualTransformModifierOptions): VisualTransformModifierHandle; /** Add one independently removable opacity factor. */ addOpacity(factor?: number): VisualOpacityModifierHandle; /** Add one independently removable visibility condition. */ addVisibility(visible?: boolean): VisualVisibilityModifierHandle; /** @internal Invalidates every outstanding handle during component teardown. */ _destroy(): void; private assertLive; private recomputeTransform; private recomputeOpacity; private recomputeVisibility; } /** * Pixi event-mode + pointer-consume config shared by every visual * component's `interactive` option. */ interface VisualInteractiveOptions { /** * Pixi event mode. Defaults to `"static"` when the option object is set * (interactive, no children-recurse cost). Pass `"dynamic"` for Pixi * behavior where event-mode propagates to children automatically. */ eventMode?: "static" | "dynamic"; /** When `true`, claim pointer events landing on this container. Default `false`. */ consumeOnInteraction?: boolean; } /** Options shared by all five visual components. */ interface VisualComponentOptions { /** Render layer name. Default: "default". */ layer?: string; /** Initial visibility. Default: true. */ visible?: boolean; /** Tint color. */ tint?: ColorValue; /** Alpha (opacity). Default: 1. */ alpha?: number; /** * How this object's pixels combine with what is drawn beneath it. * Default: `"inherit"` — the mode of the nearest ancestor that sets one, * which is `"normal"` unless a parent changed it. Set it explicitly to * `"normal"` inside a group that uses another mode. See {@link BlendMode} * for the modes that need `import "pixi.js/advanced-blend-modes"`. */ blendMode?: BlendMode; /** * Make the container interactive. When set, Pixi `eventMode` is configured * so it participates in pointer hit-testing — required for any * `.on("pointerdown", ...)` listener to fire. * * `consumeOnInteraction: true` additionally marks it as a UI-input surface * (via `@yagejs/core`'s consume registry), so a `pointerdown` landing on it * is auto-claimed by `@yagejs/input` — preventing the same press from also * firing gameplay action-map edges like `MouseLeft`. Default `false`: an * interactive container still propagates the action, matching the "I want * both Pixi events AND the action map" use case. */ interactive?: VisualInteractiveOptions; /** * Draw this visual after the scene's layers, outside every layer- and * scene-scope effect and mask. Default `false`. See * {@link VisualComponent.renderAboveEffects}. */ renderAboveEffects?: boolean; } /** * Shared base for the renderer's five visual components (Sprite, * AnimatedSprite, Graphics, Text, SplitText). Carries the render-layer field, * lazy effects host, mask lifecycle, scene-tree parenting, and the generic * visible/tint/alpha/interactive vocabulary — every underlying Pixi display * object supports all four directly on `Container`, so this operates on * `renderObject` rather than each subclass re-deriving the same three-liner. * * Subclasses provide `renderObject` (their concrete Pixi display object, * created in their own constructor) and call {@link applyVisualOptions} once * it exists — options can't be applied during `VisualComponent`'s own * constructor since `renderObject` isn't assigned yet at that point. */ declare abstract class VisualComponent extends Component { /** The underlying Pixi display object. */ abstract readonly renderObject: DisplayContainer; private _layerName; /** * Component-scope effects host. `.fx.addEffect(...)` attaches a filter to * this component's render object; the effect is torn down automatically * when the entity or component is destroyed. `.fx.findEffect(definition)` * recovers the handle for the first matching effect. */ readonly fx: EffectsHost; /** * Render-only transform, opacity, and visibility contributions. Modifiers * combine with the component's live base values and are never serialized. */ readonly modifiers: VisualModifierHost; private _mask; /** * The visibility the game asked for. The Pixi flag is this AND the * component being effectively enabled, so hiding a sprite by hand survives * a `setActive(false)` / `setActive(true)` cycle. */ private _userVisible; /** The alpha requested by the game, before transient opacity modifiers. */ private _userAlpha; /** See {@link renderAboveEffects}. */ private _renderAboveEffects; constructor(layer: string | undefined); /** * Apply the shared visible/tint/alpha/interactive options to * `renderObject`. Call once from the subclass constructor, after the * concrete Pixi object is created. */ protected applyVisualOptions(options: VisualComponentOptions): void; /** * Whether this visual draws after the scene's layers, outside every layer- * and scene-scope effect and mask, while keeping its logical parent * (position, alpha, visibility, camera). Screen-scope effects still cover * it, and hit testing follows the logical tree — a UI element drawn under * an escaped visual still receives the pointer first. * * Set while the visual is out of the display tree — in a subclass * constructor, or on a component not yet added — it records the flag and * applies it on add. */ get renderAboveEffects(): boolean; set renderAboveEffects(value: boolean); /** The layer this visual draws on. See {@link setLayer}. */ get layerName(): string; /** * Draw this visual on another layer. * * Called before the component reaches the display tree — in a subclass * constructor, or on a component that has not been added yet — it records * the name and nothing else. Called afterwards it detaches the render * object and re-parents it through the same resolution `onAdd` uses, so a * `SortGroupComponent` on the new layer still claims it. * * The visual joins its new parent last, which on a layer with no `sort` * means it draws in front of everything already there. */ setLayer(name: string): void; /** Set the container's tint color. */ set tint(color: ColorValue); /** Get the container's tint color. */ get tint(): number; /** Set the container's alpha (opacity). */ set alpha(alpha: number); /** Get the requested alpha before transient opacity modifiers. */ get alpha(): number; /** Set how the container combines with what is drawn beneath it. */ set blendMode(mode: BlendMode); /** Get the container's blend mode. */ get blendMode(): BlendMode; /** * Set the container's visibility. Written while the entity is dormant, it * is remembered and applied when the entity is activated. */ set visible(value: boolean); /** Get the requested visibility, whatever the entity's activeness. */ get visible(): boolean; /** * Attach a mask to this component's render object, replacing any existing * mask. Returns a handle for inverse toggling, redraw (graphicsMask), or * removal. The mask is torn down automatically when the component is * destroyed. */ setMask(factory: MaskFactory): MaskHandle; /** Detach and destroy the current mask, if any. */ clearMask(): void; /** The currently attached mask handle, if any. */ get mask(): MaskHandle | undefined; /** * Derived render facet for the Inspector — world-space `bounds` and the * component's own (local, non-inherited) `visible` flag, computed on * demand from the live render object. See {@link computeRenderFacet} for * the bounds coordinate space. */ inspectRender(): RenderFacetSnapshot; onAdd(): void; onEnable(): void; onDisable(): void; onDestroy(): void; /** * Pixi destroy options passed to `renderObject.destroy()`. Default: * `undefined` (Pixi's own defaults). Override for a component whose * destroy must cascade to children (SplitText's per-segment display * objects). */ protected destroyOptions(): DestroyOptions | undefined; /** Apply the final alpha after transient modifiers. */ protected applyEffectiveAlpha(alpha: number): void; private applyAppearance; } /** Options for creating a SpriteComponent. */ interface SpriteComponentOptions extends VisualComponentOptions { /** * Texture asset key or typed handle. Runtime-created textures are * referenced by registering them under a key first (`registerTexture`). */ texture: TextureRef; /** Anchor point (0-1). */ anchor?: { x: number; y: number; }; } /** Component that displays a PixiJS Sprite. */ declare class SpriteComponent extends VisualComponent { readonly sprite: DisplaySprite; constructor(options: SpriteComponentOptions); /** The underlying Pixi display object. */ get renderObject(): DisplaySprite; /** Replace the sprite's texture. */ setTexture(texture: TextureRef): void; } /** Options for creating a GraphicsComponent. */ interface GraphicsComponentOptions extends VisualComponentOptions { /** * The point of the drawing that sits on the entity position, in the * drawing's own pixels. Rotation and scale turn the drawing about it. * Default `{ x: 0, y: 0 }`, the origin the `draw` callback draws around. * The other visual components take `anchor` for the same purpose, as a * fraction of the texture; a drawing has no texture size to take a fraction * of, so this is in pixels. */ pivot?: Vec2Like; } /** Component that wraps a PixiJS Graphics object for procedural drawing. */ declare class GraphicsComponent extends VisualComponent { readonly graphics: GraphicsContext; constructor(options?: GraphicsComponentOptions); /** The underlying Pixi display object. */ get renderObject(): GraphicsContext; /** Execute a drawing function on the graphics object. Returns this for chaining. */ draw(fn: (g: GraphicsContext) => void): this; } /** Options for creating a TextComponent. */ interface TextComponentOptions extends VisualComponentOptions { /** The text string to render. */ text: string; /** Text style — forwards to PixiJS TextStyleOptions (CSS-like font properties). */ style?: TextStyle; /** * Render with a bitmap font instead of canvas-rasterised `Text` — the * pixel-art escape hatch that stays crisp at non-integer scale. Pixi bakes * or looks up the glyph atlas from `style.fontFamily` (the name an * {@link installBitmapFont} call registered, or any font for a dynamic * bake) at `style.fontSize`. */ bitmap?: boolean; /** * Per-text render resolution. Mirrors the Pixi v8 `Text` constructor * option — note `resolution` is NOT a `TextStyle` property in v8, so * setting it here is the only way to get crisp canvas text without a * prototype patch. Ignored when `bitmap` is set (bitmap resolution is * fixed at font-bake time). */ resolution?: number; /** Anchor point (0-1). Default: { x: 0, y: 0 } (top-left). */ anchor?: { x: number; y: number; }; } /** Component that displays text on a render layer. */ declare class TextComponent extends VisualComponent { readonly text: DisplayText | DisplayBitmapText; private _styleOptions?; private _bitmap?; constructor(options: TextComponentOptions); /** The underlying Pixi display object. */ get renderObject(): DisplayText | DisplayBitmapText; /** * The string currently displayed. {@link text} is the Pixi display object, * so this is the way to read the rendered string back — including from the * Inspector, which reflects public getters but skips the display object. */ get content(): string; /** Replace the displayed string. */ setText(value: string): void; /** * Replace the text style. Unset properties fall back to the engine default * (then Pixi's), so this is a full replace, not a patch — to change a few * properties while keeping the rest, use {@link mergeStyle}. */ setStyle(style: TextStyle): void; /** * Patch the current style: merge `style` over the properties already set * (construction or a prior `setStyle`/`mergeStyle`) and re-apply. Unlike * {@link setStyle}, properties you don't pass are preserved — handy for an * imperative recolour (`mergeStyle({ fill })`) that keeps the font, size, * weight, etc. */ mergeStyle(style: TextStyle): void; } /** * Renderer-specific extras `SplitTextComponent.inspectRender()` attaches on * top of the shared {@link RenderFacetSnapshot} base. Lets a typewriter reveal * be observed purely through the Inspector — `glyphs[i].visible` mirrors the * per-character display objects, and `visibleText` is the currently-painted * substring (whitespace-stripped: Pixi treats spaces as separators between * `words`/`lines`, not as `chars`, so a fully-revealed `"Hello world"` reports * `"Helloworld"`). */ interface SplitTextRenderFacetExtras { glyphs: Array<{ visible: boolean; }>; visibleText: string; } /** The full render facet shape returned by {@link SplitTextComponent.inspectRender}. */ type SplitTextRenderFacet = RenderFacetSnapshot; /** * Transform origin for a text segment, normalized 0–1. `0` is top-left, `0.5` * is center, `1` is bottom-right. A single number applies to both axes. */ type SegmentAnchor = number | { x: number; y: number; }; /** Options for creating a {@link SplitTextComponent}. */ interface SplitTextComponentOptions extends VisualComponentOptions { /** The text string to render and segment. */ text: string; /** Text style — forwards to PixiJS TextStyleOptions (CSS-like font properties). */ style?: TextStyle; /** * Transform origin for the whole text block, normalized 0–1. * Default: { x: 0, y: 0 } (top-left). */ anchor?: { x: number; y: number; }; /** * Render the segments with a bitmap font (`SplitBitmapText`) instead of * canvas `Text` (`SplitText`). Pass the installed/baked font name as * `style.fontFamily` (and glyph size as `style.fontSize`). */ bitmap?: boolean; /** Transform origin for each character. Default `0` (top-left). */ charAnchor?: SegmentAnchor; /** Transform origin for each word. Default `0` (top-left). */ wordAnchor?: SegmentAnchor; /** Transform origin for each line. Default `0` (top-left). */ lineAnchor?: SegmentAnchor; /** * Re-split automatically when `text` / `style` change. Default `true`. * Set `false` and call {@link SplitTextComponent.resplit} to batch updates. */ autoSplit?: boolean; } /** * Displays text split into per-character / per-word / per-line display * objects, for animated and rich text — typewriter reveals, per-letter * colour / wave, staggered line entrances. Wraps Pixi v8's `SplitText` * (canvas) / `SplitBitmapText` (bitmap); the segments are exposed as * {@link SplitTextComponent.chars}, {@link SplitTextComponent.words}, and * {@link SplitTextComponent.lines} for the game to animate directly. * * For static or simple dynamic strings prefer {@link TextComponent} — a single * display object is cheaper and `SplitText` re-layout on every `text` change is * not free. * * @experimental Pixi marks `SplitText` experimental; its char spacing can * differ slightly from `Text` (browser kerning is lost once glyphs are split). */ declare class SplitTextComponent extends VisualComponent { /** The underlying Pixi `SplitText` / `SplitBitmapText` container. */ readonly splitText: DisplaySplitText | DisplaySplitBitmapText; /** Whether this renders with a bitmap font (`SplitBitmapText`). */ readonly isBitmap: boolean; private _bitmap?; private _anchor?; private readonly _autoSplit; constructor(options: SplitTextComponentOptions); /** The underlying Pixi display object. */ get renderObject(): DisplaySplitText | DisplaySplitBitmapText; /** Individual character segments (`Text` or `BitmapText`), in reading order. */ get chars(): (DisplayText | DisplayBitmapText)[]; /** Word-group containers, each holding its character segments. */ get words(): DisplayContainer[]; /** Line-group containers, each holding its word containers. */ get lines(): DisplayContainer[]; /** * Replace the displayed string (re-splits when `autoSplit` is on). An empty * string renders nothing and leaves the segments empty. */ setText(value: string): void; /** * The string currently displayed. {@link splitText} is the Pixi display * object, so this is the way to read the rendered string back — including * from the Inspector, which reflects public getters but skips display * objects. */ get content(): string; /** Replace the text style (re-splits when `autoSplit` is on). */ setStyle(style: TextStyle): void; /** * Re-split now. Only needed when constructed with `autoSplit: false` — after * mutating `text` / `style`, call this to apply the change in one pass. */ resplit(): void; /** Transform origin for each character (normalized 0–1). */ set charAnchor(anchor: SegmentAnchor); get charAnchor(): SegmentAnchor; /** Transform origin for each word (normalized 0–1). */ set wordAnchor(anchor: SegmentAnchor); get wordAnchor(): SegmentAnchor; /** Transform origin for each line (normalized 0–1). */ set lineAnchor(anchor: SegmentAnchor); get lineAnchor(): SegmentAnchor; private applyBlockAnchor; /** * Derived render facet for the Inspector. Beyond the shared world-space * `bounds` and container-level `visible`, this walks the per-character * segments and reports `glyphs` (one `{ visible }` per char in reading * order) plus `visibleText` — the substring currently painted. This is the * read-only window into a typewriter reveal: `visibleText` reports only the * glyphs whose `chars[i].visible` is still on. See {@link computeRenderFacet} * for the bounds coordinate space. * * Note: Pixi's `chars` array (and therefore `glyphs` / `visibleText`) * contains only the rendered glyph segments — whitespace is laid out via * `words`/`lines` and is NOT a char. So `visibleText` strips spaces: a fully * revealed `"Hello world"` reports `"Helloworld"`. Use it to compare *which * glyphs* are on screen, not to reconstruct the original string verbatim. */ inspectRender(): SplitTextRenderFacet; /** * `{ children: true }` so the per-line / word / char display objects that * `split()` parented are destroyed too (not freed by the default destroy). */ protected destroyOptions(): DestroyOptions; } /** * Contract a single-display-object visual component satisfies: a layer name * plus the Pixi object it renders. All five built-in visual components * (`SpriteComponent`, `GraphicsComponent`, `AnimatedSpriteComponent`, * `TextComponent`, `SplitTextComponent`) expose it through their `renderObject` * getter, and `SortGroupComponent` uses it to gather a subtree's visuals * without importing the concrete classes (which would create an import cycle). * * It's also the extension point for custom visual components: implement * `renderObject` + `layerName`, and route through {@link resolveRenderParent} * in `onAdd`, and the component takes part in sort groups exactly like the * built-ins. */ interface LayerRenderable { /** Name of the layer this component renders into. */ readonly layerName: string; /** The underlying Pixi display object. */ readonly renderObject: DisplayContainer; } /** * Resolve the Pixi container a visual should render into: the nearest ancestor * {@link SortGroupComponent} bound to the same layer, or the layer container * itself when there is no enclosing group. Walks the entity hierarchy starting * at `entity` (inclusive), so a visual on a group-owning entity joins that * group. * * When `layerName` names a layer the scene never declared in its `layers`, * this warns in dev (naming the entity, the missing layer, and the scene) and * falls back to the scene's default layer, so the visual still renders instead * of throwing or silently disappearing. * * The built-in visual components call this in their `onAdd`. A custom visual * component (one implementing {@link LayerRenderable}) should do the same, so * it joins an enclosing group on its initial add rather than only when the * group next re-homes its subtree: * * ```ts * onAdd() { * const tree = this.use(SceneRenderTreeKey); * resolveRenderParent(this.entity, this.layerName, tree).addChild( * this.renderObject, * ); * } * ``` */ declare function resolveRenderParent(entity: Entity, layerName: string, tree: SceneRenderTree): DisplayContainer; /** Options for {@link SortGroupComponent}. */ interface SortGroupComponentOptions { /** * Layer the group renders into. Visuals in the entity's subtree that target * this same layer are gathered into the group; visuals targeting a different * layer are left alone (so a child's shadow can still live on a separate * `"ground"` layer). Default: `"default"`. */ layer?: string; /** * Optional depth key for ordering the group's own members. Default (unset): * members keep insertion order, and any member's manually-set `zIndex` is * honoured — a real stacking context, matching Unity's `SortingGroup`. Pass * `ySort` (or any {@link LayerSortFn}) to instead order members by position * among themselves, while the group as a whole still sorts as one unit * against the rest of the layer. */ innerSort?: LayerSortFn; } /** * Renders an entity's subtree of visuals as a single depth unit. * * Under a layer `sort` (e.g. `ySort`) every sprite is otherwise a flat child of * the layer with its own independent depth key, so a multi-part entity — a body * plus an offset held item, or a parent plus child entities — can be split when * an unrelated entity's key falls between its parts. A `SortGroupComponent` * gives the entity its own Pixi sub-container: the members sort *within* the * group, and the group sorts as **one unit** against the rest of the layer * (keyed off the group-owning entity's own sprite, falling back to its * `Transform` position when it has no sprite of its own). * * The group container is kept at identity/origin, so members hold their normal * world transforms — adding a group changes paint **order** only, never * position, rotation, or scale (those stay composed by the ECS `Transform`). * * ```ts * class Knight extends Entity { * setup() { * this.add(new Transform({ position: { x: 200, y: 200 } })); * this.add(new SortGroupComponent({ layer: "world" })); * this.add(new SpriteComponent({ texture: "knight-body", layer: "world" })); * // Child sprites on the "world" layer join the group automatically: * this.spawnChild("weapon", Weapon); // a sprite offset toward the camera * this.spawnChild("plume", Plume); * } * } * ``` * * Add the component **before** the visuals it should capture (it also re-homes * any already-present subtree visuals when added late). * A `SortGroupComponent` on a descendant entity starts its own independent * unit rather than nesting inside the ancestor's. */ declare class SortGroupComponent extends Component { private readonly positionScratch; /** The group's Pixi container. Kept at identity; holds the member visuals. */ readonly container: DisplayContainer; /** Layer this group renders into. */ readonly layer: string; /** Depth key for intra-group member order, or `undefined` for insertion order. */ innerSort: LayerSortFn | undefined; /** Lazily-created stand-in used for the group's sort key when the owning * entity has no sprite of its own. */ private _proxy; constructor(options?: SortGroupComponentOptions); onAdd(): void; onDestroy(): void; /** * Compute this group's depth key under the layer `sort`. Samples the * group-owning entity's own visual (so `ySort`/`ySortBy` read a real sprite's * position and offset); falls back to a proxy at the entity's `Transform` * world position when the owner renders nothing itself. * * @internal Called by `DisplaySystem` each Render phase. */ resolveSortKey(sort: LayerSortFn): number; /** The owning entity's own visual on this layer, if currently in the group. */ private findSample; /** Gather every subtree visual on this layer into the group container. */ private regroup; private collect; private tryLayerContainer; } /** @internal Set the renderer-level default text style (RendererPlugin). */ declare function setDefaultTextStyle(style: TextStyle | undefined): void; /** @internal Current renderer-level default text style, if any. */ declare function getDefaultTextStyle(): TextStyle | undefined; /** * Resolve the final style assigned to a Pixi text node: engine default (+ an * optional caller default, e.g. the UIPlugin override) as the base, then the * per-text `style` on top. Used by both construction and the `setStyle` * update paths so a re-render keeps the resolved default. * * @internal */ declare function resolveTextStyle(style: TextStyle | undefined, extraDefault?: TextStyle | undefined): TextStyle | undefined; /** * Build the shared `Text` / `BitmapText` constructor options and pick the * Pixi class for both `TextComponent` and `UIText`. `bitmap` selects * `BitmapText`, which bakes / looks up its glyph atlas from `style.fontFamily`. * `resolution` is forwarded only to canvas `Text` — `BitmapText` resolution * is fixed at font-bake time (Pixi v8 warns if you set it per-instance), so * use `installBitmapFont({ resolution })`. * * Centralised so the two text classes can't drift on the Pixi-v8 * resolution-gating rule. `extraDefault` layers a caller-owned default * (the UIPlugin override) between the engine default and the per-text style. * * @internal */ declare function buildTextOptions(text: string, style: TextStyle | undefined, bitmap: boolean | undefined, resolution: number | undefined, extraDefault?: TextStyle | undefined): { options: TextOptions; bitmap: boolean; }; type AnySplitText = DisplaySplitText | DisplaySplitBitmapText; /** * The `autoSplit` constructor option for a split text built with `text`. * `autoSplit` is what the caller asked for. */ declare function initialAutoSplit(autoSplit: boolean, text: string): boolean; /** * Assign `text` and keep automatic splitting on only while there is something * to split. `autoSplit` is what the caller asked for. */ declare function setSplitText(target: AnySplitText, text: string, autoSplit: boolean): void; /** * Split now, unless the text is empty. Reports whether it split, so a caller * can skip the work that only makes sense around fresh segments. */ declare function splitIfNotEmpty(target: AnySplitText): boolean; /** A single color stop along a gradient, with yage's numeric color + alpha pair. */ interface GradientStop { /** Position along the gradient, 0 (start) to 1 (end). */ offset: number; /** Color as 0xRRGGBB. */ color: number; /** Opacity 0-1. Default: 1. */ alpha?: number; } /** * How gradient coordinates are interpreted. * * - `"local"` — `start`/`end` (or `innerCenter`/`outerCenter`) are in the 0-1 * space of the shape the gradient fills. A vertical gradient from {0,0} to * {0,1} scales to cover any rect it's applied to. This is the default. * - `"global"` — coordinates are absolute world/screen pixels. Useful when * multiple shapes should share a single gradient "ruler." */ type GradientSpace = "local" | "global"; /** Options for {@link linearGradient}. */ interface LinearGradientOptions { stops: readonly GradientStop[]; /** * Shorthand for common orientations. Ignored if {@link start} / {@link end} * are provided. Default: `"vertical"`. */ axis?: "horizontal" | "vertical"; /** Explicit start point. Overrides `axis`. */ start?: { x: number; y: number; }; /** Explicit end point. Overrides `axis`. */ end?: { x: number; y: number; }; /** Coordinate space for `start`/`end`. Default: `"local"`. */ space?: GradientSpace; } /** Options for {@link radialGradient}. */ interface RadialGradientOptions { stops: readonly GradientStop[]; /** Center of the gradient. Default: `{ x: 0.5, y: 0.5 }` in local space. */ center?: { x: number; y: number; }; /** * Center of the outer (end) circle. Default: same as {@link center}. * Set to a different point for offset / non-concentric radial gradients * (rim lighting, directional glows). */ outerCenter?: { x: number; y: number; }; /** Radius of the inner (start) circle. Default: `0`. */ innerRadius?: number; /** Radius of the outer (end) circle. Default: `0.5` in local space. */ outerRadius?: number; /** Coordinate space for centers and radii. Default: `"local"`. */ space?: GradientSpace; } /** * Create a linear gradient fill usable with `GraphicsComponent` draws * (`g.rect(...).fill(myGradient)`). * * Uses yage-style numeric colors with optional alpha per stop, and a simple * axis shorthand for the common vertical/horizontal cases. * * Returns a `GradientFill` (pixi `FillGradient` under the hood). Call * `.destroy()` when you're done with it to release the backing texture — * components typically do this in `onDestroy()`. */ declare function linearGradient(options: LinearGradientOptions): GradientFill; /** * Create a radial gradient fill. In `"local"` space (the default), centers * are in the 0-1 range of the filled shape's bounds. */ declare function radialGradient(options: RadialGradientOptions): GradientFill; /** * Slice a texture into frame Textures on a uniform grid. * * Frame `i` is read at column `i % columns`, row `floor(i / columns)`. * Without `columns`, the column count is derived from the texture width; * without `count`, a single full row is read. * * Throws when a field is not a finite number at or above its minimum, or when * the resulting grid extends past the texture. */ declare function sliceGrid(base: Texture, options: TextureSliceOptions): Texture[]; /** * Slice a single-row horizontal spritesheet into individual frame Textures. * * Only reads the top row of the image (`y = 0`). For multi-row grid sheets, * use a {@link SheetFrameSource} with `count`/`columns` (or call * {@link sliceGrid} directly); for non-uniform frame layouts, use PixiJS's * `Spritesheet` class with a JSON atlas descriptor (TexturePacker / Aseprite * JSON export format). * * @param source - A PixiJS Texture or asset path string. * @param frameWidth - Width of each frame in pixels. * @param frameHeight - Height of each frame (defaults to `frameWidth` for square frames). */ declare function sliceSheet(source: Texture | string, frameWidth: number, frameHeight?: number): Texture[]; /** * A sprite sheet sliced on a uniform grid. Without `count`/`columns` it * reads the single top row (a horizontal strip); `count` extends the slice * across rows, wrapping every `columns` frames. Offsets and gaps follow * {@link TextureSliceOptions}. */ interface SheetFrameSource extends TextureSliceOptions { /** * The sheet to slice: an asset key, or the texture handle a `texture(...)` * declaration returns. Both resolve from the cache a `SpriteComponent` * texture resolves from. */ sheet: TextureRef; } /** A named animation within a JSON atlas spritesheet. */ interface AtlasFrameSource { atlas: string; animation: string; } /** Union type for asset-backed frame references. */ type FrameSource = SheetFrameSource | AtlasFrameSource; declare function isSheetSource(s: FrameSource): s is SheetFrameSource; declare function isAtlasSource(s: FrameSource): s is AtlasFrameSource; /** * Resolve a FrameSource to concrete Texture[]. * Assets must already be loaded (via scene preload) — this is synchronous. */ declare function resolveFrames(source: FrameSource): Texture[]; /** Options for creating an AnimatedSpriteComponent. */ interface AnimatedSpriteComponentOptions extends VisualComponentOptions { /** Frame source (sheet grid or atlas animation). */ source: FrameSource; /** * Default sprite anchor (0,0 = top-left, 0.5,0.5 = center, 1,1 = bottom-right). * Per-{@link AnimationController} `AnimationDef.anchor` overrides this when set. */ anchor?: Vec2Like; /** * Playback rate applied at construction: frames advanced per tick at 60 fps. * Default `1`. `play({ speed })` and the * {@link AnimatedSpriteComponent.speed} property retime the clip afterwards, * and an {@link AnimationController} writes the rate at every animation * switch. */ speed?: number; } /** Component that displays a PixiJS AnimatedSprite. */ declare class AnimatedSpriteComponent extends VisualComponent { readonly animatedSprite: DisplayAnimatedSprite; private readonly _frameListeners; constructor(options: AnimatedSpriteComponentOptions); /** The underlying Pixi display object. */ get renderObject(): DisplayAnimatedSprite; /** * Resumes from the current frame; `fromStart: true` restarts at frame 0. * * `speed` and `loop` are sticky — the next play keeps whatever this one set. * `onComplete` is not: a play owns its completion callback, so a play * without one clears the callback the previous play installed. * * Use the {@link AnimatedSpriteComponent.speed} property to retime a clip * that is already running. */ play(options?: { speed?: number; loop?: boolean; onComplete?: () => void; fromStart?: boolean; }): void; /** * Subscribe to frame changes on the underlying sprite. Returns an * unsubscribe function, so `this.addCleanup(sprite.onFrameChange(fn))` * drops the listener with the subscribing component. * * Pixi delivers a frame change on `play`, on a frame advance, and on the * frame reset an animation switch performs, so a listener sees controller * switches too. Assigning `animatedSprite.onFrameChange` directly replaces * the dispatcher this installs and silences every subscriber. */ onFrameChange(listener: (frame: number) => void): () => void; /** Stop the animation. */ stop(): void; /** Stop playback and hold `index` as a static pose. */ gotoFrame(index: number): void; /** Current frame index of the underlying AnimatedSprite. */ get frame(): number; /** Whether the animation is currently playing. */ get isPlaying(): boolean; /** * Playback rate of the underlying sprite: frames advanced per tick at 60 * fps, so `0.15` moves on about every seventh tick and `1` on every tick. * Defaults to `1`. Writing it retimes the clip that is already running, * without restarting it, and reads back the same number `play({ speed })` * writes. * * `0` holds the current frame while {@link isPlaying} stays `true`, and a * negative value plays backwards. Scene and entity `timeScale` multiply * this. A non-finite value throws. * * With an {@link AnimationController} on the entity this reads the rate the * sprite is actually running at: the animation definition's `speed`, times * the controller's `speed`, times the `playOneShot({ speed })` factor. The * controller writes it again at its next animation switch and whenever its * own `speed` is written. Set `AnimationController.speed` to retime every * animation; set this to retime only the clip on screen. Writing this does * not retime a running one-shot's lock: the lock keeps the duration computed * when the one-shot started, so the clip and the lock can end at different * times. */ get speed(): number; set speed(value: number); /** Advance playback using engine-scaled time. */ update(dt: number): void; } /** Definition for a single named animation. */ interface AnimationDef { /** Frame source (sheet grid or atlas animation). */ source: FrameSource; /** PixiJS animationSpeed value (e.g. 0.15). */ speed: number; /** Whether the animation loops. Default: true. */ loop?: boolean; /** Per-animation anchor override. */ anchor?: { x: number; y: number; }; } /** Options for a one-shot play. */ interface AnimationOneShotOptions { /** Frame to start from (integer, 0 to the last frame). Default: 0. */ startFrame?: number; /** * Playback multiplier for this one-shot only, on top of the controller's * `speed`. Finite and greater than 0. Default: 1. */ speed?: number; /** Explicit lock duration in seconds, replacing the automatic calculation. */ duration?: number; /** Called when the one-shot plays out. */ onComplete?: () => void; /** Called when anything else ends the one-shot first. */ onCancel?: () => void; } /** Options that change how long a one-shot takes to play. */ interface AnimationTimingOptions { /** Frame the play starts from. Default: 0. */ startFrame?: number; /** Per-play speed multiplier. Default: 1. */ speed?: number; } /** * High-level animation controller that manages named animations on top of * a sibling {@link AnimatedSpriteComponent}. * * Provides one-shot locking, per-animation anchors, and type-safe animation * names via the generic parameter. * * **Narrowing the animation-name type** — `entity.get(AnimationController)` * returns `AnimationController` (the default `T`); the runtime class * isn't generic, and a string-typed instance can't substitute for a narrower * one (the `current: T | ""` getter is covariant on `T`). Cast at the field * declaration so every consumer downstream sees the narrow type: * * ```ts * type Anim = "idle" | "walk" | "shoot"; * * class HeroController extends Component { * private readonly _anim = this.sibling(AnimationController) as * AnimationController; * } * ``` * * For multi-sprite (head + body + outfit) characters, see * {@link LayeredAnimationController} — it fans `play()`/`playOneShot()` across * a list of sibling controllers with a single shared lock timer. */ declare class AnimationController extends Component { private readonly _anims; private readonly _sprite; private _current; private _locked; private _lockTimer; private _lockDuration; private _lockUsesAnimationDuration; private _lockStartFrame; private _shotSpeed; private _onComplete; private _onCancel; private _speed; constructor(animations: Record); /** Currently playing animation name, or "" if none. */ get current(): T | ""; /** True if a one-shot animation is blocking. */ get locked(): boolean; /** Current frame index of the underlying AnimatedSprite. */ get frame(): number; /** * Runtime speed multiplier (default 1). A controller owned by a * {@link LayeredAnimationController} shares this value with every layer. */ get speed(): number; set speed(value: number); /** Whether this controller defines the given animation name. */ has(name: string): name is T; /** Play a named animation. No-op if already current or locked. */ play(name: T): void; /** Play an animation as a one-shot, locking out other plays until complete. * No-op if already locked on the same animation (prevents restart flicker). * * Exactly one of `onComplete` and `onCancel` runs per one-shot: * `onComplete` when the lock timer plays out, `onCancel` when another * one-shot, `forcePlay`, `unlock` or component destruction ends it first. * A cancel callback runs after the new state is in place, so calling * `playOneShot` from inside it takes effect. * * When `options.duration` is omitted, the lock duration is auto-calculated * from the frames that will actually play — the frame count from * `startFrame` on, at the controller speed times `options.speed`. Pass an * explicit `duration` to synchronise lock release across multiple * controllers (see {@link LayeredAnimationController}). */ playOneShot(name: T, options?: AnimationOneShotOptions): void; /** Clear lock and force-switch to the given animation. */ forcePlay(name: T): void; /** Manually release the one-shot lock, firing a pending `onCancel`. */ unlock(): void; /** * Calculate the engine-scaled duration (seconds) a one-shot of this * animation would take, matching what `playOneShot` locks for. * * Frame-rate independent: PixiJS normalises `deltaTime` via * `Ticker.targetFPMS` (0.06), so the formula holds at any actual fps. The * controller timer and animated sprite both receive engine-scaled time. * Throws unless the effective speed is positive and produces a finite * duration. Use an explicit one-shot duration for paused or reverse playback. */ calcDuration(name: T, options?: AnimationTimingOptions): number; /** * Throw if this controller would reject the timing, without deriving a * duration from it. `LayeredAnimationController` checks every layer before * any layer switches; when the caller passes an explicit shared duration, * no layer's own duration feeds the timer, so only the frame and speed * gates apply. * @internal */ _assertTiming(name: T, options: AnimationTimingOptions | undefined): void; private calcDurationAtSpeed; /** Check whether the current frame is within [start, end] inclusive. */ inFrameRange(start: number, end: number): boolean; /** Auto-play the first defined animation. */ onAdd(): void; /** A live one-shot ends with the component, so its `onCancel` still runs. */ onDestroy(): void; /** Tick the one-shot lock timer. */ update(dt: number): void; /** Drop the lock and both of its callbacks without notifying either. */ private _clearLock; /** Resolve a caller-supplied name, naming the entry it was passed to. */ private _def; private _validateTiming; private _apply; } /** Options for {@link LayeredAnimationController}. */ interface LayeredAnimationControllerOptions { /** * Sibling controllers to drive in lockstep. Typically one per visual layer * (head, body, outfit) of a layered character, each living on its own child * entity with its own {@link AnimatedSpriteComponent}. */ controllers: AnimationController[]; } /** * Fan-out wrapper around N sibling {@link AnimationController} instances. * * Use this when a single logical character is composed of multiple sprite * layers (head + body + outfit) — each layer has its own * `AnimatedSpriteComponent` + `AnimationController`, but they all need to * `play("walk")` or `playOneShot("attack")` in unison. * * - `play(name)` is forwarded to every child controller. * - `speed` writes the same runtime multiplier to every child. * - `playOneShot(name, opts)` uses the first child as the shared timer and * keeps every other child locked until that timer completes. * - The wrapper fires exactly one of the user's `onComplete` / `onCancel`. * - Every layer must define every name played through the wrapper; a missing * name throws before any layer switches, and so does a `startFrame` or * `speed` that any layer rejects when the timing is automatic. * * ```ts * class Hero extends Entity { * setup() { * this.add(new Transform()); * const body = this.spawnChild("body", HeroLayer, { sheet: "body.png" }); * const head = this.spawnChild("head", HeroLayer, { sheet: "head.png" }); * this.add(new LayeredAnimationController({ * controllers: [body.get(AnimationController), head.get(AnimationController)], * })); * } * } * ``` */ declare class LayeredAnimationController extends Component { private readonly _controllers; private readonly _leader; private _current; private _locked; private _onComplete; private _onCancel; constructor(options: LayeredAnimationControllerOptions); /** Sibling controllers being driven. */ get controllers(): readonly AnimationController[]; /** Currently playing animation name, or "" if none. */ get current(): T | ""; /** True if a one-shot animation is blocking. */ get locked(): boolean; /** * Shared runtime speed multiplier, read from the first controller and * applied to every controller. Writes to any participating controller's * `speed` property route through this group while the wrapper is attached. */ get speed(): number; set speed(value: number); onAdd(): void; /** Play a named animation on every layer. No-op if already current or locked. */ play(name: T): void; /** Play a one-shot on every layer with a shared lock duration. * * The first controller owns the shared timer. Its normal automatic timing * keeps the lock aligned when its speed changes. Other controllers receive * an infinite lock duration and are released with the wrapper. Pass an * explicit duration to keep the shared timer independent of playback speed. * * The shared `startFrame` and `speed` are checked against every layer * first, so a value one layer rejects throws with every layer still on its * previous animation. * * The wrapper owns the interruption signal: exactly one of `onComplete` and * `onCancel` runs per one-shot, and layers never receive a cancel of their * own. */ playOneShot(name: T, options?: AnimationOneShotOptions): void; /** Clear the lock and force-switch every layer to the given animation. */ forcePlay(name: T): void; /** Manually release the one-shot lock on this wrapper and every child. */ unlock(): void; /** A live one-shot ends with the component, so its `onCancel` still runs. */ onDestroy(): void; private completeOneShot; /** Release the lock on this wrapper and every layer, notifying nobody. */ private _clearLock; private _assertEveryLayerHas; } /** * What a follow tracks each frame, always in world coordinates. An `Entity` * or a `Transform` reads the current `worldPosition`, so a target parented * under a moving platform tracks where it actually is on screen; a `Vec2Like` * is a fixed world coord; a function is called every frame and may compute * any world coord (the midpoint of two entities, a position along a path). */ type FollowTarget = Entity | Transform | Vec2Like | (() => Vec2Like); /** Initial values for one camera contribution. */ interface CameraModifierOptions { /** Additive world-space position offset. Default: `{ x: 0, y: 0 }`. */ position?: Vec2Like; /** Additive rotation in radians. Default: `0`. */ rotation?: number; /** Multiplicative zoom factor. Default: `1`. */ zoom?: number; } /** Removable contribution owned by a {@link CameraModifierHost}. */ interface CameraModifierHandle { /** Whether this contribution is still active. */ readonly active: boolean; /** Replace this contribution's additive position offset. */ setPosition(offset: Vec2Like): void; /** Replace this contribution's additive rotation offset. */ setRotation(radians: number): void; /** Replace this contribution's multiplicative zoom factor. */ setZoom(factor: number): void; /** Remove only this contribution. Safe to call more than once. */ remove(): void; } /** Transient contributions combined with a camera's authoritative values. */ declare class CameraModifierHost { private readonly contributions; private _positionOffset; private _rotationOffset; private _zoomFactor; private destroyed; /** Combined additive world-space position offset. */ get positionOffset(): Vec2; /** Combined additive rotation offset in radians. */ get rotationOffset(): number; /** Combined multiplicative zoom factor. */ get zoomFactor(): number; /** Number of active contributions. */ get size(): number; /** Add one independently removable camera contribution. */ add(options?: CameraModifierOptions): CameraModifierHandle; /** @internal Invalidates every outstanding handle during component teardown. */ _destroy(): void; private assertLive; private recompute; } /** Bounding rectangle for camera clamping. */ interface CameraBounds { minX: number; minY: number; maxX: number; maxY: number; } /** Options for camera follow behavior. */ interface CameraFollowOptions { /** * Smoothing factor 0..1. `1` = instant snap, lower = smoother. `0` never * moves the camera at all, so the follow appears frozen. Default: `1`. */ smoothing?: number; /** Offset from the target position, in world pixels. */ offset?: Vec2Like; /** * Deadzone rectangle in world pixels (half-width, half-height). The camera * stays put while the target is inside it. */ deadzone?: { halfWidth: number; halfHeight: number; }; /** * Place the camera on the target as following starts, instead of easing in * from wherever the camera currently is. Default: false. */ snap?: boolean; } /** Options for camera shake. */ interface CameraShakeOptions { /** * How much the shake fades across its duration. `0` (the default) holds * full intensity until the shake ends. `1` fades linearly to zero over the * duration. Values above `1` reach zero earlier — at `2` the camera stops * moving halfway through. */ decay?: number; } /** * Binding that associates a camera with a named render layer. * * Each ratio is a linear blend from identity (`0`) to full camera effect * (`1`), applied independently per axis. Defaults are all `1`, giving the * classic "this layer follows the camera" behavior. * * Common recipes: * - Parallax: `translateRatio: 0.5` (half the camera's translation). * - Dampened zoom, still upright: `rotateRatio: 0, scaleRatio: 0.3`. * * A ratio below `1` scales the layer by less than the camera does while the * layer still translates by the full camera offset, so content drifts away * from the world position it should sit on as the zoom leaves `1`. For UI * that must track a world point at constant size, use `ScreenFollow`, which * projects the point through the camera every frame. */ interface CameraBinding { /** Layer name to transform. */ layer: string; /** Translation follow factor. `0` = stay at world origin, `1` = full. Default: `1`. */ translateRatio?: number; /** Rotation follow factor. `0` = stay upright, `1` = full camera rotation. Default: `1`. */ rotateRatio?: number; /** Zoom follow factor. `0` = constant size, `1` = full camera zoom. Default: `1`. */ scaleRatio?: number; } interface CameraComponentOptions { position?: Vec2; zoom?: number; rotation?: number; bindings?: CameraBinding[]; autoBind?: boolean; priority?: number; name?: string; } /** * Core camera state component. Added by `CameraEntity`; holds position, * zoom, rotation, and layer bindings. Provides convenience methods that * delegate to sibling behavior components (CameraFollow, CameraShake, etc.). * * Added by `CameraEntity`; access via direct reference from `spawn()` * or by querying entities with this component. */ declare class CameraComponent extends Component { private readonly projectionScratch; position: Vec2; zoom: number; rotation: number; /** Transient position, rotation, and zoom contributions. */ readonly modifiers: CameraModifierHost; readonly bindings: CameraBinding[] | null; /** Bind every world-space layer before applying `bindings`. Default: `true`. */ readonly autoBind: boolean; readonly priority: number; readonly cameraName: string | undefined; constructor(options?: CameraComponentOptions); get viewportWidth(): number; get viewportHeight(): number; /** Effective position including every active camera modifier. */ get effectivePosition(): Vec2; /** Copy the position including active modifiers into caller-owned scratch. */ getEffectivePositionInto(out: Vec2Buffer): Vec2Buffer; /** Effective rotation including every active camera modifier. */ get effectiveRotation(): number; /** Effective zoom including every active camera modifier. */ get effectiveZoom(): number; /** Start following a target. */ follow(target: FollowTarget, options?: CameraFollowOptions): void; /** Stop following any target. */ unfollow(): void; /** Cut to the current follow target, skipping the smoothing ease. */ snapToTarget(): void; /** * Start a screen shake effect. `intensity` is the maximum displacement per * axis in **world pixels**, so what the player sees scales with zoom — the * same intensity moves twice as far on screen at zoom 2. */ shake(intensity: number, duration: number, options?: CameraShakeOptions): void; /** Animate zoom to a target value over a duration. */ zoomTo(target: number, duration: number, easing?: EasingFunction): void; /** Get or set camera bounds. */ get bounds(): CameraBounds | undefined; set bounds(value: CameraBounds | undefined); /** * Convert screen coordinates to world coordinates. * * The conversion uses the camera's own transform, not any layer's. A layer * bound with a ratio below `1` (parallax, dampened zoom) renders under a * different transform, so this result does not name a point on that layer. * * The result is undefined for a zoom of `0` or a non-finite camera value. */ screenToWorld(screenX: number, screenY: number): Vec2; /** Copy a screen-to-world projection into caller-owned scratch. */ screenToWorldInto(out: Vec2Buffer, screenX: number, screenY: number): Vec2Buffer; /** * Convert world coordinates to screen coordinates. * * The conversion uses the camera's own transform, not any layer's. Content * on a layer bound with a ratio below `1` (parallax, dampened zoom) is * drawn somewhere else on screen than this result says. */ worldToScreen(worldX: number, worldY: number): Vec2; /** Copy a world-to-screen projection into caller-owned scratch. */ worldToScreenInto(out: Vec2Buffer, worldX: number, worldY: number): Vec2Buffer; /** * Resolve bindings for this camera against the given render tree. * * Every world-space layer (`LayerDef.space === "world"`, the default) is * bound at full strength. Screen-space layers — declared with * `space: "screen"` or auto-provisioned by plugins via * `ensureLayer(def, { space: "screen" })`, e.g. the UI layer — are skipped * so they stay fixed to the viewport. * * An entry in `bindings` replaces the binding for the layer it names; an * entry naming a screen-space layer, or a layer the tree does not hold, * is added. With `autoBind: false` the camera binds exactly the entries in * `bindings` and nothing else — the only way to leave a world-space layer * untransformed, since a binding with all three ratios at `0` centres the * layer on the viewport instead. * * Called once per camera per frame, so a layer created after the camera * spawned is bound on the next frame. */ getResolvedBindings(tree: SceneRenderTree): readonly CameraBinding[]; onDestroy(): void; } /** Axis-aligned rectangle in world space, used by `CameraEntityParams.fitTo`. */ interface CameraFitToRect { x: number; y: number; width: number; height: number; } interface CameraEntityParams { /** Initial position. */ position?: Vec2; /** Follow target — an `Entity`, a `Transform`, a world point, or a function returning one. */ follow?: FollowTarget; /** Follow smoothing factor 0..1. Default: 1 (instant). */ smoothing?: number; /** Follow offset. */ offset?: Vec2Like; /** Follow deadzone. */ deadzone?: { halfWidth: number; halfHeight: number; }; /** * Start on the follow target instead of easing in from `position`. Without * it a smoothed camera glides in from wherever it spawned — the world * origin, unless `position` or `fitTo` places it elsewhere. Ignored when no * `follow` target is given. */ snap?: boolean; /** Camera bounds for position clamping. */ bounds?: CameraBounds; /** Initial zoom level. Default: 1. */ zoom?: number; /** * Per-layer bindings applied on top of the auto-bound world layers. An * entry replaces the binding for the layer it names; an entry naming a * screen-space layer adds it. */ bindings?: CameraBinding[]; /** * Bind every world-space layer at full strength before applying * `bindings`. Default: `true`. `false` binds exactly what `bindings` * names, and nothing else. */ autoBind?: boolean; /** Camera priority (lower = processed first). Default: 0. */ priority?: number; /** Camera name (for multi-camera lookup). */ name?: string; /** * Frame an axis-aligned world rectangle: position the camera on the * rect's centre and zoom so the entire rect fits inside the viewport * (`contain` semantics — `zoom = min(viewportW / rect.w, viewportH / * rect.h)`). Wins over `position` and `zoom` when supplied. Applied * once at setup against the current renderer viewport — for fixed * cameras where the framed area is known up front (puzzle boards, * arcade levels, dialog-scene insets). For runtime re-framing, set * `position` + `zoom` directly on the camera. */ fitTo?: CameraFitToRect; } /** * Camera entity. Spawn in a scene to enable camera-based layer transforms. * * ```ts * const cam = this.spawn(CameraEntity, { * follow: player.get(Transform), * smoothing: 0.15, * bounds: { minX: 0, minY: 0, maxX: 2000, maxY: 2000 }, * }); * * // All camera operations are available directly on the entity: * cam.shake(8, 0.3); * cam.zoomTo(1.5, 1); * cam.follow(otherTarget, { smoothing: 0.1 }); * ``` */ declare class CameraEntity extends Entity { private cam; setup(params?: CameraEntityParams): void; get position(): Vec2; set position(value: Vec2); get zoom(): number; set zoom(value: number); get rotation(): number; set rotation(value: number); get bounds(): CameraBounds | undefined; set bounds(value: CameraBounds | undefined); get effectivePosition(): Vec2; get effectiveRotation(): number; get effectiveZoom(): number; get modifiers(): CameraModifierHost; follow(target: FollowTarget, options?: CameraFollowOptions): void; unfollow(): void; snapToTarget(): void; shake(intensity: number, duration: number, options?: CameraShakeOptions): void; zoomTo(target: number, duration: number, easing?: EasingFunction): void; screenToWorld(screenX: number, screenY: number): Vec2; getEffectivePositionInto(out: Vec2Buffer): Vec2Buffer; screenToWorldInto(out: Vec2Buffer, screenX: number, screenY: number): Vec2Buffer; worldToScreenInto(out: Vec2Buffer, worldX: number, worldY: number): Vec2Buffer; worldToScreen(worldX: number, worldY: number): Vec2; } /** * Camera follow behavior. Smoothly moves `CameraComponent.position` * toward the target's world position each frame. */ declare class CameraFollow extends Component { private readonly cam; private readonly targetScratch; private target; private smoothing; private offset; private deadzone; /** Start following a target. */ start(target: FollowTarget, options?: CameraFollowOptions): void; /** Stop following any target. */ stop(): void; /** * Place the camera on its target right away, offset included. Skips both * the smoothing ease and the deadzone, so the camera cuts rather than * glides — use it after a teleport (room change, respawn). Any deadzone * applies again from the next frame. Does nothing without a target. */ snapToTarget(): void; update(dt: number): void; /** Current target world position with the follow offset applied. */ private targetPosition; } /** * Camera shake behavior. Writes one removable contribution to * `CameraComponent.modifiers` and leaves the base position unchanged. */ declare class CameraShake extends Component { private intensity; private duration; private elapsed; private decay; private _offset; private modifier; /** Current shake offset contributed through `CameraComponent.modifiers`. */ get offset(): Vec2; /** * Start a screen shake effect. `intensity` is the maximum displacement per * axis in **world pixels**, so what the player sees scales with zoom — the * same intensity moves twice as far on screen at zoom 2. */ start(intensity: number, duration: number, options?: CameraShakeOptions): void; /** Cancel the current shake immediately. */ stop(): void; update(dt: number): void; onDestroy(): void; private setOffset; private ensureModifier; } /** * Camera bounds clamping. Restricts `CameraComponent.position` to a bounding * rectangle each frame. Runs after every camera behaviour that moves or zooms * the camera, so the clamp sees this frame's position and zoom rather than * last frame's. */ declare class CameraBoundsComponent extends Component { static updatePriority: number; private readonly cam; bounds: CameraBounds | undefined; update(): void; } /** * Camera zoom animation behavior. Smoothly interpolates * `CameraComponent.zoom` toward a target value over a duration. */ declare class CameraZoom extends Component { private readonly cam; private zoomFrom; private zoomTarget; private duration; private elapsed; private easing; private zooming; /** Start a zoom animation. */ start(target: number, duration: number, easing?: EasingFunction): void; update(dt: number): void; } /** What the follow tracks each frame. See {@link FollowTarget}. */ type ScreenFollowTarget = FollowTarget; /** Options for `ScreenFollow`. */ interface ScreenFollowOptions { /** What world coord to track. */ target: ScreenFollowTarget; /** * Camera whose `worldToScreen` projection defines the screen mapping. * Required — YAGE doesn't have a global "main" camera, so the projection * source must be explicit. */ camera: CameraEntity; /** * Screen-pixel offset added to the projected position. Default `(0, 0)`. * * Applied *after* projection (`cam.worldToScreen(target) + offset`), not * before — so the visual gap between UI and target stays fixed under any * camera zoom or rotation. Adding it in world coords before projection * would let the camera transform warp the offset. */ offset?: Vec2Like; /** * When the target is an `Entity` or a `Transform`, copy its * `worldRotation` onto this * entity's Transform each frame. Useful when the UI should rotate with * the target itself (e.g. a vehicle UI that tilts with the vehicle) but * stay stable against the camera. Default `false` — this entity's * rotation is left alone, so a panel on a screen-space layer renders * axis-aligned. Ignored when `target` is a Vec2 or a function. */ trackRotation?: boolean; } /** * Each frame, projects a world source through a camera and writes the * resulting screen coord to this entity's `Transform.worldPosition`. * * The canonical "billboard" primitive: pair with a `UISurface` (or `UIRoot`) * on a screen-space layer using `positioning: "transform"` to produce UI * that tracks a target entity but stays axis-aligned and constant-size * regardless of camera zoom or rotation — nameplates, health bars, * damage numbers, interaction prompts. * * ```ts * class Nameplate extends Entity { * constructor(private readonly target: Entity, private readonly camera: CameraEntity) { * super(); * } * setup() { * this.add(new Transform()); * this.add(new ScreenFollow({ * target: this.target, * camera: this.camera, * offset: new Vec2(0, -40), // 40 screen px above the target * })); * const panel = this.add(new UISurface({ * positioning: "transform", // reads Transform.worldPosition * anchor: Anchor.BottomCenter, // pivot on the panel * })); * panel.text("Grunt-42", { fontSize: 11 }); * } * } * ``` */ declare class ScreenFollow extends Component { private readonly positionScratch; private _target; private _camera; private _offset; private _trackRotation; constructor(opts?: ScreenFollowOptions); update(): void; private resolveTargetPosition; } /** * Syncs Transform components to PixiJS display objects and applies * camera-based per-layer transforms. Each scene's CameraEntity bindings * determine which layers receive the camera transform; unbound layers * stay at identity (screen-space behavior). */ declare class DisplaySystem extends System { private readonly transformScratch; readonly phase = Phase.Render; readonly priority = 0; private visualQuery; private cameraQuery; private sortGroupQuery; private treeProvider; private boundary; onRegister(context: EngineContext): void; update(): void; private applyVisualModifiers; private applyModifiers; /** * Per-frame depth-key hook. For every layer with a `sort` fn, writes * `child.zIndex = sort(child)` on every direct child. The layer's * container already has `sortableChildren = true` (set in `RenderLayer`), * so Pixi's render-pipeline sort runs at frame end and orders the * children by zIndex — no custom sort path on our side. Pixi's * `zIndex` setter marks `sortDirty` automatically, so we don't need * to flip it ourselves. * * A `SortGroupComponent`'s container is a direct child of the layer too, but * sorting it by its own (origin) position would be meaningless — it's keyed * off the group's anchor instead, so the whole group sorts as one unit. The * group's members are nested inside it, so this layer-level pass never * touches them; an optional `innerSort` re-keys them in a second pass. * * Layers without a `sort` keep insertion order. */ private applyLayerSort; /** * Apply per-layer camera transforms for every live scene. * * Layers are reset to identity first so disabling or destroying the last * camera cannot leave stale transforms behind on a scene's containers. * * Within a scene, enabled cameras are sorted by ascending `priority`; when * multiple cameras bind the same layer, the later write wins, so the * highest-priority camera fully overwrites translation, scale, and rotation * rather than blending with earlier cameras. * * Each binding's three ratios (`translateRatio`, `rotateRatio`, `scaleRatio`) * independently blend from identity (`0`) to full camera effect (`1`). All * default to `1`, matching the classic "this layer follows the camera" * behavior. Parallax is `translateRatio < 1`; a billboard layer is * `rotateRatio: 0, scaleRatio: 0`. */ private applyCameraTransforms; } /** * Built-in y-depth key: a container's `position.y` becomes its paint * order. Lower y renders first (behind); higher y renders on top — * matches the classic top-down 2D depth rule, where a character "in * front of" a tree (higher `position.y`) draws over it. * * ```ts * import { ySort } from "@yagejs/renderer"; * * // Depth-sort the auto-created default layer your entities already use — * // no per-component `layer` wiring needed. * class GameScene extends Scene { * readonly layers: readonly LayerDef[] = [ * { name: "default", order: 0, sort: ySort }, * ]; * } * ``` */ declare const ySort: LayerSortFn; /** * Y-depth key with a per-container offset, the way Godot's * `y_sort_origin` shifts a sprite's apparent "footprint" for depth * comparisons. Use when a sprite's anchor is set to its top (so the * visual base sits well below `position.y`) and the raw `position.y` * produces wrong overlaps — a player whose feet are at the bottom of * the sprite should pass *behind* a tree whose trunk is at the bottom * of its own sprite, not be sorted by the headtop. * * `offsetOf(container)` is called once per child per frame; cheap data * (a getter / a property read) keeps the per-frame cost negligible. The * key falls back to plain `position.y` when `offsetOf` returns * `undefined`, so mixed-content layers work without every child having * a depth offset. * * ```ts * import { ySortBy } from "@yagejs/renderer"; * * // Read the offset off a custom property (containers are extensible). * const sort = ySortBy((c) => (c as { depthOffset?: number }).depthOffset); * * // Then per-sprite: * sprite.sprite.depthOffset = 32; // pivot for sort lives 32 px below `position.y` * ``` */ declare function ySortBy(offsetOf: (c: DisplayContainer) => number | undefined): LayerSortFn; /** * Materializes a per-scene render tree with one root container per scene, * added as a direct child of the renderer plugin's `_worldRoot` container * (which itself sits under `app.stage`, but holds the fit transform — see * `RendererPlugin._worldRoot` for the rationale). Registered under * `SceneRenderTreeProviderKey` by the renderer plugin. * * ``` * app.stage // identity * └── _worldRoot // fit transform lives here * ├── scene A root * │ ├── layer "bg" (order -10) * │ ├── layer "world" (order 0) * │ └── layer "hud" (order 100) * └── scene B root * └── ... * ``` * * A scene that uses `renderAboveEffects` also owns a Pixi `RenderLayer` * placed immediately after its root, so the nodes attached to it draw after * the scene's layers and outside the scene root's filters and mask. */ declare class SceneRenderTreeProviderImpl implements SceneRenderTreeProvider { private readonly stage; private readonly processSystem?; private entries; constructor(stage: DisplayContainer, processSystem?: ProcessSystem | undefined); createForScene(scene: Scene): SceneRenderTree; destroyForScene(scene: Scene): void; getTree(scene: Scene): SceneRenderTree | undefined; allTrees(): IterableIterator<[Scene, SceneRenderTree]>; bringSceneToFront(scene: Scene): void; /** * Hide below-stack scene trees whose top neighbour has * `transparentBelow = false`. The topmost scene is always visible; below * neighbours stay visible only while every scene above them is * `transparentBelow = true`. Detached scenes (mounted via * `_mountDetached`, e.g. the debug overlay) are not in the stack and * their visibility is left alone. * @internal */ applyTransparentBelow(stack: readonly Scene[]): void; /** * Restore in-stack scene roots to visible. Used while a scene transition * runs so both the outgoing and incoming scenes can render even when the * new topmost scene has `transparentBelow = false`; the visibility chain * is reapplied when the transition ends. Detached scenes (mounted via * `_mountDetached`, e.g. the debug overlay) are left alone — same * contract as `applyTransparentBelow`, so callers can hide a detached * root without it being silently un-hidden on every transition start. * @internal */ resetVisibility(stack: readonly Scene[]): void; /** Destroy every tracked scene's tree. Used on renderer shutdown. */ destroyAll(): void; } interface FadeOptions { /** Fade duration in seconds. Default: 0.3. */ duration?: number; /** Fill color as a hex number. Default: 0x000000. */ color?: number; /** * When `true`, the overlay covers the full canvas including * letterbox / expand bars. When `false` (default), it covers only the * virtual play area — bars stay visible during the dip. */ coverScreen?: boolean; } /** * Fade to a solid color, then fade back in. The fade-out takes the first * half of the duration, the fade-in takes the second half. The scene swap * happens when the overlay is fully opaque: * - push/replace: incoming scene stays hidden until the half-way mark, then * is revealed underneath the decaying overlay. * - pop: outgoing scene stays visible through the fade-out, then is hidden * at the half-way mark so the destination shows through during fade-in. * * Without this, pop would render the outgoing scene the whole way through * and "pop" suddenly to the destination once the stack is popped at end(). */ declare function fade(opts?: FadeOptions): SceneTransition; interface FlashOptions { /** Flash duration in seconds. Default: 0.2. */ duration?: number; /** Flash color as a hex number. Default: 0xffffff. */ color?: number; /** * When `true`, the overlay covers the full canvas including * letterbox / expand bars. When `false` (default), it covers only the * virtual play area — bars stay visible during the flash. */ coverScreen?: boolean; } /** * Flash a solid color that decays from full opacity to zero over the * duration. The overlay is fully opaque at begin, so the scene swap happens * invisibly under the flash: * - push/replace: no visibility juggling — the incoming scene is already * mounted on top of the outgoing one in the stage order, so as the * overlay decays only the incoming scene shows through. * - pop: outgoing (top) scene is hidden from begin. Overlay masks the hide, * and the destination beneath shows through as the flash tapers. */ declare function flash(opts?: FlashOptions): SceneTransition; interface CrossFadeOptions { /** Duration in seconds. Default: 0.4. */ duration?: number; } /** * Cross-dissolve between two scenes: the outgoing scene fades from full * opacity to zero while the incoming scene fades in. Both scenes remain * visible throughout, so there's no blackout in the middle — good for * menu→game and level→level handoffs. */ declare function crossFade(opts?: CrossFadeOptions): SceneTransition; interface IrisOptions { /** Iris duration in seconds. Default: 0.6. */ duration?: number; /** Fill color visible outside the iris. Default: 0x000000. */ color?: number; /** * Iris center in **virtual-space pixels** — the same coord system you * use for game logic. Default: virtual-space center. The maximum radius * is the distance from this point to the farthest corner of whatever * the overlay covers (virtual rect by default, full canvas under * `coverScreen: true`), so the iris always fully covers its target at * the mid-point. */ center?: { x: number; y: number; }; /** * When `true`, the dip-to-color overlay covers the full canvas * including letterbox / expand bars. When `false` (default), it covers * only the virtual play area — bars stay visible during the dip. */ coverScreen?: boolean; } /** * Iris-out → swap → iris-in. A circular cut-out of the screen shrinks to * zero over the first half (covering everything in `color`), then grows * back over the second half to reveal the destination. Symmetric to * `fade()` but with a circular shape — useful for retro-style transitions * (Zelda overworld→cave, classic Mario level intros). * * Implementation: a fullscreen color overlay carries an inverse circular * mask so the area inside the circle stays transparent (revealing the * scene below) while the outside fills with `color`. The mask is redrawn * each frame to animate the radius. * * - push/replace: incoming scene stays hidden until the half-way mark, * then is revealed underneath the opening iris. * - pop: outgoing scene stays visible through the closing iris, then is * hidden at the half-way mark so the destination shows through during * the opening half. */ declare function iris(opts?: IrisOptions): SceneTransition; interface IrisRevealOptions { /** Iris duration in seconds. Default: 0.6. */ duration?: number; /** * Iris center in virtual-space pixels. Default: virtual-space center. * The maximum radius is the distance from this point to the farthest * corner of the virtual rect, so the iris always fully covers the * canvas at `t = 1`. */ center?: { x: number; y: number; }; /** Easing function applied to the radius. Default: `easeLinear`. */ easing?: EasingFunction; } /** * Reveal the destination scene through an expanding circular mask. The * incoming scene's container is masked by a circle that grows from * radius 0 to a radius covering the canvas, so the new scene "blooms" * over the previous one from the chosen center point. The previous * scene stays visible outside the iris until the circle fully covers * it — no color overlay, no mid-point swap. * * Pairs with `iris()` (the symmetric close-then-open variant): pick * `iris` for retro Zelda-style dip-to-black handoffs, `irisReveal` for * a one-way reveal where the new scene grows over the old. * * On `pop` the destination scene is brought to the front of the scene * stack so the same mechanic applies — without it the outgoing scene * would render over the masked destination. */ declare function irisReveal(opts?: IrisRevealOptions): SceneTransition; interface ChessboardOptions { /** Total duration in seconds. Default: 0.7. */ duration?: number; /** Grid rows. Default: 6. */ rows?: number; /** Grid columns. Default: 10. */ cols?: number; } /** * Reveal the destination scene through a staggered checkerboard mask. The * incoming scene's container is masked by a grid of cells that grow from * a center point to fill their slot — even-parity cells first, odd-parity * second — so the new scene "paints in" cell-by-cell on top of the * previous one. No blackout mid-point and no color overlay: the previous * scene stays visible underneath until each cell of the new scene covers it. * * - Even cells (`(row + col) & 1 === 0`): grow over `[0, 0.7]` * - Odd cells (`(row + col) & 1 === 1`): grow over `[0.3, 1]` * * Pixi v8 Graphics masks are stencil clips (binary in/out, no alpha) — * scaling each cell from 0 to its full size with smoothstep easing produces * the soft per-cell entry that mask-fill alpha can't. The 0.4 overlap means * odd cells start growing while even cells are still mid-grow, removing the * "second wave pops in" jolt at the midpoint. * * On `pop` the destination scene is brought to the front of the scene * stack so the same mechanic applies — without it the outgoing scene * would render over the masked destination. */ declare function chessboard(opts?: ChessboardOptions): SceneTransition; /** Direction the outgoing scene exits the frame in. */ type SlideDirection = "left" | "right" | "up" | "down"; interface SlidePushOptions { /** Total duration in seconds. Default: 0.5. */ duration?: number; /** * Direction the OUTGOING scene exits in. The incoming scene enters from * the opposite edge. Default: `"left"` (incoming slides in from the right, * pushing the previous scene off to the left — book-style forward turn). */ direction?: SlideDirection; /** * When `true` (default), `pop` reverses `direction` so the back motion * mirrors the forward motion — pairs naturally with a scene's * `defaultTransition`. Set to `false` if the call-site direction is * already authored for a specific kind. */ reverseOnPop?: boolean; /** Easing function applied to the slide progress. Default: `easeOutCubic`. */ easing?: EasingFunction; } /** * Slide both scenes off and on together: the incoming scene enters from * one edge while the outgoing scene exits the opposite edge at the same * pace, locked together as a single horizontal/vertical translation. * Ideal for menu carousels, level-to-level book turns, or wizard flows. * * Unlike a pure `slideIn`, this transition translates BOTH containers, * giving the visual impression that the new scene is physically pushing * the old one off the screen. * * On `pop`, the direction is mirrored by default so that "back" reverses * "forward" — opt out via `reverseOnPop: false` for explicit control. */ declare function slidePush(opts?: SlidePushOptions): SceneTransition; /** * Resolve the root container for a scene that participates in a transition. * Returns `undefined` if `scene` is undefined or its tree hasn't been * materialized. Intended for use inside `SceneTransition.begin/tick/end` * so custom transitions can manipulate per-scene containers without * boilerplate. */ declare function getSceneContainer(ctx: SceneTransitionContext, scene: Scene | undefined): DisplayContainer | undefined; /** * Bounds of the declared virtual play area — equivalent to * `renderer.virtualSize`. Use this to size masks, translations, or * geometry that's scoped to a single scene's content (e.g. a per-cell * mask painted onto a scene root). Children of scene roots and of * `_worldRoot` operate in virtual pixels. * * For full-screen overlays parented to `renderer.worldRoot`, prefer * `renderer.visibleCanvasRect` — it equals the virtual rect under * `letterbox` (clipped) but extends into the bars under `expand`, which * is usually what an obscuring overlay wants. For overlays that must * also paint over letterbox bars, parent on `app.stage` and size in * canvas pixels via `app.screen.width / .height`. */ declare function getVirtualBounds(ctx: SceneTransitionContext): { width: number; height: number; }; /** Options for {@link texture}. */ interface TextureOptions { /** * How the GPU samples this texture when it is drawn at a size other than * its own: `"nearest"` keeps pixel-art edges hard, `"linear"` smooths them. * Omit to leave Pixi's default (`"linear"`, or whatever `pixelArtPreset` * set globally). * * The setting lands on the loaded image, so every sprite drawing from it * samples the same way. */ scaleMode?: "nearest" | "linear"; } /** * Create a typed asset handle for a texture. * * ```ts * const Hero = texture("hero.png"); * const Tiles = texture("tiles.png", { scaleMode: "nearest" }); * ``` */ declare function texture(path: string, opts?: TextureOptions): TextureHandle; /** Create a typed asset handle for a spritesheet JSON atlas. */ declare function spritesheet(path: string): AssetHandle; /** Create a typed handle for an arbitrary renderer-managed asset. */ declare function renderAsset(path: string): RendererAsset; /** * Create a typed asset handle for a bitmap font — a BMFont `.fnt`/`.xml` * descriptor plus its glyph atlas. Resolve it through the asset manager * (`engine.assets`) like any other handle; the loaded font registers itself * under the `fontFamily` declared in the descriptor, so pass that same name * as `style.fontFamily` (with `bitmap: true`) on `UIText` / `TextComponent`. * * For runtime-baked fonts from a `.ttf` instead, see {@link installBitmapFont}. */ declare function bitmapFont(path: string): BitmapFontHandle; /** * Declarative atlas-baking config for a {@link webFont} loaded with `bitmap` * set. Mirrors {@link InstallBitmapFontOptions} minus `name` / `family` — the * baked bitmap font registers under the same family as the canvas face, so one * `webFont` name drives both the canvas `Text` and the `BitmapText` registries * (separate registries, no collision). */ interface WebFontBakeOptions { /** Glyph size (px) to bake the atlas at. Default `32`. */ size?: number; /** * Character set to bake. Accepts Pixi's range syntax, e.g. * `[["a", "z"], ["A", "Z"], "0123456789 .,!?"]`. Defaults to Pixi's * alphanumeric set — remember to include a space. */ chars?: string | (string | string[])[]; /** * Atlas resolution multiplier. `2` keeps glyphs crisp when the text is * upscaled by a pixel-art camera. Default `2`. */ resolution?: number; /** Glyph padding in the atlas. Default `4`. */ padding?: number; /** * Extra `TextStyle` props baked into every glyph (fill, stroke, weight, * drop shadow…). `fontFamily` / `fontSize` are managed by the baker. * `fill` defaults to white so per-text `fill` / `tint` can recolour the * glyphs — set it explicitly to bake a fixed colour instead. */ style?: Partial; /** * Weight/style emphasis atlases to bake alongside the base font from the * same source face — the same declarative model as * {@link InstallBitmapFontOptions.variants}. A `BitmapText` whose * `style.fontWeight`/`fontStyle` asks for bold or italic then renders from * the matching synthetic atlas. */ variants?: BitmapFontVariant[]; } /** Options for {@link webFont}. */ interface WebFontOptions { /** * `@font-face` family the loaded face registers under — the name you then * pass as `style.fontFamily` on `Text` / `UIText` / `TextComponent`. * Omit to let Pixi derive it from the file name. */ family?: string; /** * Also bake a bitmap glyph atlas from the loaded face under the same family, * so the one `webFont` name works for both canvas `Text` (no `bitmap`) and * `BitmapText` (`bitmap: true`). `true` bakes with defaults; pass a * {@link WebFontBakeOptions} object to control size, charset, emphasis * variants, and baked style. * * Requires `family` so the baked atlas has a stable name to register under * and uninstall on unload; baking is skipped (with a warning) when `family` * is omitted. * * ```ts * webFont("fonts/Inter.woff2", { family: "Inter", bitmap: { size: 24 } }); * // → canvas Text * // → bitmap atlas * ``` */ bitmap?: boolean | WebFontBakeOptions; } /** * Create a typed asset handle for a plain web font (a `.ttf`/`.woff`/`.woff2` * loaded for canvas `Text`, the canvas sibling of {@link bitmapFont}). Resolve * it through a scene's `preload` so the face is registered before the first * draw — Pixi caches fallback metrics on first paint otherwise, so a font that * loads late never applies. * * Pass `bitmap` to also bake a `BitmapText` atlas from the same face under the * same family, so a single declared font works for both text paths. * * ```ts * class MenuScene extends Scene { * readonly preload = [webFont("fonts/Inter.woff2", { family: "Inter" })]; * // …then: new TextComponent({ text: "Play", style: { fontFamily: "Inter" } }) * } * ``` */ declare function webFont(path: string, opts?: WebFontOptions): WebFontHandle; /** Options for {@link installBitmapFont}. */ interface InstallBitmapFontOptions { /** * Name to register the baked font under. This is what you pass as * `style.fontFamily` (alongside `bitmap: true`) on `UIText` / * `TextComponent`, and what `installBitmapFont` returns. */ name: string; /** Glyph size (px) to bake the atlas at. Default `32`. */ size?: number; /** * Character set to bake. Accepts Pixi's range syntax, e.g. * `[["a", "z"], ["A", "Z"], "0123456789 .,!?"]`. Defaults to Pixi's * alphanumeric set — remember to include a space. */ chars?: string | (string | string[])[]; /** * Atlas resolution multiplier. `2` keeps glyphs crisp when the text is * upscaled by a pixel-art camera. Default `2`. */ resolution?: number; /** Glyph padding in the atlas. Default `4`. */ padding?: number; /** * Extra `TextStyle` props baked into every glyph (fill, stroke, weight, * drop shadow…). `fontFamily` / `fontSize` are managed by this helper. * `fill` defaults to white so per-text `fill` / `tint` can recolour the * glyphs — set it explicitly to bake a fixed colour instead. */ style?: Partial; /** * `@font-face` family the loaded `.ttf` registers under. Defaults to * `name`, so the loaded face and the baked bitmap font share one * coherent identifier. */ family?: string; /** * Bake weight/style emphasis atlases alongside the base font from the same * source `.ttf`, so a `BitmapText` whose `style.fontWeight`/`fontStyle` * asks for bold or italic renders from the matching synthetic atlas instead * of being ignored (canvas `Text` honours those props; plain `BitmapText` * does not). * * Every variant is baked through the same pipeline as the base, then has * its baseline metrics aligned to the base atlas — so a bold span and * regular text sit on one shared baseline with no vertical drift. Variants * register under derived names (`" bold"`, `" italic"`, …); you * never name them yourself. Just set `style.fontWeight: "bold"` on a * `BitmapText` using this font and the bold atlas is selected automatically. * * ```ts * await installBitmapFont("fonts/Body.ttf", { * name: "Body", * variants: [{ fontWeight: "bold" }, { fontStyle: "italic" }], * }); * // → bold atlas * ``` */ variants?: BitmapFontVariant[]; } /** * One weight/style emphasis to bake as a sibling atlas of a base bitmap font. * Identified by the `fontWeight`/`fontStyle` a `BitmapText` will ask for — a * variant only differs from the base along the bold and italic axes, so a * request for `fontWeight: "700"` resolves the atlas baked for * `fontWeight: "bold"`. * * This is the declarative shape the loader-level bitmap-font config reuses, so * the same `variants` array can be authored inline or hung off an asset * manifest. */ interface BitmapFontVariant { /** * Weight to synthesise this variant at. Keyword (`"bold"`) or numeric * string (`"700"`); >= 600 (or `"bold"`/`"bolder"`) selects the bold axis. */ fontWeight?: TextStyle["fontWeight"]; /** Slant to synthesise this variant at — `"italic"` or `"oblique"`. */ fontStyle?: TextStyle["fontStyle"]; /** * Extra `TextStyle` props baked into this variant's glyphs only, layered * over the base font's `style`. `fontFamily` / `fontSize` / * `fontWeight` / `fontStyle` are managed by the variant pipeline. */ style?: Partial; } /** * Load a `.ttf`/`.woff` and bake a bitmap glyph atlas from it via Pixi v8's * `BitmapFont.install`. Returns the registered font name, ready to hand to * `style.fontFamily` (with `bitmap: true`) on `UIText` / `TextComponent`. Pair * with {@link uninstallBitmapFont} to free the atlas when it's no longer used. * * ```ts * const font = await installBitmapFont("fonts/PressStart2P.ttf", { * name: "PressStart", * size: 16, * }); * entity.add( * new TextComponent({ text: "READY", bitmap: true, style: { fontFamily: font } }), * ); * ``` */ declare function installBitmapFont(source: string | AssetHandle, opts: InstallBitmapFontOptions): Promise; /** * Tear down a font installed by {@link installBitmapFont}: drop its source face * and free the baked atlas (and every emphasis variant) plus its registry * entries. The symmetric counterpart of `installBitmapFont` — without it an * install-once font's atlas lives until the page unloads. * * Safe to interleave with a `webFont({ bitmap })` sharing the same family: the * atlas is reference-counted, so it's only destroyed once the last owner (this * install and any web-font load) has released it. A no-op for a name that was * never installed. * * ```ts * const font = await installBitmapFont("fonts/PressStart2P.ttf", { name: "PressStart" }); * // …later, when nothing renders with it anymore: * uninstallBitmapFont(font); * ``` */ declare function uninstallBitmapFont(name: string): void; /** * Register a runtime-created texture under an asset key, so every key-based * surface resolves it exactly like a preloaded asset: `texture: key` on * `SpriteComponent` and on a particle emitter, and `{ sheet: key, frameWidth }` * on a `FrameSource`. * * Registered keys are engine-global and live until {@link unregisterTexture} — * registration is a boot-scoped act, outside the asset manager's ref counts * and unloads. A game-owned save root can store the key, but the game must * re-register runtime textures under the same keys during boot before it * reconstructs scenes and components. Resolving a missing key throws and * names the key. * * Re-registering a key this API still owns replaces the cache entry; * components constructed before the replacement keep the old texture instance * (resolution happens at construction). A key present in the cache but owned * by the asset pipeline — a loaded asset's path, or an asset that overwrote a * stale registration — throws: shadowing a loaded asset would let that asset's * unload destroy the registered texture later. * * ```ts * // The size names the strip's region, so every 32-pixel cell holds one circle. * const strip = renderer.createTexture( * (g) => { * for (let i = 0; i < 4; i++) g.circle(i * 32 + 16, 16, 4 + i * 3).fill(0xffcc00); * }, * { width: 128, height: 32 }, * ); * registerTexture("boss-idle", strip); * entity.add(new AnimatedSpriteComponent({ source: { sheet: "boss-idle", frameWidth: 32 } })); * ``` */ declare function registerTexture(key: string, texture: TextureResource): void; /** * Remove a texture registered by {@link registerTexture}. A no-op for keys * this API never registered. Never destroys the texture — the creator owns * the GPU resource; call `texture.destroy()` once nothing draws it anymore. * * Only evicts the cache entry while it still holds the registered texture: if * an asset preloaded under the same key overwrote it after registration, that * entry belongs to the asset pipeline and is left in place. */ declare function unregisterTexture(key: string): void; /** * Resolve a texture input into a concrete texture resource. Keys and handles * resolve from the global asset cache — preloaded assets and * {@link registerTexture} entries; an unresolvable key throws rather than * handing the caller an empty texture. */ declare function resolveTextureInput(input: TextureInput): TextureResource; /** Options for {@link createNineSlice}. Slice insets follow pixi's `NineSliceSprite`. */ interface NineSliceOptions { /** Frame {@link TextureInput} — handle, asset key, or raw `Texture`. */ readonly texture: TextureInput; /** Left slice-guide inset (source px). */ readonly leftWidth: number; /** Top slice-guide inset (source px). */ readonly topHeight: number; /** Right slice-guide inset (source px). */ readonly rightWidth: number; /** Bottom slice-guide inset (source px). */ readonly bottomHeight: number; /** Rendered width (px) the frame stretches to. */ readonly width: number; /** Rendered height (px) the frame stretches to. */ readonly height: number; } /** * Build a `NineSliceSprite` from an engine-resolved {@link TextureInput} — a * stretchable textured frame whose corners stay crisp at any size. Returns the * raw display object so callers can parent it into their own container, the * same escape-hatch shape as {@link resolveTextureInput}. This is the renderer's * nine-slice primitive: reach for it (not a direct `pixi.js` import) when * building textured panels, dialogue/UI frames, or buttons. * * `width`/`height` are required: a nine-slice is stretched to a target size, and * defaulting to the (possibly unloaded → 0×0) texture size would silently bake a * degenerate frame. */ declare function createNineSlice(options: NineSliceOptions): NineSliceSprite; /** Inputs for {@link measureWrappedText}. */ interface MeasureTextOptions { /** Canvas font family (or a baked bitmap-font name when `bitmap`). */ readonly fontFamily?: string; /** Font size in px. */ readonly fontSize: number; /** Vertical advance per line in px (defaults to the font's natural height). */ readonly lineHeight?: number; /** Wrap width in px. Omit or `<= 0` to measure a single unwrapped line. */ readonly wordWrapWidth?: number; /** * Measure via the bitmap-font path (`BitmapFontManager`): `fontFamily` names * a baked atlas. Wrap-aware like the canvas path, and returns px (the atlas's * base-unit metrics are scaled to `fontSize`). */ readonly bitmap?: boolean; } /** Natural laid-out size of a (optionally wrapped) text string. */ interface MeasuredText { readonly width: number; readonly height: number; /** Number of laid-out lines (wrap-aware on the canvas path; `>= 1`). */ readonly lineCount: number; } /** * Measure the natural size of a text string — wrap-aware — without constructing * a live text node. This is the renderer's text-metrics primitive: reach for it * (not a direct `pixi.js` import) when a layout needs to size a panel to its * text (e.g. a content-sized dialogue bubble). * * Both paths honour `wordWrapWidth`, so `lineCount` reflects the wrapped line * count: canvas via Pixi's `CanvasTextMetrics`, bitmap via `BitmapFontManager` * (whose base-unit metrics are scaled to `fontSize`, matching what a * `BitmapText` renders at). Measurement resolves the engine-level * `defaultTextStyle` under the given options — the same merge the render path * applies — so the measured box matches the drawn text. * * Requires a DOM/canvas at runtime (the browser) for the canvas path; unit tests * mock `CanvasTextMetrics` (there is no canvas under the node test env). */ declare function measureWrappedText(text: string, options: MeasureTextOptions): MeasuredText; /** Slice a texture input into an array of frame textures. */ declare function sliceTextureFrames(input: TextureInput, options: TextureSliceOptions): TextureResource[]; /** * Internal: a list of attached effects bound to one pixi `Container`. * * - Coexists with external `displayObject.filters` assignments. The stack * tracks the filter instances it owns; any other filter present on the * target at sync time is treated as external and preserved (placed before * the stack's owned filters in the chain, so user filters render first * and stack effects composite on top). * - `fadeIn` / `fadeOut` are implemented via `Tween.custom`, scheduled on * the supplied `ScopedProcessQueue`. Per-effect processes are tracked so * `handle.remove()` cancels in-flight fades for that effect rather than * letting them keep firing `setIntensity` after detach. * * @internal */ declare class EffectStack { private readonly displayObject; private readonly queue; private readonly scope; private readonly entries; private readonly handles; private readonly ownedFilters; private readonly effectProcesses; private destroyed; private detachBounds; constructor(displayObject: DisplayContainer, queue: ScopedProcessQueue, scope: EffectScope); /** Build and attach an effect, returning its handle. */ add(factory: EffectFactory): H; /** Number of attached effects. */ get size(): number; /** * Find the handle for the first effect in the stack built from a * `defineEffect` definition with the given `name`. * * Returns `undefined` if no matching entry exists. If the stack holds * multiple entries with the same definition name, the first one * encountered (insertion order) is returned. */ findHandle(definitionName: string): EffectHandle | undefined; /** Tear down every attached effect and cancel any in-flight tweens. */ destroy(): void; private removeEffect; private syncFilters; } /** Options for {@link rawFilter}. */ interface RawFilterOptions { /** * Optional accessor for the filter's primary intensity uniform. If * provided, `fadeIn` / `fadeOut` on the resulting handle will tween it. * If omitted, fades become no-ops and a one-shot dev warning fires. */ intensity?: { get: () => number; set: (value: number) => void; }; } /** * Wrap a user-supplied pixi `Filter` so it can be attached through the * `addEffect` API and managed by the same handle interface as built-in * effect presets. The escape hatch for custom shaders or any pixi-filters * import the engine doesn't expose a typed wrapper for. * * ```ts * import { BlurFilter } from "pixi.js"; * * const filter = new BlurFilter({ strength: 8 }); * sprite.fx.addEffect(rawFilter(filter, { * intensity: { * get: () => filter.strength / 8, * set: (v) => { filter.strength = v * 8; }, * }, * })); * ``` * * Without the `intensity` option, `fadeIn` / `fadeOut` will return an * already-completed Process and warn once per session — the system can't * guess which uniform represents the effect's "strength." */ declare function rawFilter(filter: Filter, options?: RawFilterOptions): EffectFactory; /** * Apply a mask to any pixi `Container`. Returns a {@link MaskHandle} that * controls the mask's lifecycle and inverse state. * * The high-level `setMask` methods on the visual components, `RenderLayer`, * and `SceneRenderTree` are thin wrappers around this — use those when you * have one of those targets in hand. Reach for `attachMask` directly when * you only have a raw `Container` (e.g. `UIPanel` masking its own root). * * Idempotent on `remove()`. The handle's `setInverse` toggles * pixi v8 `Container.setMask({ mask, inverse })`. * * Pass `owner` when a component holds the mask: a throw from the game's own * draw callback is then attributed to the callback (readable via * `Inspector.getErrors().callbackErrors`) instead of to whichever engine pass * triggered the redraw. */ declare function attachMask(target: DisplayContainer, factory: MaskFactory, owner?: Component): MaskHandle; /** * Named mask definition. Mirrors {@link EffectDefinition}. The callable * shape `(options) => MaskFactory` is what users invoke (`rectMask({ ... })`). */ interface MaskDefinition { (options: O): MaskFactory; readonly name: string; } /** * Define a named mask preset. The returned callable accepts the preset's * options and yields a `MaskFactory`. */ declare function defineMask(spec: { name: string; factory: (options: O) => Mask; }): MaskDefinition; /** Options for {@link rectMask}. */ interface RectMaskOptions { x: number; y: number; width: number; height: number; /** Corner radius in pixels. Omit or pass 0 for a sharp rectangle. */ rounded?: number; } /** * Build a static rectangular mask. The renderer owns the underlying * `Graphics` node and destroys it on `remove()`. * * `x`/`y`/`width`/`height` are in the masked object's own local space, which * is world pixels on a world layer — the mask then scrolls with the camera — * and virtual pixels on a screen layer, where it stays put. * * For a mask that needs to update with the target's dimensions (e.g. a * layout-driven panel), use {@link graphicsMask} so you can call * `handle.redraw()` after each layout pass. */ declare const rectMask: MaskDefinition; /** * Use a caller-supplied `Sprite` as a mask — the sprite's alpha channel * defines the visible region. Useful for soft-edged or texture-driven * clipping (vignettes, organic frames) that a Graphics shape can't express. * * Ownership stays with the caller: the sprite is NOT parented or destroyed * by the mask system. Make sure it's already in the display tree * (typically as a child of the target or a hidden sibling) before calling * `setMask`, or pixi will silently fail to apply the mask. */ declare function spriteMask(sprite: DisplaySprite): MaskFactory; /** * Build a procedurally-drawn mask from a `Graphics` callback. The renderer * owns the `Graphics` node, runs `draw(g)` once at attach time, and re-runs * it whenever you call `handle.redraw()` — typically after a layout pass * changes the dimensions the closure references. * * ```ts * const handle = attachMask(panel.container, graphicsMask((g) => { * g.clear(); * g.rect(0, 0, panel.width, panel.height); * g.fill({ color: 0xffffff }); * })); * // …after layout changes: * handle.redraw(); * ``` * * Everything the callback draws is in the masked object's own local space, * which is world pixels on a world layer — the mask then scrolls with the * camera — and virtual pixels on a screen layer, where it stays put. * * **Two gotchas:** * * 1. **Always `g.clear()` first.** Pixi `Graphics` commands accumulate, so * without `clear()` each `redraw()` layers another shape on top of the * previous one. We don't auto-clear — some draws intentionally compose. * 2. **Read live state inside the closure, don't snapshot it outside.** JS * closures capture variable bindings, not values; if you save a number * into a `const` and reference that, `redraw()` keeps using the original * number. Reach through to a live source — a property access on a * captured object, a method call, a getter — so each invocation pulls * the current value: * * ```ts * // ❌ Stale — captures const value * const w = 200, h = 100; * graphicsMask((g) => { g.clear(); g.rect(0, 0, w, h).fill(0xffffff); }); * * // ✅ Fresh — reads live state every call * graphicsMask((g) => { * g.clear(); * g.rect(0, 0, panel.width, panel.height).fill(0xffffff); * }); * ``` */ declare function graphicsMask(draw: (g: GraphicsContext) => void): MaskFactory; /** Apply a camera's effective pose. Without a camera, restore identity. */ declare function syncCameraTransform(target: DisplayContainer, camera?: CameraComponent, binding?: CameraBinding): void; export { AnimatedSpriteComponent, type AnimatedSpriteComponentOptions, AnimationController, type AnimationDef, type AnimationOneShotOptions, type AnimationTimingOptions, type AtlasFrameSource, BitmapFontHandle, type BitmapFontVariant, BlendMode, type CameraBinding, type CameraBounds, CameraBoundsComponent, CameraComponent, type CameraComponentOptions, CameraEntity, type CameraEntityParams, type CameraFitToRect, CameraFollow, type CameraFollowOptions, type CameraModifierHandle, CameraModifierHost, type CameraModifierOptions, CameraShake, type CameraShakeOptions, CameraZoom, type ChessboardOptions, ColorValue, type CrossFadeOptions, DestroyOptions, DisplayAnimatedSprite, DisplayBitmapText, DisplayContainer, DisplaySplitBitmapText, DisplaySplitText, DisplaySprite, DisplaySystem, DisplayText, EffectFactory, EffectHandle, EffectScope, EffectStack, EffectsHost, type FadeOptions, Filter, type FlashOptions, type FollowTarget, type FrameSource, GradientFill, type GradientSpace, type GradientStop, GraphicsComponent, type GraphicsComponentOptions, GraphicsContext, type InstallBitmapFontOptions, type IrisOptions, type IrisRevealOptions, type LayerRenderable, LayerSortFn, LayeredAnimationController, type LayeredAnimationControllerOptions, type LinearGradientOptions, Mask, type MaskDefinition, MaskFactory, MaskHandle, type MeasureTextOptions, type MeasuredText, type NineSliceOptions, NineSliceSprite, type RadialGradientOptions, type RawFilterOptions, type RectMaskOptions, RenderFacetContributor, type RenderFacetSnapshot, type RenderInspectable, RendererAsset, SceneRenderTree, SceneRenderTreeProvider, SceneRenderTreeProviderImpl, ScreenFollow, type ScreenFollowOptions, type ScreenFollowTarget, type SegmentAnchor, type SheetFrameSource, type SlideDirection, type SlidePushOptions, SortGroupComponent, type SortGroupComponentOptions, SplitTextComponent, type SplitTextComponentOptions, type SplitTextRenderFacet, type SplitTextRenderFacetExtras, SpriteComponent, type SpriteComponentOptions, TextComponent, type TextComponentOptions, TextStyle, TextureHandle, TextureInput, type TextureOptions, TextureRef, TextureResource, TextureSliceOptions, VisualComponent, type VisualComponentOptions, type VisualInteractiveOptions, VisualModifierHost, type VisualOpacityModifierHandle, type VisualTransformModifierHandle, type VisualTransformModifierOptions, type VisualVisibilityModifierHandle, type WebFontBakeOptions, WebFontHandle, type WebFontOptions, attachMask, bitmapFont, buildTextOptions, chessboard, createNineSlice, crossFade, defineMask, fade, flash, getDefaultTextStyle, getSceneContainer, getVirtualBounds, graphicsMask, initialAutoSplit, installBitmapFont, iris, irisReveal, isAtlasSource, isSheetSource, linearGradient, measureWrappedText, radialGradient, rawFilter, rectMask, registerTexture, renderAsset, resolveFrames, resolveRenderParent, resolveTextStyle, resolveTextureInput, setDefaultTextStyle, setSplitText, sliceGrid, sliceSheet, sliceTextureFrames, slidePush, splitIfNotEmpty, spriteMask, spritesheet, syncCameraTransform, texture, uninstallBitmapFont, unregisterTexture, webFont, ySort, ySortBy };