textmode.js 0.7.1 → 0.8.0-beta.2

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 (54) hide show
  1. package/dist/textmode.esm.js +2042 -2108
  2. package/dist/textmode.umd.js +16 -16
  3. package/dist/types/Textmode.d.ts +11 -11
  4. package/dist/types/errors/index.d.ts +1 -1
  5. package/dist/types/index.d.ts +11 -3
  6. package/dist/types/rendering/webgl/core/Framebuffer.d.ts +0 -6
  7. package/dist/types/rendering/webgl/core/Renderer.d.ts +7 -6
  8. package/dist/types/rendering/webgl/core/interfaces/IFramebuffer.d.ts +6 -6
  9. package/dist/types/rendering/webgl/core/interfaces/IRenderer.d.ts +3 -3
  10. package/dist/types/rendering/webgl/index.d.ts +2 -2
  11. package/dist/types/rendering/webgl/pipeline/MaterialBatchPipeline.d.ts +1 -1
  12. package/dist/types/textmode/Canvas.d.ts +2 -2
  13. package/dist/types/textmode/Grid.d.ts +32 -3
  14. package/dist/types/textmode/Textmodifier.d.ts +14 -72
  15. package/dist/types/textmode/conversion/ConversionManager.d.ts +73 -0
  16. package/dist/types/textmode/conversion/ConversionRegistry.d.ts +61 -18
  17. package/dist/types/textmode/conversion/index.d.ts +3 -1
  18. package/dist/types/textmode/filters/FilterManager.d.ts +0 -4
  19. package/dist/types/textmode/filters/index.d.ts +1 -1
  20. package/dist/types/textmode/interfaces/ITextmodifier.d.ts +165 -50
  21. package/dist/types/textmode/layers/Layer2DCompositor.d.ts +13 -20
  22. package/dist/types/textmode/layers/LayerManager.d.ts +31 -20
  23. package/dist/types/textmode/layers/TextmodeLayer.d.ts +58 -20
  24. package/dist/types/textmode/layers/interfaces/ILayerManager.d.ts +7 -0
  25. package/dist/types/textmode/layers/interfaces/ITextmodeLayer.d.ts +49 -28
  26. package/dist/types/textmode/layers/types.d.ts +16 -21
  27. package/dist/types/textmode/loadables/ITextmodeSource.d.ts +123 -0
  28. package/dist/types/textmode/loadables/TextmodeImage.d.ts +2 -2
  29. package/dist/types/textmode/loadables/TextmodeSource.d.ts +10 -118
  30. package/dist/types/textmode/loadables/font/CharacterExtractor.d.ts +1 -1
  31. package/dist/types/textmode/loadables/font/TextmodeFont.d.ts +3 -0
  32. package/dist/types/textmode/loadables/font/index.d.ts +2 -2
  33. package/dist/types/textmode/loadables/index.d.ts +0 -2
  34. package/dist/types/textmode/loadables/video/ITextmodeVideo.d.ts +75 -0
  35. package/dist/types/textmode/loadables/video/TextmodeVideo.d.ts +23 -126
  36. package/dist/types/textmode/loading/LoadingPhase.d.ts +26 -0
  37. package/dist/types/textmode/loading/LoadingScreenManager.d.ts +91 -93
  38. package/dist/types/textmode/loading/index.d.ts +3 -2
  39. package/dist/types/textmode/loading/types.d.ts +57 -57
  40. package/dist/types/textmode/managers/MouseManager.d.ts +24 -14
  41. package/dist/types/textmode/managers/TouchManager.d.ts +25 -13
  42. package/dist/types/textmode/mixins/index.d.ts +1 -2
  43. package/dist/types/textmode/mixins/interfaces/IAnimationMixin.d.ts +87 -87
  44. package/dist/types/textmode/mixins/interfaces/IKeyboardMixin.d.ts +128 -128
  45. package/dist/types/textmode/mixins/interfaces/IMouseMixin.d.ts +96 -105
  46. package/dist/types/textmode/mixins/interfaces/IRenderingMixin.d.ts +271 -370
  47. package/dist/types/textmode/mixins/interfaces/ITouchMixin.d.ts +1 -1
  48. package/dist/types/textmode/types.d.ts +2 -6
  49. package/package.json +5 -2
  50. package/dist/types/textmode/layers/filters/index.d.ts +0 -6
  51. package/dist/types/textmode/loadables/video/TextmodeVideoPreloader.d.ts +0 -29
  52. package/dist/types/textmode/loadables/video/types.d.ts +0 -43
  53. package/dist/types/textmode/mixins/FontMixin.d.ts +0 -8
  54. package/dist/types/textmode/mixins/interfaces/IFontMixin.d.ts +0 -46
