textmode.js 0.8.1 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/textmode.esm.js +2150 -1860
  2. package/dist/textmode.umd.js +16 -16
  3. package/dist/types/Textmode.d.ts +1 -12
  4. package/dist/types/exports/conversion.d.ts +1 -0
  5. package/dist/types/exports/filters.d.ts +1 -0
  6. package/dist/types/exports/input.d.ts +1 -0
  7. package/dist/types/exports/layering.d.ts +1 -0
  8. package/dist/types/exports/loadables.d.ts +1 -0
  9. package/dist/types/exports/loading.d.ts +1 -0
  10. package/dist/types/exports/plugins.d.ts +1 -0
  11. package/dist/types/index.d.ts +35 -1
  12. package/dist/types/rendering/webgl/core/Framebuffer.d.ts +1 -1
  13. package/dist/types/rendering/webgl/core/Shader.d.ts +17 -3
  14. package/dist/types/rendering/webgl/core/interfaces/IFramebuffer.d.ts +1 -8
  15. package/dist/types/textmode/AnimationController.d.ts +39 -0
  16. package/dist/types/textmode/Grid.d.ts +2 -0
  17. package/dist/types/textmode/Textmodifier.d.ts +8 -15
  18. package/dist/types/textmode/interfaces/ITextmodifier.d.ts +9 -13
  19. package/dist/types/textmode/layers/LayerManager.d.ts +41 -25
  20. package/dist/types/textmode/layers/TextmodeLayer.d.ts +11 -52
  21. package/dist/types/textmode/layers/interfaces/ILayerManager.d.ts +5 -0
  22. package/dist/types/textmode/layers/interfaces/ITextmodeLayer.d.ts +45 -2
  23. package/dist/types/textmode/managers/PluginManager.d.ts +157 -9
  24. package/dist/types/textmode/mixins/interfaces/IAnimationMixin.d.ts +153 -1
  25. package/dist/types/textmode/mixins/interfaces/IRenderingMixin.d.ts +8 -0
  26. package/dist/types/textmode/types.d.ts +4 -3
  27. package/dist/types/utils/TextmodeCollection.d.ts +262 -0
  28. package/dist/types/utils/math.d.ts +26 -0
  29. package/package.json +37 -2
@@ -24,18 +24,7 @@ export declare class Textmode {
24
24
  * t.rect(10, 10);
25
25
  * });
