textmode.js 0.4.0 → 0.6.0-beta.1

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 (105) hide show
  1. package/dist/textmode.esm.js +2868 -2164
  2. package/dist/textmode.esm.min.js +2863 -2159
  3. package/dist/textmode.umd.js +11 -8
  4. package/dist/textmode.umd.min.js +11 -8
  5. package/dist/types/Textmode.d.ts +13 -22
  6. package/dist/types/index.d.ts +8 -6
  7. package/dist/types/rendering/index.d.ts +3 -3
  8. package/dist/types/rendering/webgl/batching/DrawQueue.d.ts +89 -0
  9. package/dist/types/rendering/webgl/{VAOManager.d.ts → batching/GeometryAttributeCache.d.ts} +4 -4
  10. package/dist/types/rendering/webgl/batching/InstanceAttributeBinder.d.ts +87 -0
  11. package/dist/types/rendering/webgl/{InstanceBatch.d.ts → batching/InstanceBatch.d.ts} +25 -34
  12. package/dist/types/rendering/webgl/batching/InstanceBuffer.d.ts +78 -0
  13. package/dist/types/rendering/webgl/{InstanceData.d.ts → batching/InstanceData.d.ts} +11 -18
  14. package/dist/types/rendering/webgl/batching/InstanceWriter.d.ts +70 -0
  15. package/dist/types/rendering/webgl/{Framebuffer.d.ts → core/Framebuffer.d.ts} +37 -39
  16. package/dist/types/rendering/webgl/core/Renderer.d.ts +64 -0
  17. package/dist/types/rendering/webgl/{Shader.d.ts → core/Shader.d.ts} +2 -23
  18. package/dist/types/rendering/webgl/core/interfaces/IFramebuffer.d.ts +103 -0
  19. package/dist/types/rendering/webgl/core/interfaces/IRenderer.d.ts +210 -0
  20. package/dist/types/rendering/webgl/geometries/{Arc.d.ts → 2d/Arc.d.ts} +5 -4
  21. package/dist/types/rendering/webgl/geometries/{BezierCurve.d.ts → 2d/BezierCurve.d.ts} +5 -4
  22. package/dist/types/rendering/webgl/geometries/{Ellipse.d.ts → 2d/Ellipse.d.ts} +6 -5
  23. package/dist/types/rendering/webgl/geometries/{Line.d.ts → 2d/Line.d.ts} +5 -4
  24. package/dist/types/rendering/webgl/geometries/{Rectangle.d.ts → 2d/Rectangle.d.ts} +5 -4
  25. package/dist/types/rendering/webgl/geometries/{Triangle.d.ts → 2d/Triangle.d.ts} +5 -4
  26. package/dist/types/rendering/webgl/geometries/BaseGeometry.d.ts +30 -26
  27. package/dist/types/rendering/webgl/geometries/immediate/ImmediateQuad.d.ts +33 -0
  28. package/dist/types/rendering/webgl/geometries/index.d.ts +6 -6
  29. package/dist/types/rendering/webgl/geometries/utils/GeometryDescriptors.d.ts +31 -0
  30. package/dist/types/rendering/webgl/geometries/utils/GeometryGenerator.d.ts +16 -0
  31. package/dist/types/rendering/webgl/index.d.ts +15 -14
  32. package/dist/types/rendering/webgl/materials/Material.d.ts +26 -0
  33. package/dist/types/rendering/webgl/materials/MaterialManager.d.ts +63 -0
  34. package/dist/types/rendering/webgl/materials/index.d.ts +2 -0
  35. package/dist/types/rendering/webgl/pipeline/MaterialBatchPipeline.d.ts +63 -0
  36. package/dist/types/rendering/webgl/pipeline/index.d.ts +7 -0
  37. package/dist/types/rendering/webgl/state/RenderState.d.ts +143 -0
  38. package/dist/types/rendering/webgl/types/DrawCommand.d.ts +5 -3
  39. package/dist/types/rendering/webgl/types/GeometryTypes.d.ts +10 -10
  40. package/dist/types/rendering/webgl/types/RenderTypes.d.ts +1 -1
  41. package/dist/types/rendering/webgl/utils/GLUtils.d.ts +45 -0
  42. package/dist/types/rendering/webgl/utils/hash.d.ts +118 -0
  43. package/dist/types/textmode/AnimationController.d.ts +11 -21
  44. package/dist/types/textmode/Canvas.d.ts +10 -2
  45. package/dist/types/textmode/Grid.d.ts +2 -0
  46. package/dist/types/textmode/TextmodeColor.d.ts +57 -0
  47. package/dist/types/textmode/Textmodifier.d.ts +40 -212
  48. package/dist/types/textmode/interfaces/ITextmodifier.d.ts +272 -0
  49. package/dist/types/textmode/interfaces/index.d.ts +1 -0
  50. package/dist/types/textmode/loadables/TextmodeImage.d.ts +21 -0
  51. package/dist/types/textmode/loadables/TextmodeSource.d.ts +130 -0
  52. package/dist/types/textmode/loadables/TextmodeVideo.d.ts +237 -0
  53. package/dist/types/textmode/{font → loadables/font}/CharacterColorMapper.d.ts +1 -1
  54. package/dist/types/textmode/{font → loadables/font}/CharacterExtractor.d.ts +0 -10
  55. package/dist/types/textmode/{font → loadables/font}/TextmodeFont.d.ts +6 -3
  56. package/dist/types/textmode/{font → loadables/font}/TextureAtlas.d.ts +4 -11
  57. package/dist/types/textmode/{font → loadables/font}/typr/types.d.ts +0 -6
  58. package/dist/types/textmode/loadables/index.d.ts +5 -0
  59. package/dist/types/textmode/loading/LoadingPhaseTracker.d.ts +20 -0
  60. package/dist/types/textmode/loading/LoadingScreenManager.d.ts +170 -0
  61. package/dist/types/textmode/loading/LoadingScreenState.d.ts +22 -0
  62. package/dist/types/textmode/loading/LoadingScreenTheme.d.ts +26 -0
  63. package/dist/types/textmode/loading/LoadingScreenTransition.d.ts +17 -0
  64. package/dist/types/textmode/loading/index.d.ts +6 -0
  65. package/dist/types/textmode/loading/templates/SpinnerTemplate.d.ts +2 -0
  66. package/dist/types/textmode/loading/templates/index.d.ts +1 -0
  67. package/dist/types/textmode/loading/types.d.ts +251 -0
  68. package/dist/types/textmode/managers/KeyboardManager.d.ts +2 -3
  69. package/dist/types/textmode/managers/MouseManager.d.ts +1 -1
  70. package/dist/types/textmode/{plugins → managers}/PluginManager.d.ts +12 -15
  71. package/dist/types/textmode/managers/TouchManager.d.ts +0 -2
  72. package/dist/types/textmode/mixins/AnimationMixin.d.ts +2 -122
  73. package/dist/types/textmode/mixins/FontMixin.d.ts +2 -77
  74. package/dist/types/textmode/mixins/KeyboardMixin.d.ts +3 -85
  75. package/dist/types/textmode/mixins/MouseMixin.d.ts +3 -130
  76. package/dist/types/textmode/mixins/RenderingMixin.d.ts +2 -749
  77. package/dist/types/textmode/mixins/TextmodifierMixin.d.ts +2 -44
  78. package/dist/types/textmode/mixins/TouchMixin.d.ts +2 -187
  79. package/dist/types/textmode/mixins/index.d.ts +8 -8
  80. package/dist/types/textmode/mixins/interfaces/IAnimationMixin.d.ts +167 -0
  81. package/dist/types/textmode/mixins/interfaces/IFontMixin.d.ts +46 -0
  82. package/dist/types/textmode/mixins/interfaces/IKeyboardMixin.d.ts +235 -0
  83. package/dist/types/textmode/mixins/interfaces/IMouseMixin.d.ts +457 -0
  84. package/dist/types/textmode/mixins/interfaces/IRenderingMixin.d.ts +1085 -0
  85. package/dist/types/textmode/mixins/interfaces/ITouchMixin.d.ts +186 -0
  86. package/dist/types/textmode/types.d.ts +49 -0
  87. package/dist/types/textmode/utils/cssColor.d.ts +8 -0
  88. package/dist/types/utils/array.d.ts +34 -0
  89. package/dist/types/utils/math.d.ts +69 -0
  90. package/package.json +1 -1
  91. package/dist/types/rendering/webgl/DrawQueue.d.ts +0 -30
  92. package/dist/types/rendering/webgl/RenderPipeline.d.ts +0 -30
  93. package/dist/types/rendering/webgl/RenderState.d.ts +0 -73
  94. package/dist/types/rendering/webgl/Renderer.d.ts +0 -158
  95. package/dist/types/rendering/webgl/ShaderManager.d.ts +0 -66
  96. package/dist/types/rendering/webgl/geometries/NoiseGrid.d.ts +0 -1
  97. package/dist/types/textmode/TextmodeImage.d.ts +0 -161
  98. package/dist/types/textmode/mixins/ShaderMixin.d.ts +0 -1
  99. /package/dist/types/rendering/webgl/{StateCache.d.ts → utils/ViewportCache.d.ts} +0 -0
  100. /package/dist/types/textmode/{font → loadables/font}/MetricsCalculator.d.ts +0 -0
  101. /package/dist/types/textmode/{font → loadables/font}/index.d.ts +0 -0
  102. /package/dist/types/textmode/{font → loadables/font}/types.d.ts +0 -0
  103. /package/dist/types/textmode/{font → loadables/font}/typr/Typr.d.ts +0 -0
  104. /package/dist/types/textmode/{font → loadables/font}/utils/FontTableReader.d.ts +0 -0
  105. /package/dist/types/textmode/{font → loadables/font}/utils/index.d.ts +0 -0