@@ -1,8 +1,8 @@
1
- import type { GLFramebuffer, GLShader, TextmodeFramebufferOptions, UniformValue } from "../../../rendering/webgl";
1
+ import type { GLFramebuffer, GLShader, TextmodeFramebufferOptions, UniformValue } from '../../../rendering/webgl';
2
2
  import type { TextmodeSource } from '../../loadables/TextmodeSource';
3
3
  import type { TextmodeImage } from '../../loadables/TextmodeImage';
4
- import type { TextmodeVideo, TextmodeVideoOptions } from "../../loadables/video/TextmodeVideo";
5
- import type { TextmodeColor } from "../../TextmodeColor";
4
+ import type { TextmodeColor } from '../../TextmodeColor';
5
+ import type { TextmodeVideo } from '../../loadables';
6
6
  /**
7
7
  * Interface for rendering capabilities that will be mixed into Textmodifier
8
8
  */
@@ -12,13 +12,13 @@ export interface IRenderingMixin {
12
12
  * @param shader The custom shader to use
13
13
  *
14
14
  * @example
15
- * ```javascript
16
- * const t = textmode.create({ width: 800, height: 600 });
17
- *
18
- * let glitchShader;
19
- *
20
- * t.setup(async() => {
21
- * glitchShader = await t.createFilterShader(`#version 300 es
15
+ * ```javascript
16
+ * const t = textmode.create({ width: 800, height: 600 });
17
+ *
18
+ * let glitchShader;
19
+ *
20
+ * t.setup(async() => {
21
+ * glitchShader = await t.createFilterShader(`#version 300 es
22
22
  * precision highp float;
23
23
  * in vec2 v_uv;
24
24
  * uniform float u_intensity;
@@ -36,51 +36,51 @@ export interface IRenderingMixin {
36
36
  * }
37
37
  * `);
38
38
  *
39
- * t.draw(() => {
40
- * t.shader(glitchShader);
41
- * t.setUniform('u_intensity', Math.sin(t.frameCount * 0.1) * 0.02);
42
- * t.rect(t.grid.cols, t.grid.rows);
43
- * });
39
+ * t.draw(() => {
40
+ * t.shader(glitchShader);
41
+ * t.setUniform('u_intensity', Math.sin(t.frameCount * 0.1) * 0.02);
42
+ * t.rect(t.grid.cols, t.grid.rows);
43
+ * });
44
44
  * ```
45
45
  */
46
46
  shader(shader: GLShader): void;
47
47
  /**
48
48
  * Create a new framebuffer for offscreen rendering.
49
49
  *
50
- * The framebuffer uses the same MRT structure as the main rendering pipeline.
51
- * By default it allocates 4 attachments (character + color data).
50
+ * The framebuffer uses the same MRT structure as the main rendering pipeline.
51
+ * By default it allocates 4 attachments (character + color data).
52
52
  *
53
53
  * @param options Configuration options for the framebuffer.
54
54
  * @returns A new Framebuffer instance.
55
55
  *
56
- * @example
57
- * ```javascript
58
- * const t = textmode.create({
59
- * width: 800,
60
- * height: 600,
61
- * });
62
- *
63
- * // Create a framebuffer with 50x30 grid cells
64
- * const fb = t.createFramebuffer({
65
- * width: 50,
66
- * height: 30
67
- * });
68
- *
69
- * t.draw(() => {
70
- * // Render to framebuffer
71
- * fb.begin();
72
- * t.background(255, 0, 0);
73
- * t.charColor(255);
74
- * t.char('A');
75
- * t.rect(20, 10);
76
- * fb.end();
77
- *
78
- * // Render framebuffer to main canvas
79
- * t.background(0);
80
- * t.rotateZ(t.frameCount * 2);
81
- * t.image(fb);
82
- * });
83
- * ```
56
+ * @example
57
+ * ```javascript
58
+ * const t = textmode.create({
59
+ * width: 800,
60
+ * height: 600,
61
+ * });
62
+ *
63
+ * // Create a framebuffer with 50x30 grid cells
64
+ * const fb = t.createFramebuffer({
65
+ * width: 50,
66
+ * height: 30
67
+ * });
68
+ *
69
+ * t.draw(() => {
70
+ * // Render to framebuffer
71
+ * fb.begin();
72
+ * t.background(255, 0, 0);
73
+ * t.charColor(255);
74
+ * t.char('A');
75
+ * t.rect(20, 10);
76
+ * fb.end();
77
+ *
78
+ * // Render framebuffer to main canvas
79
+ * t.background(0);
80
+ * t.rotateZ(t.frameCount * 2);
81
+ * t.image(fb);
82
+ * });
83
+ * ```
84
84
  */
85
85
  createFramebuffer(options: TextmodeFramebufferOptions): GLFramebuffer;
86
86
  /**
@@ -131,29 +131,29 @@ export interface IRenderingMixin {
131
131
  * @param src URL or existing HTMLImageElement
132
132
  * @returns A Promise that resolves to a TextmodeImage object
133
133
  *
134
- * @example
135
- * ```javascript
136
- * const t = textmode.create({
137
- * width: 800,
138
- * height: 600,
139
- * });
140
- *
141
- * let img;
142
- *
143
- * t.setup(async () => {
144
- * img = await t.loadImage('https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80');
145
- * img.characters(" .:-=+*#%@");
146
- * });
147
- *
148
- * t.draw(() => {
149
- * t.background(0);
150
- *
151
- * if (img) {
152
- * // Draw the loaded image
153
- * t.image(img);
154
- * }
155
- * });
156
- * ```
134
+ * @example
135
+ * ```javascript
136
+ * const t = textmode.create({
137
+ * width: 800,
138
+ * height: 600,
139
+ * });
140
+ *
141
+ * let img;
142
+ *
143
+ * t.setup(async () => {
144
+ * img = await t.loadImage('https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&q=80');
145
+ * img.characters(" .:-=+*#%@");
146
+ * });
147
+ *
148
+ * t.draw(() => {
149
+ * t.background(0);
150
+ *
151
+ * if (img) {
152
+ * // Draw the loaded image
153
+ * t.image(img);
154
+ * }
155
+ * });
156
+ * ```
157
157
  */
158
158
  loadImage(src: string | HTMLImageElement): Promise<TextmodeImage>;
159
159
  /**
@@ -189,7 +189,7 @@ export interface IRenderingMixin {
189
189
  * });
190
190
  * ```
191
191
  */
192
- loadVideo(src: string | HTMLVideoElement, options?: TextmodeVideoOptions): Promise<TextmodeVideo>;
192
+ loadVideo(src: string | HTMLVideoElement): Promise<TextmodeVideo>;
193
193
  /**
194
194
  * Set a uniform value for the current custom shader.
195
195
  * @param name The name of the uniform variable
@@ -277,96 +277,50 @@ export interface IRenderingMixin {
277
277
  * @param fragmentSource The fragment shader source code or a file path (e.g., './shader.frag')
278
278
  * @returns A Promise that resolves to a compiled shader ready for use with {@link shader}
279
279
  *
280
- * @example
281
- * ```javascript
282
- * const t = textmode.create({
283
- * width: 800,
284
- * height: 600,
285
- * })
286
- *
287
- * let waveShader;
288
- *
289
- * t.setup(async () => {
290
- * // Load shader from file
291
- * waveShader = await t.createFilterShader('./shader.frag');
292
- *
293
- * // Or create from inline source
294
- * // waveShader = await t.createFilterShader(`#version 300 es
295
- * // precision highp float;
296
- * //
297
- * // in vec2 v_uv;
298
- * // in vec3 v_character;
299
- * // in vec4 v_primaryColor;
300
- * // in vec4 v_secondaryColor;
301
- * //
302
- * // uniform float u_time;
303
- * //
304
- * // layout(location = 0) out vec4 o_character;
305
- * // layout(location = 1) out vec4 o_primaryColor;
306
- * // layout(location = 2) out vec4 o_secondaryColor;
307
- * //
308
- * // void main() {
309
- * // // Shader code here
310
- * // }
311
- * // `);
312
- * });
313
- *
314
- * t.draw(() => {
315
- * if (waveShader) {
316
- * t.shader(waveShader);
317
- * t.setUniform('u_time', t.frameCount * 0.003);
318
- * t.rect(t.grid.cols, t.grid.rows);
319
- * }
320
- * });
321
- * ```
322
- */
323
- createFilterShader(fragmentSource: string): Promise<GLShader>;
324
- /**
325
- * Create a custom shader from vertex and fragment shader source code or file paths.
326
- * Both the vertex and fragment shaders can be provided as inline GLSL source code
327
- * or as file paths (e.g., './vertex.vert', './fragment.frag').
328
- * @param vertexSource The vertex shader source code or a file path (e.g., './shader.vert')
329
- * @param fragmentSource The fragment shader source code or a file path (e.g., './shader.frag')
330
- * @returns A Promise that resolves to a compiled shader ready for use with {@link shader}
280
+ * @example
281
+ * ```javascript
282
+ * const t = textmode.create({
283
+ * width: 800,
284
+ * height: 600,
285
+ * })
286
+ *
287
+ * let waveShader;
288
+ *
289
+ * t.setup(async () => {
290
+ * // Load shader from file
291
+ * waveShader = await t.createFilterShader('./shader.frag');
292
+ *
293
+ * // Or create from inline source
294
+ * // waveShader = await t.createFilterShader(`#version 300 es
295
+ * // precision highp float;
296
+ * //
297
+ * // in vec2 v_uv;
298
+ * // in vec3 v_character;
299
+ * // in vec4 v_primaryColor;
300
+ * // in vec4 v_secondaryColor;
301
+ * //
302
+ * // uniform float u_time;
303
+ * //
304
+ * // layout(location = 0) out vec4 o_character;
305
+ * // layout(location = 1) out vec4 o_primaryColor;
306
+ * // layout(location = 2) out vec4 o_secondaryColor;
307
+ * //
308
+ * // void main() {
309
+ * // // Shader code here
310
+ * // }
311
+ * // `);
312
+ * });
331
313
  *
332
- * @example
333
- * ```javascript
334
- * const t = textmode.create({
335
- * width: 800,
336
- * height: 600,
337
- * });
338
- *
339
- * let customShader;
340
- *
341
- * t.setup(async () => {
342
- * // Load shaders from files
343
- * customShader = await t.createShader('./vertex.vert', './fragment.frag');
344
- *
345
- * // Or create from inline source
346
- * // customShader = await t.createShader(
347
- * // `#version 300 es
348
- * // in vec2 a_position;
349
- * // void main() {
350
- * // gl_Position = vec4(a_position, 0.0, 1.0);
351
- * // }`,
352
- * // `#version 300 es
353
- * // precision highp float;
354
- * // out vec4 fragColor;
355
- * // void main() {
356
- * // fragColor = vec4(1.0, 0.0, 0.0, 1.0);
357
- * // }`
358
- * // );
359
- * });
360
- *
361
- * t.draw(() => {
362
- * if (customShader) {
363
- * t.shader(customShader);
364
- * t.rect(t.grid.cols, t.grid.rows);
365
- * }
366
- * });
367
- * ```
314
+ * t.draw(() => {
315
+ * if (waveShader) {
316
+ * t.shader(waveShader);
317
+ * t.setUniform('u_time', t.frameCount * 0.003);
318
+ * t.rect(t.grid.cols, t.grid.rows);
319
+ * }
320
+ * });
321
+ * ```
368
322
  */
369
- createShader(vertexSource: string, fragmentSource: string): Promise<GLShader>;
323
+ createFilterShader(fragmentSource: string): Promise<GLShader>;
370
324
  /**
371
325
  * Sets the rotation angles for subsequent shape rendering operations.
372
326
  *
@@ -610,45 +564,45 @@ export interface IRenderingMixin {
610
564
  * @param value Grayscale value, hex string, single character, or an existing color
611
565
  * @param g Optional green component, or `value` when using grayscale form
612
566
  * @param b Optional blue component, or `value` when using grayscale form
613
- * @param a Optional alpha component when using RGB form
614
- *
615
- * Example usage of the {@link color} helper.
616
- *
617
- * @example
618
- * ```javascript
619
- * const t = textmode.create({ width: 800, height: 600 });
620
- *
621
- * // Grayscale (0 = black, 255 = white)
622
- * const gray = t.color(128);
623
- *
624
- * // RGB
625
- * const hotPink = t.color(255, 105, 180);
626
- *
627
- * // RGBA (alpha 0-255)
628
- * const semiTransparentRed = t.color(255, 0, 0, 128);
629
- *
630
- * // Hex string
631
- * const dusk = t.color('#203040');
632
- *
633
- * t.draw(() => {
634
- * // Using colors with other drawing APIs
635
- * t.background(gray);
636
- * t.charColor(hotPink);
637
- * t.char('A');
638
- * t.rect(5, 5);
639
- *
640
- * t.translate(5, 0);
641
- * t.cellColor(dusk);
642
- * t.char('*');
643
- * t.rect(5, 5);
644
- *
645
- * t.translate(5, 0);
646
- * t.charColor("#FF00FF");
647
- * t.char("B");
648
- * t.rect(5, 5);
649
- * });
650
- * ```
651
- */
567
+ * @param a Optional alpha component when using RGB form
568
+ *
569
+ * Example usage of the {@link color} helper.
570
+ *
571
+ * @example
572
+ * ```javascript
573
+ * const t = textmode.create({ width: 800, height: 600 });
574
+ *
575
+ * // Grayscale (0 = black, 255 = white)
576
+ * const gray = t.color(128);
577
+ *
578
+ * // RGB
579
+ * const hotPink = t.color(255, 105, 180);
580
+ *
581
+ * // RGBA (alpha 0-255)
582
+ * const semiTransparentRed = t.color(255, 0, 0, 128);
583
+ *
584
+ * // Hex string
585
+ * const dusk = t.color('#203040');
586
+ *
587
+ * t.draw(() => {
588
+ * // Using colors with other drawing APIs
589
+ * t.background(gray);
590
+ * t.charColor(hotPink);
591
+ * t.char('A');
592
+ * t.rect(5, 5);
593
+ *
594
+ * t.translate(5, 0);
595
+ * t.cellColor(dusk);
596
+ * t.char('*');
597
+ * t.rect(5, 5);
598
+ *
599
+ * t.translate(5, 0);
600
+ * t.charColor("#FF00FF");
601
+ * t.char("B");
602
+ * t.rect(5, 5);
603
+ * });
604
+ * ```
605
+ */
652
606
  color(value: number | string | TextmodeColor, g?: number, b?: number, a?: number): TextmodeColor;
653
607
  /**
654
608
  * Draw a rectangle with the current settings.
@@ -680,42 +634,42 @@ export interface IRenderingMixin {
680
634
  * Draw a 1x1 rectangle with the current settings.
681
635
  *
682
636
  * @example
683
- * ```javascript
684
- * const t = textmode.create({ width: 800, height: 600 });
685
- *
686
- * t.draw(() => {
687
- * t.background(0);
688
- *
689
- * const angle = t.frameCount * 0.06;
690
- * const radius = Math.min(t.grid.cols, t.grid.rows) * 0.35;
691
- *
692
- * // Draw a short trail of points behind the leading point
693
- * for (let i = 0; i < 10; i++) {
694
- * const a = angle - i * 0.18;
695
- * const r = radius * (1 - i * 0.08);
696
- * const x = Math.round(Math.cos(a) * r);
697
- * const y = Math.round(Math.sin(a) * r);
698
- *
699
- * // Color and brightness fade across the trail
700
- * const brightness = Math.max(40, 255 - i * 20);
701
- * const blue = Math.max(60, 255 - i * 25);
702
- * const green = 120 + i * 8;
703
- *
704
- * t.push();
705
- * t.translate(x, y);
706
- * t.char('*');
707
- * t.charColor(brightness, green, blue);
708
- * t.point();
709
- *
710
- * t.pop();
711
- * }
712
- *
713
- * // Leading point drawn with highest brightness
714
- * t.char('@');
715
- * t.charColor(255, 255, 160);
716
- * t.translate(Math.round(Math.cos(angle) * radius), Math.round(Math.sin(angle) * radius));
717
- * t.point();
718
- * });
637
+ * ```javascript
638
+ * const t = textmode.create({ width: 800, height: 600 });
639
+ *
640
+ * t.draw(() => {
641
+ * t.background(0);
642
+ *
643
+ * const angle = t.frameCount * 0.06;
644
+ * const radius = Math.min(t.grid.cols, t.grid.rows) * 0.35;
645
+ *
646
+ * // Draw a short trail of points behind the leading point
647
+ * for (let i = 0; i < 10; i++) {
648
+ * const a = angle - i * 0.18;
649
+ * const r = radius * (1 - i * 0.08);
650
+ * const x = Math.round(Math.cos(a) * r);
651
+ * const y = Math.round(Math.sin(a) * r);
652
+ *
653
+ * // Color and brightness fade across the trail
654
+ * const brightness = Math.max(40, 255 - i * 20);
655
+ * const blue = Math.max(60, 255 - i * 25);
656
+ * const green = 120 + i * 8;
657
+ *
658
+ * t.push();
659
+ * t.translate(x, y);
660
+ * t.char('*');
661
+ * t.charColor(brightness, green, blue);
662
+ * t.point();
663
+ *
664
+ * t.pop();
665
+ * }
666
+ *
667
+ * // Leading point drawn with highest brightness
668
+ * t.char('@');
669
+ * t.charColor(255, 255, 160);
670
+ * t.translate(Math.round(Math.cos(angle) * radius), Math.round(Math.sin(angle) * radius));
671
+ * t.point();
672
+ * });
719
673
  * ```
720
674
  */
721
675
  point(): void;
@@ -726,29 +680,29 @@ export interface IRenderingMixin {
726
680
  * @param x2 X-coordinate of the line end point
727
681
  * @param y2 Y-coordinate of the line end point
728
682
  *
729
- * @example
730
- * ```javascript
731
- * const t = textmode.create({
732
- * width: 800,
733
- * height: 600,
734
- * })
735
- *
736
- * t.draw(() => {
737
- * t.background(0);
738
- *
739
- * t.char('*');
740
- * t.charColor(255, 100, 255); // Magenta
741
- * t.lineWeight(2);
742
- *
743
- * const halfWidth = 5;
744
- * const halfHeight = 7.5;
745
- *
746
- * t.push();
747
- * t.rotateZ(t.frameCount * 2);
748
- * t.line(-halfWidth, halfHeight, halfWidth, -halfHeight);
749
- * t.pop();
750
- * });
751
- * ```
683
+ * @example
684
+ * ```javascript
685
+ * const t = textmode.create({
686
+ * width: 800,
687
+ * height: 600,
688
+ * })
689
+ *
690
+ * t.draw(() => {
691
+ * t.background(0);
692
+ *
693
+ * t.char('*');
694
+ * t.charColor(255, 100, 255); // Magenta
695
+ * t.lineWeight(2);
696
+ *
697
+ * const halfWidth = 5;
698
+ * const halfHeight = 7.5;
699
+ *
700
+ * t.push();
701
+ * t.rotateZ(t.frameCount * 2);
702
+ * t.line(-halfWidth, halfHeight, halfWidth, -halfHeight);
703
+ * t.pop();
704
+ * });
705
+ * ```
752
706
  */
753
707
  line(x1: number, y1: number, x2: number, y2: number): void;
754
708
  /**
@@ -805,39 +759,39 @@ export interface IRenderingMixin {
805
759
  * Update the line weight (thickness) for subsequent {@link line} and {@link bezierCurve} calls.
806
760
  * @param weight The line weight (thickness) to set.
807
761
  *
808
- * @example
809
- * ```javascript
810
- * const t = textmode.create({
811
- * width: 800,
812
- * height: 600,
813
- * })
814
- *
815
- * t.draw(() => {
816
- * t.background('#050810');
817
- *
818
- * // Animate the weight so every line breathes differently
819
- * const layers = 6;
820
- * const halfCols = t.grid.cols / 2;
821
- * const spacing = 4;
822
- *
823
- * for (let i = 0; i < layers; i++) {
824
- * const phase = t.frameCount * 0.03 + i * 0.8;
825
- * const pulse = 0.75 + 3.25 * (0.5 + 0.5 * Math.sin(phase));
826
- * const wobble = Math.sin(phase * 1.6) * 4;
827
- * const centeredRow = (i - (layers - 1) / 2) * spacing;
828
- *
829
- * t.lineWeight(Math.round(pulse));
830
- * t.charColor(160 + i * 12, 200 - i * 8, 255);
831
- * t.char('-');
832
- * t.line(
833
- * -halfCols + 2,
834
- * centeredRow + wobble,
835
- * halfCols - 2,
836
- * centeredRow - wobble,
837
- * );
838
- * }
839
- * });
840
- * ```
762
+ * @example
763
+ * ```javascript
764
+ * const t = textmode.create({
765
+ * width: 800,
766
+ * height: 600,
767
+ * })
768
+ *
769
+ * t.draw(() => {
770
+ * t.background('#050810');
771
+ *
772
+ * // Animate the weight so every line breathes differently
773
+ * const layers = 6;
774
+ * const halfCols = t.grid.cols / 2;
775
+ * const spacing = 4;
776
+ *
777
+ * for (let i = 0; i < layers; i++) {
778
+ * const phase = t.frameCount * 0.03 + i * 0.8;
779
+ * const pulse = 0.75 + 3.25 * (0.5 + 0.5 * Math.sin(phase));
780
+ * const wobble = Math.sin(phase * 1.6) * 4;
781
+ * const centeredRow = (i - (layers - 1) / 2) * spacing;
782
+ *
783
+ * t.lineWeight(Math.round(pulse));
784
+ * t.charColor(160 + i * 12, 200 - i * 8, 255);
785
+ * t.char('-');
786
+ * t.line(
787
+ * -halfCols + 2,
788
+ * centeredRow + wobble,
789
+ * halfCols - 2,
790
+ * centeredRow - wobble,
791
+ * );
792
+ * }
793
+ * });
794
+ * ```
841
795
  */
842
796
  lineWeight(weight: number): void;
843
797
  /**
@@ -852,40 +806,38 @@ export interface IRenderingMixin {
852
806
  * @param x2 End point X coordinate
853
807
  * @param y2 End point Y coordinate
854
808
  *
855
- * @example
856
- * ```javascript
857
- * const t = textmode.create({
858
- * width: 800,
859
- * height: 600,
860
- * })
861
- *
862
- * t.draw(() => {
863
- * t.background(0);
864
- * t.translate(-t.grid.cols / 2, -t.grid.rows / 2);
865
- *
866
- * // Draw a smooth S-curve
867
- * t.char('*');
868
- * t.charColor(255, 100, 255); // Magenta
869
- * t.lineWeight(2);
870
- *
871
- * // Rotate the curve around its geometric center
872
- * // The bezier's control points: (5,20), (15,5), (25,35), (35,20)
873
- * // Center = average of points; translate to center then draw with local coordinates
874
- * const cx = (5 + 15 + 25 + 35) / 4;
875
- * const cy = (20 + 5 + 35 + 20) / 4;
876
- *
877
- * t.translate(cx, cy);
878
- * t.rotateZ(t.frameCount * 2);
879
- * t.bezierCurve(5 - cx, 20 - cy, 15 - cx, 5 - cy, 25 - cx, 35 - cy, 35 - cx, 20 - cy);
880
- * });
881
- * ```
809
+ * @example
810
+ * ```javascript
811
+ * const t = textmode.create({
812
+ * width: 800,
813
+ * height: 600,
814
+ * })
815
+ *
816
+ * t.draw(() => {
817
+ * t.background(0);
818
+ * t.translate(-t.grid.cols / 2, -t.grid.rows / 2);
819
+ *
820
+ * // Draw a smooth S-curve
821
+ * t.char('*');
822
+ * t.charColor(255, 100, 255); // Magenta
823
+ * t.lineWeight(2);
824
+ *
825
+ * // Rotate the curve around its geometric center
826
+ * // The bezier's control points: (5,20), (15,5), (25,35), (35,20)
827
+ * // Center = average of points; translate to center then draw with local coordinates
828
+ * const cx = (5 + 15 + 25 + 35) / 4;
829
+ * const cy = (20 + 5 + 35 + 20) / 4;
830
+ *
831
+ * t.translate(cx, cy);
832
+ * t.rotateZ(t.frameCount * 2);
833
+ * t.bezierCurve(5 - cx, 20 - cy, 15 - cx, 5 - cy, 25 - cx, 35 - cy, 35 - cx, 20 - cy);
834
+ * });
835
+ * ```
882
836
  */
883
837
  bezierCurve(x1: number, y1: number, cp1x: number, cp1y: number, cp2x: number, cp2y: number, x2: number, y2: number): void;
884
838
  /**
885
839
  * Set the character to be used for subsequent rendering operations.
886
- * Accepts a single character string or a
887
- * {@link TextmodeColor} produced via {@link color}. When a color is provided,
888
- * the encoded glyph information is applied if available.
840
+ * Accepts a single character string.
889
841
  *
890
842
  * @example
891
843
  * ```javascript
@@ -905,7 +857,7 @@ export interface IRenderingMixin {
905
857
  * });
906
858
  * ```
907
859
  */
908
- char(character: string | TextmodeColor): void;
860
+ char(character: string): void;
909
861
  /**
910
862
  * Set the character color for subsequent rendering operations.
911
863
  * Accepts channel values, hex strings, or a {@link TextmodeColor} instance.
@@ -1116,55 +1068,4 @@ export interface IRenderingMixin {
1116
1068
  * ```
1117
1069
  */
1118
1070
  arc(width: number, height: number, startAngle: number, endAngle: number): void;
1119
- /**
1120
- * Enable orthographic projection for the current frame.
1121
- *
1122
- * By default, textmode.js uses perspective projection. Calling this function
1123
- * switches to orthographic projection for all geometries drawn in the current frame.
1124
- * Orthographic projection renders objects without perspective distortion - parallel
1125
- * lines remain parallel regardless of depth, and objects don't appear smaller as
1126
- * they move away from the camera.
1127
- *
1128
- * **Note**: The projection mode resets to perspective at the start of each frame,
1129
- * so `ortho()` must be called in every frame where you want orthographic projection.
1130
- *
1131
- * @example
1132
- * ```javascript
1133
- * const t = textmode.create({
1134
- * width: 800,
1135
- * height: 600,
1136
- * });
1137
- *
1138
- * let useOrtho = false;
1139
- *
1140
- * // Toggle between ortho and perspective with spacebar
1141
- * t.keyPressed((data) => {
1142
- * if (data.key === ' ') {
1143
- * useOrtho = !useOrtho;
1144
- * }
1145
- * });
1146
- *
1147
- * t.draw(() => {
1148
- * t.background(0);
1149
- *
1150
- * // Enable orthographic projection if toggled on
1151
- * if (useOrtho) {
1152
- * t.ortho();
1153
- * }
1154
- *
1155
- * // Animate the rectangle back and forth on the z-axis
1156
- * const zPos = Math.sin(t.frameCount * 0.01) * 50;
1157
- *
1158
- * t.push();
1159
- * t.translate(0, 0, zPos);
1160
- * t.rotateZ(t.frameCount * 2);
1161
- * t.rotateX(t.frameCount * 1.5);
1162
- * t.char('A');
1163
- * t.charColor(255, 100, 200);
1164
- * t.rect(16, 16);
1165
- * t.pop();
1166
- * });
1167
- * ```
1168
- */
1169
- ortho(): void;
1170
1071
  }