26
26
  * ```
27
- * @exampleAuthor
28
- * <div style="display:flex;align-items:center;gap:0.75rem;flex-wrap:wrap;">
29
- * <img src="https://github.com/humanbydefinition.png" alt="@humanbydefinition avatar" width="72" height="72" style="border-radius:12px;box-shadow:0 2px 6px rgba(0,0,0,0.35);" />
30
- * <div style="display:flex;flex-direction:column;gap:0.25rem;">
31
- * <strong><a href="https://github.com/humanbydefinition">@humanbydefinition</a></strong>
32
- * <span style="font-size:0.95em;">
33
- * 📷 <a href="https://instagram.com/humanbydefinition">Instagram</a>
34
- * &nbsp;•&nbsp; 🐘 <a href="https://mastodon.social/@humanbydefinition">Mastodon</a>
35
- * &nbsp;•&nbsp; 🦋 <a href="https://bsky.app/profile/humanbydefinition.bsky.social">BlueSky</a>
36
- * </span>
37
- * </div>
38
- * </div>
27
+ * <!-- example-author: humanbydefinition -->
39
28
  */
40
29
  static create(opts?: TextmodeOptions): Textmodifier;
41
30
  /**
@@ -0,0 +1 @@
1
+ export * from '../textmode/conversion';
@@ -0,0 +1 @@
1
+ export * from '../textmode/filters';
@@ -0,0 +1 @@
1
+ export * from '../textmode/managers';
@@ -0,0 +1 @@
1
+ export * from '../textmode/layers';
@@ -0,0 +1 @@
1
+ export * from '../textmode/loadables';
@@ -0,0 +1 @@
1
+ export * from '../textmode/loading';
@@ -0,0 +1 @@
1
+ export type { TextmodePlugin, TextmodePluginAPI, TextmodePluginHook, LayerLifecycleHook, LayerRenderHook, SetupLifecycleHook, } from '../textmode/managers/PluginManager';
@@ -16,7 +16,40 @@ export type { TextmodeFramebufferOptions } from './rendering/webgl';
16
16
  * but custom strategies can be registered via {@link TextmodeConversionManager.register}.
17
17
  */
18
18
  export * as conversion from './textmode/conversion';
19
- export type { TextmodePlugin, TextmodePluginAPI } from './textmode/managers/PluginManager';
19
+ /**
20
+ * Plugin system types for extending textmode.js functionality.
21
+ *
22
+ * Plugins can:
23
+ * - Add methods to TextmodeLayer instances (e.g., `.synth()`)
24
+ * - Hook into the render lifecycle (pre/post draw, per-layer rendering)
25
+ * - React to layer creation and disposal events
26
+ * - Access the WebGL renderer, framebuffers, and other internals
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import type { TextmodePlugin, TextmodePluginAPI } from 'textmode.js/plugins';
31
+ *
32
+ * const MyPlugin: TextmodePlugin = {
33
+ * name: 'my-plugin',
34
+ * version: '1.0.0',
35
+ * install(textmodifier, api) {
36
+ * // Extend layers with a new method
37
+ * api.extendLayer('myMethod', function(value) {
38
+ * this.setPluginState('my-plugin', { value });
39
+ * });
40
+ *
41
+ * // Hook into layer rendering
42
+ * api.registerLayerPreRenderHook((layer, ctx) => {
43
+ * const state = layer.getPluginState('my-plugin');
44
+ * if (state) {
45
+ * // Render plugin content to layer.drawFramebuffer
46
+ * }
47
+ * });
48
+ * }
49
+ * };
50
+ * ```
51
+ */
52
+ export * as plugins from './textmode/managers/PluginManager';
20
53
  /**
21
54
  * All filter related modules and types.
22
55
  *
@@ -28,6 +61,7 @@ export type { TextmodePlugin, TextmodePluginAPI } from './textmode/managers/Plug
28
61
  */
29
62
  export * as filters from './textmode/filters';
30
63
  export { TextmodeErrorLevel } from './errors/ErrorHandler';
64
+ export { GLShader as TextmodeShader } from './rendering/webgl/core/Shader';
31
65
  export { Textmode as textmode } from './Textmode';
32
66
  /** All loading screen related modules and types. */
33
67
  export * as loading from './textmode/loading';