@@ -0,0 +1,1085 @@
1
+ import type { GLFramebuffer, GLShader, TextmodeFramebufferOptions, UniformValue } from "../../../rendering/webgl";
2
+ import type { TextmodeImage } from "../../loadables/TextmodeImage";
3
+ import type { TextmodeVideo, TextmodeVideoOptions } from "../../loadables/TextmodeVideo";
4
+ import type { TextmodeColor } from "../../TextmodeColor";
5
+ /**
6
+ * Interface for rendering capabilities that will be mixed into Textmodifier
7
+ */
8
+ export interface IRenderingMixin {
9
+ /**
10
+ * Set a custom shader for subsequent rendering operations.
11
+ * @param shader The custom shader to use
12
+ *
13
+ * @example
14
+ * ```javascript
15
+ * const t = textmode.create({
16
+ * width: 800,
17
+ * height: 600,
18
+ * })
19
+ *
20
+ * // Create a custom filter shader
21
+ * const customShader = t.createFilterShader('
22
+ * // ... fragment shader code ...
23
+ * ');
24
+ *
25
+ * t.draw(() => {
26
+ * t.background(0);
27
+ *
28
+ * // Use custom shader
29
+ * t.shader(customShader);
30
+ * t.setUniform('u_frameCount', t.frameCount);
31
+ * t.rect(0, 0, t.grid.cols, t.grid.rows);
32
+ * });
33
+ * ```
34
+ */
35
+ shader(shader: GLShader): void;
36
+ /**
37
+ * Create a new framebuffer for offscreen rendering.
38
+ *
39
+ * The framebuffer uses the same MRT structure as the main rendering pipeline.
40
+ * By default it allocates 4 attachments (character + color data).
41
+ *
42
+ * @param options Configuration options for the framebuffer.
43
+ * @returns A new Framebuffer instance.
44
+ *
45
+ * @example
46
+ * ```javascript
47
+ * const t = textmode.create({
48
+ * width: 800,
49
+ * height: 600,
50
+ * });
51
+ *
52
+ * // Create a framebuffer with 50x30 grid cells
53
+ * const fb = t.createFramebuffer({
54
+ * width: 50,
55
+ * height: 30
56
+ * });
57
+ *
58
+ * t.draw(() => {
59
+ * // Render to framebuffer
60
+ * fb.begin();
61
+ * t.background(255, 0, 0);
62
+ * t.charColor(255);
63
+ * t.char('A');
64
+ * t.rect(20, 10);
65
+ * fb.end();
66
+ *
67
+ * // Render framebuffer to main canvas
68
+ * t.background(0);
69
+ * t.rotateZ(t.frameCount * 2);
70
+ * t.image(fb);
71
+ * });
72
+ * ```
73
+ */
74
+ createFramebuffer(options: TextmodeFramebufferOptions): GLFramebuffer;
75
+ /**
76
+ * Draw a TextmodeFramebuffer or TextmodeImage to the current render target.
77
+ *
78
+ * @param source The TextmodeFramebuffer or TextmodeImage to render
79
+ * @param x X position on the grid where to place the content *(top-left corner)*
80
+ * @param y Y position on the grid where to place the content *(top-left corner)*
81
+ * @param width Width to potentially scale the content
82
+ * @param height Height to potentially scale the content
83
+ *
84
+ * @example
85
+ * ```javascript
86
+ * const t = textmode.create({
87
+ * width: 800,
88
+ * height: 600,
89
+ * });
90
+ *
91
+ * const fb = t.createFramebuffer({width: 30, height: 20});
92
+ *
93
+ * t.draw(() => {
94
+ * // Draw something to the framebuffer
95
+ * fb.begin();
96
+ * t.clear();
97
+ * t.charColor(255, 0, 0);
98
+ * t.char('A');
99
+ * t.rect(20, 10);
100
+ * fb.end();
101
+ *
102
+ * // Clear main canvas and render framebuffer content
103
+ * t.background(0);
104
+ *
105
+ * // Render at original size
106
+ * t.image(fb);
107
+ *
108
+ * // Render scaled version
109
+ * // t.image(fb, 60, 40);
110
+ * });
111
+ * ```
112
+ */
113
+ image(source: GLFramebuffer | TextmodeImage, width?: number, height?: number): void;
114
+ /**
115
+ * Load an image and return a TextmodeImage that can be drawn with image().
116
+ *
117
+ * The loaded image can be rendered to the canvas using the {@link image} method.
118
+ * This function returns a Promise that resolves when the image has loaded.
119
+ *
120
+ * @param src URL or existing HTMLImageElement
121
+ * @returns A Promise that resolves to a TextmodeImage object
122
+ *
123
+ * @example
124
+ * ```javascript
125
+ * const t = textmode.create({
126
+ * width: 800,
127
+ * height: 600,
128
+ * });
129
+ *
130
+ * let img;
131
+ *
132
+ * t.setup(async () => {
133
+ * img = await t.loadImage('https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80');
134
+ * img.characters(" .:-=+*#%@");
135
+ * });
136
+ *
137
+ * t.draw(() => {
138
+ * t.background(0);
139
+ *
140
+ * if (img) {
141
+ * // Draw the loaded image
142
+ * t.image(img);
143
+ * }
144
+ * });
145
+ * ```
146
+ */
147
+ loadImage(src: string | HTMLImageElement): Promise<TextmodeImage>;
148
+ /**
149
+ * Load a video and return a TextmodeVideo that can be drawn with image().
150
+ * @param src URL or existing HTMLVideoElement
151
+ * @param options Optional configuration for preloading behavior. Provide `frameRate` to preload frames, `onProgress` to observe preload progress, `onComplete` to know when preloading finished, and `onError` to catch preload failures.
152
+ *
153
+ * @example
154
+ * ```javascript
155
+ * const t = textmode.create({
156
+ * width: 800,
157
+ * height: 600,
158
+ * });
159
+ *
160
+ * let video;
161
+ *
162
+ * t.setup(async () => {
163
+ * video = await t.loadVideo('https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4');
164
+ * // Start playback and enable looping so the video keeps playing
165
+ * video.play();
166
+ * video.loop();
167
+ *
168
+ * video.characters(" .:-=+*#%@");
169
+ * });
170
+ *
171
+ * t.draw(() => {
172
+ * t.background(0);
173
+ *
174
+ * if (video) {
175
+ * // Draw the loaded video
176
+ * t.image(video);
177
+ * }
178
+ * });
179
+ * ```
180
+ */
181
+ loadVideo(src: string | HTMLVideoElement, options?: TextmodeVideoOptions): Promise<TextmodeVideo>;
182
+ /**
183
+ * Set a uniform value for the current custom shader.
184
+ * @param name The name of the uniform variable
185
+ * @param value The value to set
186
+ *
187
+ * @example
188
+ * ```javascript
189
+ * const t = textmode.create({
190
+ * width: 800,
191
+ * height: 600,
192
+ * })
193
+ *
194
+ * const shader = t.createFilterShader(`
195
+ * uniform float u_time;
196
+ * // ... rest of shader ...
197
+ * `);
198
+ *
199
+ * t.draw(() => {
200
+ * t.shader(shader);
201
+ * t.setUniform('u_time', t.frameCount * 0.02);
202
+ * t.rect(0, 0, t.grid.cols, t.grid.rows);
203
+ * });
204
+ * ```
205
+ */
206
+ setUniform(name: string, value: UniformValue): void;
207
+ /**
208
+ * Set multiple uniform values for the current custom shader.
209
+ * @param uniforms Object containing uniform name-value pairs
210
+ *
211
+ * @example
212
+ * ```javascript
213
+ * const t = textmode.create({
214
+ * width: 800,
215
+ * height: 600,
216
+ * })
217
+ *
218
+ * const shader = t.createFilterShader(`
219
+ * uniform float u_time;
220
+ * uniform vec2 u_resolution;
221
+ * // ... rest of shader ...
222
+ * `);
223
+ *
224
+ * t.draw(() => {
225
+ * t.shader(shader);
226
+ * t.setUniforms({
227
+ * u_time: t.frameCount * 0.02,
228
+ * u_resolution: [t.grid.cols, t.grid.rows]
229
+ * });
230
+ * t.rect(0, 0, t.grid.cols, t.grid.rows);
231
+ * });
232
+ * ```
233
+ */
234
+ setUniforms(uniforms: Record<string, UniformValue>): void;
235
+ /**
236
+ * Create a custom filter shader from fragment shader source code.
237
+ * The fragment shader automatically receives the standard vertex shader inputs
238
+ * and must output to the 3 MRT attachments (character/transform, primary color, secondary color).
239
+ * @param fragmentSource The fragment shader source code
240
+ * @returns A compiled shader ready for use with {@link shader}
241
+ *
242
+ * @example
243
+ * ```javascript
244
+ * const t = textmode.create({
245
+ * width: 800,
246
+ * height: 600,
247
+ * })
248
+ *
249
+ * const waveShader = t.createFilterShader(`#version 300 es
250
+ * precision highp float;
251
+ *
252
+ * in vec2 v_uv;
253
+ * in vec3 v_character;
254
+ * in vec4 v_primaryColor;
255
+ * in vec4 v_secondaryColor;
256
+ *
257
+ * uniform float u_time;
258
+ *
259
+ * layout(location = 0) out vec4 o_character;
260
+ * layout(location = 1) out vec4 o_primaryColor;
261
+ * layout(location = 2) out vec4 o_secondaryColor;
262
+ *
263
+ * float luma(vec3 c) {
264
+ * return dot(c, vec3(0.2126, 0.7152, 0.0722));
265
+ * }
266
+ *
267
+ * void main() {
268
+ * vec2 uv = v_uv * 2.0 - 1.0;
269
+ * float time = u_time * 0.4;
270
+ * float radial = length(uv);
271
+ * float swirl = sin(radial * 9.0 - time) + cos(uv.x * 6.0 + time * 1.3);
272
+ * float ripple = sin((uv.x + uv.y) * 10.0 + time * 2.0) * 0.5;
273
+ *
274
+ * // Palette that shifts through warm→cool hues
275
+ * vec3 color = vec3(
276
+ * 0.55 + 0.45 * sin(time + radial * 4.0),
277
+ * 0.55 + 0.45 * sin(time * 1.3 + uv.y * 5.0 + ripple),
278
+ * 0.55 + 0.45 * sin(time * 0.9 + uv.x * 5.0 - ripple)
279
+ * );
280
+ *
281
+ * float glyphIndex = fract(0.5 + 0.5 * swirl);
282
+ * float rotation = fract(0.5 + swirl * 0.25);
283
+ * int invertFlag = luma(color) > 0.6 ? 1 : 0;
284
+ * float packedFlags = float(invertFlag) / 255.0;
285
+ *
286
+ * o_character = vec4(glyphIndex, 0.0, packedFlags, 0.0);
287
+ * o_primaryColor = vec4(color, 1.0);
288
+ * o_secondaryColor = vec4(mix(vec3(0.1), color, 0.35), 1.0);
289
+ * }
290
+ * `);
291
+ *
292
+ * t.draw(() => {
293
+ * t.shader(waveShader);
294
+ * t.setUniform('u_time', t.frameCount * 0.003);
295
+ * t.rect(t.grid.cols, t.grid.rows);
296
+ * });
297
+ * ```
298
+ */
299
+ createFilterShader(fragmentSource: string): GLShader;
300
+ /**
301
+ * Sets the rotation angles for subsequent shape rendering operations.
302
+ *
303
+ * All geometries rotate around the center of the shape.
304
+ *
305
+ * @param degreesX The rotation angle in degrees around the X-axis (optional, defaults to 0)
306
+ * @param degreesY The rotation angle in degrees around the Y-axis (optional, defaults to 0)
307
+ * @param degreesZ The rotation angle in degrees around the Z-axis (optional, defaults to 0)
308
+ *
309
+ * @example
310
+ * ```javascript
311
+ * const t = textmode.create({
312
+ * width: 800,
313
+ * height: 600,
314
+ * })
315
+ *
316
+ * t.draw(() => {
317
+ * t.background(0);
318
+ *
319
+ * // Rotate only around Z-axis (backward compatible)
320
+ * t.rotate(0, 0, 45);
321
+ *
322
+ * // Rotate around all three axes
323
+ * t.rotate(30, 45, 60);
324
+ *
325
+ * t.rect(10, 10, 5, 5);
326
+ * });
327
+ * ```
328
+ */
329
+ rotate(degreesX?: number, degreesY?: number, degreesZ?: number): void;
330
+ /**
331
+ * Sets the X-axis rotation angle for subsequent shape rendering operations.
332
+ *
333
+ * All geometries rotate around the center of the shape.
334
+ *
335
+ * @param degrees The rotation angle in degrees around the X-axis
336
+ *
337
+ * @example
338
+ * ```javascript
339
+ * const t = textmode.create({
340
+ * width: 800,
341
+ * height: 600,
342
+ * })
343
+ *
344
+ * t.draw(() => {
345
+ * t.background(0);
346
+ * t.rotateX(45); // Rotate around X-axis
347
+ * t.rect(10, 10, 5, 5);
348
+ * });
349
+ * ```
350
+ */
351
+ rotateX(degrees: number): void;
352
+ /**
353
+ * Sets the Y-axis rotation angle for subsequent shape rendering operations.
354
+ *
355
+ * All geometries rotate around the center of the shape.
356
+ *
357
+ * @param degrees The rotation angle in degrees around the Y-axis
358
+ *
359
+ * @example
360
+ * ```javascript
361
+ * const t = textmode.create({
362
+ * width: 800,
363
+ * height: 600,
364
+ * })
365
+ *
366
+ * t.draw(() => {
367
+ * t.background(0);
368
+ * t.rotateY(45); // Rotate around Y-axis
369
+ * t.rect(10, 10, 5, 5);
370
+ * });
371
+ * ```
372
+ */
373
+ rotateY(degrees: number): void;
374
+ /**
375
+ * Sets the Z-axis rotation angle for subsequent shape rendering operations.
376
+ *
377
+ * All geometries rotate around the center of the shape.
378
+ *
379
+ * @param degrees The rotation angle in degrees around the Z-axis
380
+ *
381
+ * @example
382
+ * ```javascript
383
+ * const t = textmode.create({
384
+ * width: 800,
385
+ * height: 600,
386
+ * })
387
+ *
388
+ * t.draw(() => {
389
+ * t.background(0);
390
+ * t.rotateZ(45); // Rotate around Z-axis
391
+ * t.rect(10, 10, 5, 5);
392
+ * });
393
+ * ```
394
+ */
395
+ rotateZ(degrees: number): void;
396
+ /**
397
+ * Sets the translation offsets for subsequent shape rendering operations.
398
+ *
399
+ * All geometries are displaced by the specified amounts. Similar to p5.js translate().
400
+ *
401
+ * @param x Translation along the X-axis in pixels (optional, defaults to 0)
402
+ * @param y Translation along the Y-axis in pixels (optional, defaults to 0)
403
+ * @param z Translation along the Z-axis in pixels (optional, defaults to 0)
404
+ *
405
+ * @example
406
+ * ```javascript
407
+ * const t = textmode.create({
408
+ * width: 800,
409
+ * height: 600,
410
+ * })
411
+ *
412
+ * t.draw(() => {
413
+ * t.background(0);
414
+ *
415
+ * // Translate in 2D
416
+ * t.translate(10, 5);
417
+ *
418
+ * // Translate in 3D
419
+ * t.translate(10, 5, 2);
420
+ *
421
+ * t.rect(0, 0, 5, 5); // Drawn at (10, 5) with Z offset
422
+ * });
423
+ * ```
424
+ */
425
+ translate(x?: number, y?: number, z?: number): void;
426
+ /**
427
+ * Sets the X-axis translation offset for subsequent shape rendering operations.
428
+ *
429
+ * @param pixels The translation offset in pixels along the X-axis
430
+ *
431
+ * @example
432
+ * ```javascript
433
+ * const t = textmode.create({
434
+ * width: 800,
435
+ * height: 600,
436
+ * })
437
+ *
438
+ * t.draw(() => {
439
+ * t.background(0);
440
+ * t.translateX(10); // Translate 10 pixels to the right
441
+ * t.rect(0, 0, 5, 5); // Drawn at (10, 0)
442
+ * });
443
+ * ```
444
+ */
445
+ translateX(pixels: number): void;
446
+ /**
447
+ * Sets the Y-axis translation offset for subsequent shape rendering operations.
448
+ *
449
+ * @param pixels The translation offset in pixels along the Y-axis
450
+ *
451
+ * @example
452
+ * ```javascript
453
+ * const t = textmode.create({
454
+ * width: 800,
455
+ * height: 600,
456
+ * })
457
+ *
458
+ * t.draw(() => {
459
+ * t.background(0);
460
+ * t.translateY(10); // Translate 10 pixels down
461
+ * t.rect(0, 0, 5, 5); // Drawn at (0, 10)
462
+ * });
463
+ * ```
464
+ */
465
+ translateY(pixels: number): void;
466
+ /**
467
+ * Sets the Z-axis translation offset for subsequent shape rendering operations.
468
+ *
469
+ * @param pixels The translation offset in pixels along the Z-axis
470
+ *
471
+ * @example
472
+ * ```javascript
473
+ * const t = textmode.create({
474
+ * width: 800,
475
+ * height: 600,
476
+ * })
477
+ *
478
+ * t.draw(() => {
479
+ * t.background(0);
480
+ * t.translateZ(5); // Move 5 pixels forward in 3D space
481
+ * t.rect(10, 10, 5, 5);
482
+ * });
483
+ * ```
484
+ */
485
+ translateZ(pixels: number): void;
486
+ /**
487
+ * Save the current rendering state to the state stack.
488
+ * Use with {@link pop} to isolate style changes within a block.
489
+ *
490
+ * @example
491
+ * ```javascript
492
+ * const t = textmode.create({
493
+ * width: 800,
494
+ * height: 600,
495
+ * })
496
+ *
497
+ * t.draw(() => {
498
+ * t.background(0);
499
+ *
500
+ * t.push(); // Save current state
501
+ * t.charColor(255, 0, 0); // Red characters
502
+ * t.rotateZ(t.frameCount * 2);
503
+ * t.char('A');
504
+ * t.rect(16, 16);
505
+ * t.pop(); // Restore previous state
506
+ * });
507
+ * ```
508
+ */
509
+ push(): void;
510
+ /**
511
+ * Restore the most recently saved rendering state from the state stack.
512
+ * Use with {@link push} to isolate style changes within a block.
513
+ *
514
+ * @example
515
+ * ```javascript
516
+ * const t = textmode.create({
517
+ * width: 800,
518
+ * height: 600,
519
+ * })
520
+ *
521
+ * t.draw(() => {
522
+ * t.background(0);
523
+ *
524
+ * t.push(); // Save current state
525
+ * t.charColor(0, 255, 0); // Green characters
526
+ * t.rotateZ(t.frameCount * 2);
527
+ * t.char('A');
528
+ * t.rect(16, 16);
529
+ * t.pop(); // Restore previous state
530
+ * });
531
+ * ```
532
+ */
533
+ pop(): void;
534
+ /**
535
+ * Create a reusable color object compatible with textmode drawing APIs.
536
+ *
537
+ * Accepts grayscale, RGB, RGBA, hex string values as arguments, and
538
+ * single characters that resolve to their encoded glyph color. Returned
539
+ * {@link TextmodeColor} instances can be passed to {@link background},
540
+ * {@link char}, {@link charColor}, {@link cellColor}, and more.
541
+ *
542
+ * @param value Grayscale value, hex string, single character, or an existing color
543
+ * @param g Optional green component, or `value` when using grayscale form
544
+ * @param b Optional blue component, or `value` when using grayscale form
545
+ * @param a Optional alpha component when using RGB form
546
+ *
547
+ * Example usage of the {@link color} helper.
548
+ *
549
+ * @example
550
+ * ```javascript
551
+ * const t = textmode.create({ width: 800, height: 600 });
552
+ *
553
+ * // Grayscale (0 = black, 255 = white)
554
+ * const gray = t.color(128);
555
+ *
556
+ * // RGB
557
+ * const hotPink = t.color(255, 105, 180);
558
+ *
559
+ * // RGBA (alpha 0-255)
560
+ * const semiTransparentRed = t.color(255, 0, 0, 128);
561
+ *
562
+ * // Hex string
563
+ * const dusk = t.color('#203040');
564
+ *
565
+ * // Single character: resolves to a TextmodeColor that may encode a glyph
566
+ * let glyphColor;
567
+ *
568
+ * t.setup(() => {
569
+ * glyphColor = t.color('B'); // Color based on 'B' character glyph
570
+ * });
571
+ *
572
+ * t.draw(() => {
573
+ * // Using colors with other drawing APIs
574
+ * t.background(gray);
575
+ * t.charColor(hotPink);
576
+ * t.char('A');
577
+ * t.rect(5, 5);
578
+ *
579
+ * t.translate(5, 0);
580
+ * t.cellColor(dusk);
581
+ * t.char('*');
582
+ * t.rect(5, 5);
583
+ *
584
+ * t.translate(5, 0);
585
+ * t.charColor("#FF00FF");
586
+ * t.char(glyphColor);
587
+ * t.rect(5, 5);
588
+ * });
589
+ * ```
590
+ */
591
+ color(value: number | string | TextmodeColor, g?: number, b?: number, a?: number): TextmodeColor;
592
+ /**
593
+ * Draw a rectangle with the current settings.
594
+ * Position is controlled via {@link translate}, {@link push}, and {@link pop}.
595
+ * @param width Width of the rectangle
596
+ * @param height Height of the rectangle
597
+ *
598
+ * @example
599
+ * ```javascript
600
+ * const t = textmode.create({
601
+ * width: 800,
602
+ * height: 600,
603
+ * })
604
+ *
605
+ * t.draw(() => {
606
+ * // Set the background color to black
607
+ * t.background(0);
608
+ *
609
+ * // Position and draw a filled rectangle
610
+ * t.char('A');
611
+ * t.charColor(255, 255, 255); // White
612
+ * t.rotateZ(t.frameCount * 2);
613
+ * t.rect(16, 16);
614
+ * });
615
+ * ```
616
+ */
617
+ rect(width?: number, height?: number): void;
618
+ /**
619
+ * Draw a single point at (x, y) with the current settings.
620
+ * @param x X-coordinate of the point
621
+ * @param y Y-coordinate of the point
622
+ *
623
+ * @example
624
+ * ```javascript
625
+ * const t = textmode.create({
626
+ * width: 800,
627
+ * height: 600,
628
+ * })
629
+ *
630
+ * t.draw(() => {
631
+ * t.background(0);
632
+ *
633
+ * t.char('*');
634
+ * t.point();
635
+ * });
636
+ * ```
637
+ */
638
+ point(x: number, y: number): void;
639
+ /**
640
+ * Draw a line from point (x1, y1) to point (x2, y2) with the settings.
641
+ * @param x1 X-coordinate of the line start point
642
+ * @param y1 Y-coordinate of the line start point
643
+ * @param x2 X-coordinate of the line end point
644
+ * @param y2 Y-coordinate of the line end point
645
+ *
646
+ * @example
647
+ * ```javascript
648
+ * const t = textmode.create({
649
+ * width: 800,
650
+ * height: 600,
651
+ * })
652
+ *
653
+ * t.draw(() => {
654
+ * t.background(0);
655
+ *
656
+ * t.char('*');
657
+ * t.charColor(255, 100, 255); // Magenta
658
+ * t.lineWeight(2);
659
+ *
660
+ * const halfWidth = 5;
661
+ * const halfHeight = 7.5;
662
+ *
663
+ * t.push();
664
+ * t.rotateZ(t.frameCount * 2);
665
+ * t.line(-halfWidth, halfHeight, halfWidth, -halfHeight);
666
+ * t.pop();
667
+ * });
668
+ * ```
669
+ */
670
+ line(x1: number, y1: number, x2: number, y2: number): void;
671
+ /**
672
+ * Set the background color for the canvas.
673
+ * @param value A {@link TextmodeColor}, hex string, grayscale value, or single RGB channel
674
+ * @param g Optional green component when providing RGB channels or alpha when used with grayscale
675
+ * @param b Optional blue component when providing RGB channels
676
+ * @param a Optional alpha component (0-255)
677
+ *
678
+ * @example
679
+ * ```javascript
680
+ * const t = textmode.create({
681
+ * width: 800,
682
+ * height: 600,
683
+ * });
684
+ *
685
+ * const midnight = t.color('#0b1d3a');
686
+ *
687
+ * t.draw(() => {
688
+ * // Set the background using a reusable color
689
+ * t.background(midnight);
690
+ *
691
+ * // Or inline RGB(A) notation
692
+ * //t.background(32, 48, 64);
693
+ *
694
+ * // Or hex string
695
+ * //t.background('#203040');
696
+ *
697
+ * t.char('M');
698
+ * t.rotateZ(t.frameCount * 2);
699
+ * t.rect(12, 12);
700
+ * });
701
+ * ```
702
+ */
703
+ background(value: number | string | TextmodeColor, g?: number, b?: number, a?: number): void;
704
+ /**
705
+ * Clear the canvas.
706
+ *
707
+ * @example
708
+ * ```javascript
709
+ * const t = textmode.create({
710
+ * width: 800,
711
+ * height: 600,
712
+ * })
713
+ *
714
+ * t.draw(() => {
715
+ * // Clear the canvas
716
+ * t.clear();
717
+ * });
718
+ * ```
719
+ */
720
+ clear(): void;
721
+ /**
722
+ * Update the line weight (thickness) for subsequent {@link line} and {@link bezierCurve} calls.
723
+ * @param weight The line weight (thickness) to set.
724
+ *
725
+ * @example
726
+ * ```javascript
727
+ * const t = textmode.create({
728
+ * width: 800,
729
+ * height: 600,
730
+ * })
731
+ *
732
+ * t.draw(() => {
733
+ * t.background('#050810');
734
+ *
735
+ * // Animate the weight so every line breathes differently
736
+ * const layers = 6;
737
+ * const halfCols = t.grid.cols / 2;
738
+ * const spacing = 4;
739
+ *
740
+ * for (let i = 0; i < layers; i++) {
741
+ * const phase = t.frameCount * 0.03 + i * 0.8;
742
+ * const pulse = 0.75 + 3.25 * (0.5 + 0.5 * Math.sin(phase));
743
+ * const wobble = Math.sin(phase * 1.6) * 4;
744
+ * const centeredRow = (i - (layers - 1) / 2) * spacing;
745
+ *
746
+ * t.lineWeight(Math.round(pulse));
747
+ * t.charColor(160 + i * 12, 200 - i * 8, 255);
748
+ * t.char('-');
749
+ * t.line(
750
+ * -halfCols + 2,
751
+ * centeredRow + wobble,
752
+ * halfCols - 2,
753
+ * centeredRow - wobble,
754
+ * );
755
+ * }
756
+ * });
757
+ * ```
758
+ */
759
+ lineWeight(weight: number): void;
760
+ /**
761
+ * Draw a smooth cubic bezier curve between two points with two control points.
762
+ * The curve thickness is controlled by the current {@link lineWeight} setting.
763
+ * @param x1 Start point X coordinate
764
+ * @param y1 Start point Y coordinate
765
+ * @param cp1x First control point X coordinate
766
+ * @param cp1y First control point Y coordinate
767
+ * @param cp2x Second control point X coordinate
768
+ * @param cp2y Second control point Y coordinate
769
+ * @param x2 End point X coordinate
770
+ * @param y2 End point Y coordinate
771
+ *
772
+ * @example
773
+ * ```javascript
774
+ * const t = textmode.create({
775
+ * width: 800,
776
+ * height: 600,
777
+ * })
778
+ *
779
+ * t.draw(() => {
780
+ * t.background(0);
781
+ * t.translate(-t.grid.cols / 2, -t.grid.rows / 2);
782
+ *
783
+ * // Draw a smooth S-curve
784
+ * t.char('*');
785
+ * t.charColor(255, 100, 255); // Magenta
786
+ * t.lineWeight(2);
787
+ *
788
+ * // Rotate the curve around its geometric center
789
+ * // The bezier's control points: (5,20), (15,5), (25,35), (35,20)
790
+ * // Center = average of points; translate to center then draw with local coordinates
791
+ * const cx = (5 + 15 + 25 + 35) / 4;
792
+ * const cy = (20 + 5 + 35 + 20) / 4;
793
+ *
794
+ * t.translate(cx, cy);
795
+ * t.rotateZ(t.frameCount * 2);
796
+ * t.bezierCurve(5 - cx, 20 - cy, 15 - cx, 5 - cy, 25 - cx, 35 - cy, 35 - cx, 20 - cy);
797
+ * });
798
+ * ```
799
+ */
800
+ bezierCurve(x1: number, y1: number, cp1x: number, cp1y: number, cp2x: number, cp2y: number, x2: number, y2: number): void;
801
+ /**
802
+ * Set the character to be used for subsequent rendering operations.
803
+ * Accepts a single character string or a
804
+ * {@link TextmodeColor} produced via {@link color}. When a color is provided,
805
+ * the encoded glyph information is applied if available.
806
+ *
807
+ * @example
808
+ * ```javascript
809
+ * const t = textmode.create({
810
+ * width: 800,
811
+ * height: 600,
812
+ * })
813
+ *
814
+ * let semicolon;
815
+ *
816
+ * t.setup(() => {
817
+ * semicolon = t.color(';');
818
+ * });
819
+ *
820
+ * t.draw(() => {
821
+ * t.background(0);
822
+ * t.char('A');
823
+ * t.rect(10, 10);
824
+ *
825
+ * t.char(semicolon);
826
+ * t.translate(15, 0);
827
+ * t.rect(10, 10);
828
+ * });
829
+ * ```
830
+ */
831
+ char(character: string | TextmodeColor): void;
832
+ /**
833
+ * Set the character color for subsequent rendering operations.
834
+ * Accepts channel values, hex strings, or a {@link TextmodeColor} instance.
835
+ * @param value Color object, hex string, or grayscale value (0-255)
836
+ * @param g Optional green component when providing RGB values or alpha when using grayscale form
837
+ * @param b Optional blue component when providing RGB values
838
+ * @param a Optional alpha component (0-255)
839
+ *
840
+ * @example
841
+ * ```javascript
842
+ * const t = textmode.create({
843
+ * width: 800,
844
+ * height: 600,
845
+ * })
846
+ *
847
+ * const hotPink = t.color(255, 105, 180);
848
+ *
849
+ * t.draw(() => {
850
+ * t.background(0);
851
+ * t.char('A');
852
+ * t.charColor(hotPink);
853
+ * t.rect(10, 10);
854
+ * });
855
+ * ```
856
+ */
857
+ charColor(value: number | string | TextmodeColor, g?: number, b?: number, a?: number): void;
858
+ /**
859
+ * Set the cell background color for subsequent rendering operations.
860
+ * Accepts channel values, hex strings, or a {@link TextmodeColor} instance.
861
+ * @param value Color object, hex string, or grayscale value (0-255)
862
+ * @param g Optional green component when providing RGB values or alpha when using grayscale form
863
+ * @param b Optional blue component when providing RGB values
864
+ * @param a Optional alpha component (0-255)
865
+ *
866
+ * @example
867
+ * ```javascript
868
+ * const t = textmode.create({
869
+ * width: 800,
870
+ * height: 600,
871
+ * })
872
+ *
873
+ * const dusk = t.color('#203040');
874
+ *
875
+ * t.draw(() => {
876
+ * t.background(0);
877
+ * t.cellColor(dusk);
878
+ * t.char('A');
879
+ * t.rotateZ(t.frameCount * 2);
880
+ * t.rect(10, 10);
881
+ * });
882
+ * ```
883
+ */
884
+ cellColor(value: number | string | TextmodeColor, g?: number, b?: number, a?: number): void;
885
+ /**
886
+ * Toggle horizontal flipping for subsequent character rendering.
887
+ * @param toggle Whether to flip horizontally
888
+ *
889
+ * @example
890
+ * ```javascript
891
+ * const t = textmode.create({
892
+ * width: 800,
893
+ * height: 600,
894
+ * })
895
+ *
896
+ * t.draw(() => {
897
+ * t.background(0);
898
+ * t.flipX(true);
899
+ * t.rect(5, 5);
900
+ * });
901
+ * ```
902
+ */
903
+ flipX(toggle: boolean): void;
904
+ /**
905
+ * Toggle vertical flipping for subsequent character rendering.
906
+ * @param toggle Whether to flip vertically
907
+ *
908
+ * @example
909
+ * ```javascript
910
+ * const t = textmode.create({
911
+ * width: 800,
912
+ * height: 600,
913
+ * })
914
+ *
915
+ * t.draw(() => {
916
+ * t.background(0);
917
+ * t.flipY(true);
918
+ * t.rect(5, 5);
919
+ * });
920
+ * ```
921
+ */
922
+ flipY(toggle: boolean): void;
923
+ /**
924
+ * Set the character rotation angle for subsequent character rendering.
925
+ * @param degrees The rotation angle in degrees
926
+ *
927
+ * @example
928
+ * ```javascript
929
+ * const t = textmode.create({
930
+ * width: 800,
931
+ * height: 600,
932
+ * })
933
+ *
934
+ * t.draw(() => {
935
+ * t.background(0);
936
+ * t.char('A');
937
+ * t.charRotation(90); // Rotate character 90 degrees
938
+ * t.rotateZ(t.frameCount * 2);
939
+ * t.rect(10, 10);
940
+ * });
941
+ * ```
942
+ */
943
+ charRotation(degrees: number): void;
944
+ /**
945
+ * Toggle color inversion for subsequent character rendering.
946
+ * @param toggle Whether to invert colors
947
+ *
948
+ * @example
949
+ * ```javascript
950
+ * const t = textmode.create({
951
+ * width: 800,
952
+ * height: 600,
953
+ * })
954
+ *
955
+ * t.draw(() => {
956
+ * t.background(0);
957
+ * t.invert(true);
958
+ * t.char('A');
959
+ * t.rotateZ(t.frameCount * 2);
960
+ * t.rect(5, 5);
961
+ * });
962
+ * ```
963
+ */
964
+ invert(toggle: boolean): void;
965
+ /**
966
+ * Draw an ellipse with the current settings.
967
+ * Position is controlled via {@link translate}, {@link push}, and {@link pop}.
968
+ * @param width Width of the ellipse
969
+ * @param height Height of the ellipse
970
+ *
971
+ * @example
972
+ * ```javascript
973
+ * const t = textmode.create({
974
+ * width: 800,
975
+ * height: 600,
976
+ * })
977
+ *
978
+ * t.draw(() => {
979
+ * t.background(0);
980
+ * t.char('O');
981
+ * t.rotateZ(t.frameCount * 2);
982
+ * t.ellipse(10, 8);
983
+ * });
984
+ * ```
985
+ */
986
+ ellipse(width: number, height: number): void;
987
+ /**
988
+ * Draw a triangle with the current settings.
989
+ * @param x1 X-coordinate of the first vertex
990
+ * @param y1 Y-coordinate of the first vertex
991
+ * @param x2 X-coordinate of the second vertex
992
+ * @param y2 Y-coordinate of the second vertex
993
+ * @param x3 X-coordinate of the third vertex
994
+ * @param y3 Y-coordinate of the third vertex
995
+ *
996
+ * @example
997
+ * ```javascript
998
+ * const t = textmode.create({
999
+ * width: 800,
1000
+ * height: 600,
1001
+ * })
1002
+ *
1003
+ * t.draw(() => {
1004
+ * t.background(0);
1005
+ * t.triangle(10, 10, 20, 10, 15, 20);
1006
+ * });
1007
+ * ```
1008
+ */
1009
+ triangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): void;
1010
+ /**
1011
+ * Draw an arc with the current settings.
1012
+ * Position is controlled via {@link translate}, {@link push}, and {@link pop}.
1013
+ * @param width Width of the arc
1014
+ * @param height Height of the arc
1015
+ * @param startAngle Starting angle in degrees
1016
+ * @param endAngle Ending angle in degrees
1017
+ *
1018
+ * @example
1019
+ * ```javascript
1020
+ * const t = textmode.create({
1021
+ * width: 800,
1022
+ * height: 600,
1023
+ * })
1024
+ *
1025
+ * t.draw(() => {
1026
+ * t.background(0);
1027
+ * t.rotateZ(t.frameCount);
1028
+ * t.char('A');
1029
+ * t.arc(10, 10, 0, 90);
1030
+ * });
1031
+ * ```
1032
+ */
1033
+ arc(width: number, height: number, startAngle: number, endAngle: number): void;
1034
+ /**
1035
+ * Enable orthographic projection for the current frame.
1036
+ *
1037
+ * By default, textmode.js uses perspective projection. Calling this function
1038
+ * switches to orthographic projection for all geometries drawn in the current frame.
1039
+ * Orthographic projection renders objects without perspective distortion - parallel
1040
+ * lines remain parallel regardless of depth, and objects don't appear smaller as
1041
+ * they move away from the camera.
1042
+ *
1043
+ * **Note**: The projection mode resets to perspective at the start of each frame,
1044
+ * so `ortho()` must be called in every frame where you want orthographic projection.
1045
+ *
1046
+ * @example
1047
+ * ```javascript
1048
+ * const t = textmode.create({
1049
+ * width: 800,
1050
+ * height: 600,
1051
+ * });
1052
+ *
1053
+ * let useOrtho = false;
1054
+ *
1055
+ * // Toggle between ortho and perspective with spacebar
1056
+ * t.keyPressed((data) => {
1057
+ * if (data.key === ' ') {
1058
+ * useOrtho = !useOrtho;
1059
+ * }
1060
+ * });
1061
+ *
1062
+ * t.draw(() => {
1063
+ * t.background(0);
1064
+ *
1065
+ * // Enable orthographic projection if toggled on
1066
+ * if (useOrtho) {
1067
+ * t.ortho();
1068
+ * }
1069
+ *
1070
+ * // Animate the rectangle back and forth on the z-axis
1071
+ * const zPos = Math.sin(t.frameCount * 0.01) * 50;
1072
+ *
1073
+ * t.push();
1074
+ * t.translate(0, 0, zPos);
1075
+ * t.rotateZ(t.frameCount * 2);
1076
+ * t.rotateX(t.frameCount * 1.5);
1077
+ * t.char('A');
1078
+ * t.charColor(255, 100, 200);
1079
+ * t.rect(16, 16);
1080
+ * t.pop();
1081
+ * });
1082
+ * ```
1083
+ */
1084
+ ortho(): void;
1085
+ }