@@ -81,7 +81,7 @@ export declare class GLFramebuffer implements IFramebuffer {
81
81
  * @ignore
82
82
  */
83
83
  private _updateMaterial;
84
- $dispose(): void;
84
+ dispose(): void;
85
85
  /** Get the width of the framebuffer */
86
86
  get width(): number;
87
87
  /** Get the height of the framebuffer */
@@ -4,8 +4,13 @@ import { GLFramebuffer } from './Framebuffer';
4
4
  */
5
5
  export type UniformValue = number | boolean | number[] | number[][] | Float32Array | Int32Array | GLFramebuffer | WebGLTexture;
6
6
  /**
7
- * WebGL implementation of the shader abstraction.
8
- * Provides GPU shader program management with automatic uniform handling and minification support.
7
+ *
8
+ * Shader class for managing WebGL shader programs initialized via {@link Textmodifier.createFilterShader} or {@link Textmodifier.createShader}.
9
+ *
10
+ * Use shaders and set uniforms via {@link Textmodifier.shader}, {@link Textmodifier.setUniform}, and {@link Textmodifier.setUniforms}.
11
+ *
12
+ * With a shader active, the next {@link Textmodifier.rect} call will use the shader for rendering,
13
+ * and automatically unuse it afterwards.
9
14
  */
10
15
  export declare class GLShader {
11
16
  private _gl;
@@ -28,22 +33,31 @@ export declare class GLShader {
28
33
  private _createShader;
29
34
  /**
30
35
  * Use this shader program
36
+ * @ignore
31
37
  */
32
38
  $use(): void;
33
39
  /**
34
40
  * Reset texture unit counter and other state
35
41
  */
36
42
  private _resetState;
43
+ /**
44
+ * Set multiple uniform values at once.
45
+ * @param uniforms An object mapping uniform names to their values.
46
+ * @ignore
47
+ */
37
48
  $setUniforms(uniforms: Record<string, any>): void;
38
49
  /**
39
50
  * Set a single uniform value with automatic texture unit management and proper type detection
51
+ * @param name The name of the uniform variable in the shader
52
+ * @param value The value to set for the uniform
53
+ * @ignore
40
54
  */
41
55
  $setUniform(name: string, value: UniformValue): void;
42
56
  private _acquireTextureUnit;
43
57
  /**
44
58
  * Get the WebGL program
45
59
  */
46
- get $glProgram(): WebGLProgram;
60
+ get program(): WebGLProgram;
47
61
  /**
48
62
  * Dispose of WebGL resources used by this shader.
49
63
  */
@@ -89,15 +89,8 @@ export interface IFramebuffer {
89
89
  /**
90
90
  * Dispose of WebGL resources used by this framebuffer.
91
91
  *
92
- * This releases:
93
- * - The WebGL framebuffer object
94
- * - All associated texture objects
95
- * - Any cached pixel data
96
- *
97
92
  * This method is idempotent and safe to call multiple times.
98
93
  * After disposal, the framebuffer should not be used for rendering.
99
- *
100
- * @ignore
101
94
  */
102
- $dispose(): void;
95
+ dispose(): void;
103
96
  }
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export declare class AnimationController {
6
6
  private _frameInterval;
7
+ private _targetFrameRate;
7
8
  private _animationFrameId;
8
9
  private _lastFrameTime;
9
10
  private _isLooping;
@@ -11,7 +12,9 @@ export declare class AnimationController {
11
12
  private _lastRenderTime;
12
13
  private _frameTimeHistory;
13
14
  private _frameTimeHistorySize;
15
+ private _deltaTime;
14
16
  private _frameCount;
17
+ private _millisStart;
15
18
  /**
16
19
  * Creates an AnimationController instance.
17
20
  * @param frameRateLimit Maximum frames per second. Defaults to 60.
@@ -55,6 +58,15 @@ export declare class AnimationController {
55
58
  * Get the current measured frame rate.
56
59
  */
57
60
  get $currentFrameRate(): number;
61
+ /**
62
+ * Get the target frame rate limit.
63
+ */
64
+ get $targetFrameRate(): number;
65
+ /**
66
+ * Set the target frame rate limit.
67
+ * @param value The new target frame rate in frames per second
68
+ */
69
+ set $targetFrameRate(value: number);
58
70
  /**
59
71
  * Get the current frame count.
60
72
  */
@@ -68,4 +80,31 @@ export declare class AnimationController {
68
80
  * Should be called on each render to track total frames rendered.
69
81
  */
70
82
  $incrementFrame(): void;
83
+ /**
84
+ * Get the number of milliseconds since the animation started.
85
+ * Returns 0 if the animation has not started yet.
86
+ */
87
+ get $millis(): number;
88
+ /**
89
+ * Set the elapsed milliseconds by adjusting the start time.
90
+ * This allows seeking/scrubbing in animations.
91
+ * @param value The new elapsed time in milliseconds
92
+ */
93
+ set $millis(value: number);
94
+ /**
95
+ * Get the number of seconds since the animation started.
96
+ * Returns 0 if the animation has not started yet.
97
+ */
98
+ get $secs(): number;
99
+ /**
100
+ * Set the elapsed seconds by adjusting the start time.
101
+ * This allows seeking/scrubbing in animations.
102
+ * @param value The new elapsed time in seconds
103
+ */
104
+ set $secs(value: number);
105
+ /**
106
+ * Get the time in milliseconds between the current frame and the last frame.
107
+ * Useful for frame-rate-independent animations.
108
+ */
109
+ get $deltaTime(): number;
71
110
  }
@@ -80,6 +80,8 @@ export declare class TextmodeGrid {
80
80
  get offsetY(): number;
81
81
  /**
82
82
  * Restores responsive sizing so subsequent `t.resizeCanvas` calls recompute cols/rows.
83
+ *
84
+ * A grid becomes non-responsive when either `cols` or `rows` is manually set.
83
85
  */
84
86
  responsive(): void;
85
87
  /**
@@ -7,8 +7,8 @@ import { AnimationController } from './AnimationController';
7
7
  import { MouseManager } from './managers/MouseManager';
8
8
  import { KeyboardManager } from './managers/KeyboardManager';
9
9
  import { TouchManager } from './managers/TouchManager';
10
+ import { TextmodePluginManager } from './managers/PluginManager';
10
11
  import type { ITextmodifier } from './interfaces';
11
- import type { GLShader } from '../rendering';
12
12
  import type { TextmodeOptions } from './types';
13
13
  import type { IAnimationMixin } from './mixins/interfaces/IAnimationMixin';
14
14
  import type { IRenderingMixin } from './mixins/interfaces/IRenderingMixin';
@@ -17,8 +17,8 @@ import type { ITouchMixin } from './mixins/interfaces/ITouchMixin';
17
17
  import type { IMouseMixin } from './mixins/interfaces/IMouseMixin';
18
18
  import { LoadingScreenManager } from './loading/LoadingScreenManager';
19
19
  import { LayerManager } from './layers/LayerManager';
20
- import type { TextmodeLayerManager } from './layers';
21
- import { TextmodeFilterManager } from './filters';
20
+ import type { TextmodeLayer, TextmodeLayerManager } from './layers';
21
+ import type { TextmodeFilterManager } from './filters';
22
22
  import type { FilterName, BuiltInFilterName, BuiltInFilterParams } from './filters';
23
23
  import { TextmodeConversionManager } from './conversion';
24
24
  declare const Textmodifier_base: {
@@ -40,23 +40,16 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
40
40
  _touchManager: TouchManager;
41
41
  _keyboardManager: KeyboardManager;
42
42
  _loading: LoadingScreenManager;
43
- _textmodeConversionShader: GLShader;
44
- _presentShader: GLShader;
45
43
  _layerManager: TextmodeLayerManager;
46
- _activeFont?: TextmodeFont;
47
- _activeGrid?: TextmodeGrid;
48
- _filterManager: TextmodeFilterManager;
44
+ _activeLayer?: TextmodeLayer;
49
45
  _conversionManager: TextmodeConversionManager;
50
- private _globalFilterQueue;
51
- private _preFilterFramebuffer;
52
- private _postFilterFramebuffer;
53
- private _pluginManager;
46
+ /** @ignore */
47
+ _pluginManager: TextmodePluginManager;
54
48
  private _destroyRequested;
55
49
  private _isRenderingFrame;
56
50
  private _isDisposed;
57
51
  private _setupComplete;
58
52
  private _setupCallback;
59
- private _drawCallback;
60
53
  private _resizedCallback;
61
54
  private _windowResizeListener;
62
55
  private _resizeObserver?;
@@ -81,17 +74,16 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
81
74
  private _performDestroy;
82
75
  filter<T extends BuiltInFilterName>(name: T, params?: BuiltInFilterParams[T]): void;
83
76
  filter(name: FilterName, params?: unknown): void;
77
+ draw(callback: () => void): void;
84
78
  loadFont(fontSource: string): Promise<TextmodeFont>;
85
79
  fontSize(size: number): void;
86
80
  inputGrid(target?: 'topmost' | TextmodeGrid): 'topmost' | TextmodeGrid | void;
87
81
  /**
88
82
  * Get the grid used for input coordinate mapping.
89
83
  * Returns the override grid/layer's grid if set, otherwise the topmost visible layer's grid.
90
- * @ignore
91
84
  */
92
85
  private _getInputGrid;
93
86
  setup(callback: () => void | Promise<void>): Promise<void>;
94
- draw(callback: () => void): void;
95
87
  windowResized(callback: () => void): void;
96
88
  get grid(): TextmodeGrid | undefined;
97
89
  get font(): TextmodeFont;
@@ -104,6 +96,7 @@ export declare class Textmodifier extends Textmodifier_base implements ITextmodi
104
96
  get layers(): LayerManager;
105
97
  get filters(): TextmodeFilterManager;
106
98
  get conversions(): TextmodeConversionManager;
99
+ get isRenderingFrame(): boolean;
107
100
  }
108
101
  export interface Textmodifier extends IRenderingMixin, IAnimationMixin, IMouseMixin, ITouchMixin, IKeyboardMixin {
109
102
  }
@@ -3,7 +3,6 @@ import type { TextmodeFont } from '../loadables/font';
3
3
  import type { TextmodeImage } from '../loadables/TextmodeImage';
4
4
  import type { TextmodeCanvas } from '../Canvas';
5
5
  import type { AnimationController } from '../AnimationController';
6
- import type { GLShader } from '../../rendering';
7
6
  import type { GLRenderer } from '../../rendering/webgl/core/Renderer';
8
7
  import type { MouseManager } from '../managers/MouseManager';
9
8
  import type { KeyboardManager } from '../managers/KeyboardManager';
@@ -15,6 +14,7 @@ import type { IMouseMixin } from '../mixins/interfaces/IMouseMixin';
15
14
  import type { IAnimationMixin } from '../mixins/interfaces/IAnimationMixin';
16
15
  import type { LoadingScreenManager } from '../loading/LoadingScreenManager';
17
16
  import type { TextmodeLayerManager } from '../layers';
17
+ import type { TextmodeLayer } from '../layers/TextmodeLayer';
18
18
  import type { BuiltInFilterName, BuiltInFilterParams, TextmodeFilterManager, FilterName } from '../filters';
19
19
  import type { TextmodeConversionManager } from '../conversion';
20
20
  /**
@@ -38,22 +38,14 @@ export interface ITextmodifier extends IRenderingMixin, IAnimationMixin, IMouseM
38
38
  readonly _touchManager: TouchManager;
39
39
  /** Keyboard interaction manager @ignore */
40
40
  readonly _keyboardManager: KeyboardManager;
41
- /** Shader used for converting pixels to textmode grid format @ignore */
42
- readonly _textmodeConversionShader: GLShader;
43
- /** Shader used for final presentation to the screen @ignore */
44
- readonly _presentShader: GLShader;
45
41
  /** Loading screen manager for boot-time UX @ignore */
46
42
  readonly _loading: LoadingScreenManager;
47
43
  /** Conversion manager for image-to-ASCII conversion @ignore */
48
44
  readonly _conversionManager: TextmodeConversionManager;
49
- /** Filter manager for applying post-processing effects @ignore */
50
- readonly _filterManager: TextmodeFilterManager;
51
45
  /** Layer manager for handling multiple layers @ignore */
52
46
  readonly _layerManager: TextmodeLayerManager;
53
- /** Active font based on layer, or loading screen font override @ignore */
54
- _activeFont?: TextmodeFont;
55
- /** Active grid based on layer currently being rendered @ignore */
56
- _activeGrid?: TextmodeGrid;
47
+ /** Active layer currently being rendered @ignore */
48
+ _activeLayer?: TextmodeLayer;
57
49
  /** Main render method @ignore */
58
50
  $render(): void;
59
51
  /**
@@ -117,7 +109,7 @@ export interface ITextmodifier extends IRenderingMixin, IAnimationMixin, IMouseM
117
109
  * - The specific `TextmodeGrid` if locked
118
110
  *
119
111
  * @example
120
- * ```javascript
112
+ * ```js
121
113
  * const t = textmode.create();
122
114
  *
123
115
  * // Add a UI layer on top
@@ -131,7 +123,7 @@ export interface ITextmodifier extends IRenderingMixin, IAnimationMixin, IMouseM
131
123
  *
132
124
  * t.draw(() => {
133
125
  * // Mouse positions now always use base layer's grid
134
- * t.text(`Mouse: ${t.mouseX}, ${t.mouseY}`, 0, 0);
126
+ * console.log(`Mouse: ${t.mouseX}, ${t.mouseY}`);
135
127
  * });
136
128
  *
137
129
  * // Switch back to responsive mode
@@ -446,4 +438,8 @@ export interface ITextmodifier extends IRenderingMixin, IAnimationMixin, IMouseM
446
438
  * ```
447
439
  */
448
440
  readonly loading: LoadingScreenManager;
441
+ /**
442
+ * Check if rendering is currently in progress for this frame.
443
+ */
444
+ readonly isRenderingFrame: boolean;
449
445
  }
@@ -5,12 +5,14 @@ import type { TextmodeLayerOptions } from './types';
5
5
  import type { ILayerManager } from './interfaces/ILayerManager';
6
6
  import type { TextmodeOptions } from '../types';
7
7
  import type { TextmodeGrid } from '../Grid';
8
+ import { type FilterName, type BuiltInFilterName, type BuiltInFilterParams, TextmodeFilterManager } from '../filters';
8
9
  /**
9
10
  * Manages all user-defined layers within a Textmodifier in addition to the base layer.
10
11
  *
11
- * This manager is responsible for:
12
+ * Responsibilities:
12
13
  * - Managing the collection of user layers (add, remove, move, swap)
13
14
  * - Coordinating layer rendering and compositing
15
+ * - Owning the global post-processing pipeline (global filters + present to screen)
14
16
  *
15
17
  * The instance of this class can be accessed via {@link Textmodifier.layers}.
16
18
  *
@@ -19,13 +21,17 @@ import type { TextmodeGrid } from '../Grid';
19
21
  export declare class LayerManager implements ILayerManager {
20
22
  private readonly _textmodifier;
21
23
  private readonly _renderer;
22
- private readonly _conversionShader;
23
24
  private readonly _compositor2D;
24
- private _pendingLayers;
25
- private _layers;
25
+ private readonly _filterManager;
26
+ private readonly _textmodeConversionShader;
27
+ private readonly _presentShader;
28
+ private readonly _layers;
26
29
  private readonly _baseLayer;
27
30
  private _isReady;
28
31
  private readonly _gridDimensionChangeCallbacks;
32
+ private _globalFilterQueue;
33
+ private _preFilterFramebuffer;
34
+ private _postFilterFramebuffer;
29
35
  /**
30
36
  * Create a new LayerManager.
31
37
  * @param textmodifier The Textmodifier instance this manager belongs to.
@@ -33,42 +39,64 @@ export declare class LayerManager implements ILayerManager {
33
39
  */
34
40
  constructor(textmodifier: Textmodifier, opts: TextmodeOptions);
35
41
  /**
36
- * Initialize all pending layers and the compositor.
42
+ * Initialize all pending layers, compositor, and global post-processing resources.
37
43
  * @ignore
38
44
  */
39
45
  $initialize(): Promise<void>;
46
+ /**
47
+ * Queue a global filter to be applied after all layers are composited.
48
+ * Intended to be called by Textmodifier.filter().
49
+ * @ignore
50
+ */
51
+ $queueGlobalFilter<T extends BuiltInFilterName>(name: T, params?: BuiltInFilterParams[T]): void;
52
+ $queueGlobalFilter(name: FilterName, params?: unknown): void;
53
+ /**
54
+ * Clear any queued global filters for the current frame.
55
+ * @ignore
56
+ */
57
+ $clearGlobalFilterQueue(): void;
40
58
  add(options?: TextmodeLayerOptions): TextmodeLayer;
41
59
  remove(layer: TextmodeLayer): void;
42
60
  move(layer: TextmodeLayer, newIndex: number): void;
43
61
  swap(layerA: TextmodeLayer, layerB: TextmodeLayer): void;
62
+ /**
63
+ * Remove and dispose all user layers (keeps base layer intact).
64
+ */
44
65
  clear(): void;
45
66
  /**
46
- * Render all layers (base and user) and composite them to the target framebuffer.
67
+ * Render all layers (base and user) and composite them to the provided target framebuffer.
68
+ * This performs ONLY layer rendering + compositing (no global filters, no present).
69
+ *
47
70
  * @param targetFramebuffer The framebuffer to render the final composited result to.
48
- * @param backgroundColor The background color as RGBA values (0-1 range).
49
71
  * @ignore
50
72
  */
51
- $renderAndComposite(targetFramebuffer: GLFramebuffer, fallbackBaseDraw: () => void): void;
73
+ $renderAndComposite(targetFramebuffer: GLFramebuffer): void;
52
74
  /**
53
- * Render all user layers to their respective framebuffers.
75
+ * Render, composite, apply global filters, present to screen, run post-draw hooks.
76
+ * This replaces the removed "Pass 3/4 + post hooks" section from Textmodifier.$render().
77
+ *
78
+ * @param fallbackBaseDraw Fallback draw callback for the base layer if it has no own draw callback.
79
+ * @ignore
54
80
  */
55
- private _renderUserLayers;
81
+ $renderAndPresent(): void;
56
82
  /**
57
- * Composite all layers onto the target framebuffer.
83
+ * Composite base + user layers onto the target framebuffer.
58
84
  */
59
85
  private _compositeLayers;
60
86
  /**
61
- * Resize all layers and the compositor to match the current grid dimensions.
87
+ * Resize all layers, compositor, and global post-processing buffers.
62
88
  * @ignore
63
89
  */
64
90
  $resize(): void;
65
91
  /**
66
- * Dispose of the layer manager, all layers, and the compositor.
92
+ * Dispose of the layer manager, all layers, compositor, and global post-processing resources.
67
93
  * @ignore
68
94
  */
69
95
  $dispose(): void;
70
96
  get all(): readonly TextmodeLayer[];
71
97
  get base(): TextmodeLayer;
98
+ get filters(): TextmodeFilterManager;
99
+ get resultFramebuffer(): GLFramebuffer;
72
100
  /**
73
101
  * Get the grid of the topmost visible layer.
74
102
  * Returns the topmost user layer's grid if any are visible, otherwise returns the base layer's grid.
@@ -91,16 +119,4 @@ export declare class LayerManager implements ILayerManager {
91
119
  * Initialize a single layer with required dependencies.
92
120
  */
93
121
  private _initializeLayer;
94
- /**
95
- * Remove a layer from a collection and dispose it.
96
- */
97
- private _removeFromCollection;
98
- /**
99
- * Move a layer to a new index within a collection.
100
- */
101
- private _moveInCollection;
102
- /**
103
- * Swap two layers within a collection.
104
- */
105
- private _swapInCollection;
106
122
  }
@@ -14,6 +14,10 @@ import type { ITextmodeLayer } from './interfaces/ITextmodeLayer';
14
14
  *
15
15
  * You can draw on each layer by providing a draw callback function,
16
16
  * like you would with the base layer's {@link Textmodifier.draw} method.
17
+ *
18
+ * Plugins can extend TextmodeLayer with additional methods using the plugin API's
19
+ * `extendLayer` function. For example, the `textmode-synth` plugin adds a `.synth()`
20
+ * method for hydra-like procedural generation.
17
21
  */
18
22
  export declare class TextmodeLayer implements ITextmodeLayer {
19
23
  /** @ignore */
@@ -40,8 +44,8 @@ export declare class TextmodeLayer implements ITextmodeLayer {
40
44
  private _rawAsciiFramebuffer?;
41
45
  private _pingPongBuffers?;
42
46
  private _drawCallback;
43
- private _hasRenderableContent;
44
47
  private _filterQueue;
48
+ private _pluginState;
45
49
  /**
46
50
  * Create a new TextmodeLayer with the given options.
47
51
  * @param options Layer configuration options.
@@ -54,18 +58,6 @@ export declare class TextmodeLayer implements ITextmodeLayer {
54
58
  * @ignore
55
59
  */
56
60
  $attachDependencies(deps: LayerDependencies): Promise<void>;
57
- /**
58
- * Return true when this layer has a user-provided draw callback.
59
- * @ignore
60
- */
61
- $hasDraw(): boolean;
62
- /**
63
- * Run the layer's draw callback in the calling context. This does NOT
64
- * manage framebuffer binding; the caller must ensure the correct
65
- * framebuffer is bound before invoking this.
66
- * @ignore
67
- */
68
- $runDraw(textmodifier: Textmodifier): void;
69
61
  draw(callback: () => void): void;
70
62
  show(): void;
71
63
  hide(): void;
@@ -78,25 +70,11 @@ export declare class TextmodeLayer implements ITextmodeLayer {
78
70
  rotateZ(z?: number): number | void;
79
71
  filter<T extends BuiltInFilterName>(name: T, params?: BuiltInFilterParams[T]): void;
80
72
  filter(name: FilterName, params?: unknown): void;
81
- /** Get or set the font size for this layer's font. */
82
- fontSize(size?: number): number | void;
83
- /**
84
- * Load a font into this layer from a URL/path or reuse an existing {@link TextmodeFont} instance.
85
- * Creates a new font instance for this layer and loads the font data when a string source is provided.
86
- *
87
- * @param fontSource The URL or path to the font file.
88
- * @returns The loaded TextmodeFont instance.
89
- *
90
- * @example
91
- * ```js
92
- * const layer = t.layers.add();
93
- *
94
- * t.setup(async () => {
95
- * // Load a custom font for this layer
96
- * await layer.loadFont('./fonts/custom.ttf');
97
- * });
98
- * ```
99
- */
73
+ setPluginState<T>(pluginName: string, state: T): void;
74
+ getPluginState<T>(pluginName: string): T | undefined;
75
+ hasPluginState(pluginName: string): boolean;
76
+ deletePluginState(pluginName: string): boolean;
77
+ fontSize(size?: number): void;
100
78
  loadFont(fontSource: string | TextmodeFont): Promise<TextmodeFont>;
101
79
  /**
102
80
  * Render the layer's content into its ASCII framebuffer.
@@ -104,9 +82,7 @@ export declare class TextmodeLayer implements ITextmodeLayer {
104
82
  * @param conversionShader The shader used for conversion.
105
83
  * @ignore
106
84
  */
107
- $render(textmodifier: Textmodifier, conversionShader: GLShader, options?: {
108
- fallbackDraw?: () => void;
109
- }): void;
85
+ $render(textmodifier: Textmodifier, conversionShader: GLShader): void;
110
86
  /**
111
87
  * Resize the layer's framebuffers to match the given grid dimensions.
112
88
  * @param grid The TextmodeGrid instance.
@@ -118,29 +94,12 @@ export declare class TextmodeLayer implements ITextmodeLayer {
118
94
  * @ignore
119
95
  */
120
96
  $dispose(): void;
121
- /**
122
- * Get the texture containing the rendered textmode output for this layer.
123
- */
124
97
  get texture(): WebGLTexture | undefined;
125
- /**
126
- * Get the grid associated with this layer.
127
- */
128
98
  get grid(): TextmodeGrid | undefined;
129
99
  get font(): TextmodeFont;
130
100
  get width(): number;
131
101
  get height(): number;
132
- /**
133
- * Return true when this layer has renderable content.
134
- * @ignore
135
- */
136
- get $hasRenderableContent(): boolean;
137
- /**
138
- * Get the framebuffer used for drawing operations on this layer.
139
- */
140
102
  get drawFramebuffer(): GLFramebuffer | undefined;
141
- /**
142
- * Get the framebuffer containing the rendered textmode output for this layer.
143
- */
144
103
  get asciiFramebuffer(): GLFramebuffer | undefined;
145
104
  private _syncGridToFont;
146
105
  }
@@ -1,6 +1,7 @@
1
1
  import type { TextmodeLayer } from '../TextmodeLayer';
2
2
  import type { TextmodeLayerOptions } from '../types';
3
3
  import type { TextmodeGrid } from '../../Grid';
4
+ import type { GLFramebuffer } from '../../../rendering/webgl/core/Framebuffer';
4
5
  export interface ILayerManager {
5
6
  /**
6
7
  * Get all user layers as a readonly array.
@@ -11,6 +12,10 @@ export interface ILayerManager {
11
12
  * This layer represents the main drawing content before any user layers are composited.
12
13
  */
13
14
  readonly base: TextmodeLayer;
15
+ /**
16
+ * The framebuffer containing the final composited result after all layers and filters have been applied.
17
+ */
18
+ readonly resultFramebuffer: GLFramebuffer;
14
19
  /**
15
20
  * Add a new layer to the manager.
16
21
  * @param options Layer configuration options.