textmode.js 0.8.1 → 0.9.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.
- package/dist/textmode.esm.js +2841 -2345
- package/dist/textmode.umd.js +18 -16
- package/dist/types/exports/conversion.d.ts +1 -0
- package/dist/types/exports/filters.d.ts +1 -0
- package/dist/types/exports/input.d.ts +1 -0
- package/dist/types/exports/layering.d.ts +1 -0
- package/dist/types/exports/loadables.d.ts +1 -0
- package/dist/types/exports/loading.d.ts +1 -0
- package/dist/types/exports/plugins.d.ts +1 -0
- package/dist/types/index.d.ts +35 -1
- package/dist/types/rendering/webgl/core/Framebuffer.d.ts +1 -1
- package/dist/types/rendering/webgl/core/Shader.d.ts +17 -3
- package/dist/types/rendering/webgl/core/interfaces/IFramebuffer.d.ts +1 -8
- package/dist/types/textmode/AnimationController.d.ts +29 -0
- package/dist/types/textmode/Grid.d.ts +2 -0
- package/dist/types/textmode/Textmodifier.d.ts +8 -15
- package/dist/types/textmode/interfaces/ITextmodifier.d.ts +3 -11
- package/dist/types/textmode/layers/Camera3D.d.ts +205 -0
- package/dist/types/textmode/layers/Layer3DCompositor.d.ts +152 -0
- package/dist/types/textmode/layers/LayerManager.d.ts +70 -25
- package/dist/types/textmode/layers/TextmodeLayer.d.ts +12 -52
- package/dist/types/textmode/layers/index.d.ts +4 -0
- package/dist/types/textmode/layers/interfaces/ILayerManager.d.ts +52 -0
- package/dist/types/textmode/layers/interfaces/ITextmodeLayer.d.ts +49 -2
- package/dist/types/textmode/managers/PluginManager.d.ts +155 -7
- package/dist/types/textmode/mixins/interfaces/IAnimationMixin.d.ts +133 -0
- package/dist/types/textmode/mixins/interfaces/IRenderingMixin.d.ts +80 -0
- package/dist/types/textmode/types.d.ts +4 -3
- package/dist/types/utils/TextmodeCollection.d.ts +262 -0
- package/dist/types/utils/mat3.d.ts +149 -0
- package/dist/types/utils/math.d.ts +26 -0
- package/package.json +36 -1
|
@@ -23,6 +23,139 @@ export interface IAnimationMixin {
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
frameRate(fps?: number): number | void;
|
|
26
|
+
/**
|
|
27
|
+
* Get the number of milliseconds since the sketch started running.
|
|
28
|
+
*
|
|
29
|
+
* `millis` keeps track of how long a sketch has been running in milliseconds
|
|
30
|
+
* (thousandths of a second). This information is often helpful for timing events
|
|
31
|
+
* and animations.
|
|
32
|
+
*
|
|
33
|
+
* Time tracking begins before the code in {@link setup} runs. If loading screen is
|
|
34
|
+
* enabled, `millis` begins tracking as soon as the loading screen starts.
|
|
35
|
+
*
|
|
36
|
+
* This property is connected to {@link secs} - setting one will affect the other.
|
|
37
|
+
*
|
|
38
|
+
* @returns Number of milliseconds since starting the sketch.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```javascript
|
|
42
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
43
|
+
*
|
|
44
|
+
* t.draw(() => {
|
|
45
|
+
* t.background(0);
|
|
46
|
+
*
|
|
47
|
+
* // Get the number of seconds the sketch has run
|
|
48
|
+
* const seconds = t.millis / 1000;
|
|
49
|
+
*
|
|
50
|
+
* t.text(`Running time: ${seconds.toFixed(1)} sec`, 10, 10);
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```javascript
|
|
56
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
57
|
+
*
|
|
58
|
+
* t.draw(() => {
|
|
59
|
+
* t.background(0);
|
|
60
|
+
*
|
|
61
|
+
* // Use millis for smooth animation
|
|
62
|
+
* const time = t.millis / 1000;
|
|
63
|
+
* const x = Math.sin(time) * 20 + 40;
|
|
64
|
+
*
|
|
65
|
+
* t.char('O', Math.floor(x), 10);
|
|
66
|
+
* });
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```javascript
|
|
71
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
72
|
+
*
|
|
73
|
+
* // Seek to a specific time in the animation
|
|
74
|
+
* t.millis = 5000; // Jump to 5 seconds
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
get millis(): number;
|
|
78
|
+
/**
|
|
79
|
+
* Set the elapsed milliseconds by adjusting the internal start time.
|
|
80
|
+
*
|
|
81
|
+
* This allows seeking/scrubbing in animations. Setting `millis` will also
|
|
82
|
+
* affect the value returned by {@link secs} since they are connected.
|
|
83
|
+
*
|
|
84
|
+
* @param value The new elapsed time in milliseconds
|
|
85
|
+
*/
|
|
86
|
+
set millis(value: number);
|
|
87
|
+
/**
|
|
88
|
+
* Get the number of seconds since the sketch started running.
|
|
89
|
+
*
|
|
90
|
+
* `secs` is a convenience property that returns the elapsed time in seconds
|
|
91
|
+
* instead of milliseconds. Equivalent to `millis / 1000`.
|
|
92
|
+
*
|
|
93
|
+
* Time tracking begins before the code in {@link setup} runs. If loading screen is
|
|
94
|
+
* enabled, `secs` begins tracking as soon as the loading screen starts.
|
|
95
|
+
*
|
|
96
|
+
* This property is connected to {@link millis} - setting one will affect the other.
|
|
97
|
+
*
|
|
98
|
+
* @returns Number of seconds since starting the sketch.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```javascript
|
|
102
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
103
|
+
*
|
|
104
|
+
* t.draw(() => {
|
|
105
|
+
* t.background(0);
|
|
106
|
+
*
|
|
107
|
+
* // Use secs for smooth time-based animations
|
|
108
|
+
* const angle = t.secs * Math.PI;
|
|
109
|
+
* const x = Math.sin(angle) * 10;
|
|
110
|
+
*
|
|
111
|
+
* t.text(`X: ${x.toFixed(2)}`, 10, 10);
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```javascript
|
|
117
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
118
|
+
*
|
|
119
|
+
* // Seek to a specific time in the animation
|
|
120
|
+
* t.secs = 10; // Jump to 10 seconds (equivalent to t.millis = 10000)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
get secs(): number;
|
|
124
|
+
/**
|
|
125
|
+
* Set the elapsed seconds by adjusting the internal start time.
|
|
126
|
+
*
|
|
127
|
+
* This allows seeking/scrubbing in animations. Setting `secs` will also
|
|
128
|
+
* affect the value returned by {@link millis} since they are connected.
|
|
129
|
+
*
|
|
130
|
+
* @param value The new elapsed time in seconds
|
|
131
|
+
*/
|
|
132
|
+
set secs(value: number);
|
|
133
|
+
/**
|
|
134
|
+
* Returns the time in milliseconds between the current frame and the previous frame.
|
|
135
|
+
*
|
|
136
|
+
* `deltaTime()` is useful for creating frame-rate-independent animations. By multiplying
|
|
137
|
+
* velocities and movements by `deltaTime()`, animations will run at consistent speeds
|
|
138
|
+
* regardless of the actual frame rate.
|
|
139
|
+
*
|
|
140
|
+
* @returns Time elapsed between current and previous frame in milliseconds.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```javascript
|
|
144
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
145
|
+
* let x = 0;
|
|
146
|
+
* const speed = 0.1; // units per millisecond
|
|
147
|
+
*
|
|
148
|
+
* t.draw(() => {
|
|
149
|
+
* t.background(0);
|
|
150
|
+
*
|
|
151
|
+
* // Move at consistent speed regardless of frame rate
|
|
152
|
+
* x += speed * t.deltaTime();
|
|
153
|
+
*
|
|
154
|
+
* t.text(`X: ${x.toFixed(2)}`, 10, 10);
|
|
155
|
+
* });
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
deltaTime(): number;
|
|
26
159
|
/**
|
|
27
160
|
* Stop the automatic rendering loop.
|
|
28
161
|
*
|
|
@@ -314,6 +314,14 @@ export interface IRenderingMixin {
|
|
|
314
314
|
* ```
|
|
315
315
|
*/
|
|
316
316
|
createFilterShader(fragmentSource: string): Promise<GLShader>;
|
|
317
|
+
/**
|
|
318
|
+
* Create a shader from vertex and fragment source code or file paths.
|
|
319
|
+
* Accepts inline shader source or file paths (e.g. './shader.frag', './shader.vert', '.frag', '.vert').
|
|
320
|
+
* @param vertexSource The vertex shader source code or a file path
|
|
321
|
+
* @param fragmentSource The fragment shader source code or a file path
|
|
322
|
+
* @returns A Promise that resolves to a compiled shader
|
|
323
|
+
*/
|
|
324
|
+
createShader(vertexSource: string, fragmentSource: string): Promise<GLShader>;
|
|
317
325
|
/**
|
|
318
326
|
* Sets the rotation angles for subsequent shape rendering operations.
|
|
319
327
|
*
|
|
@@ -1068,4 +1076,76 @@ export interface IRenderingMixin {
|
|
|
1068
1076
|
* ```
|
|
1069
1077
|
*/
|
|
1070
1078
|
arc(width: number, height: number, startAngle: number, endAngle: number): void;
|
|
1079
|
+
/**
|
|
1080
|
+
* Set the rendering mode to 2D (traditional ASCII compositing) or 3D (voxel raymarching).
|
|
1081
|
+
*
|
|
1082
|
+
* In 2D mode, each layer is individually converted to ASCII and then composited.
|
|
1083
|
+
* In 3D mode, layer data is stacked in depth and rendered through a voxel raymarching shader.
|
|
1084
|
+
*
|
|
1085
|
+
* @param mode The rendering mode: '2d' or '3d'.
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* ```javascript
|
|
1089
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
1090
|
+
*
|
|
1091
|
+
* t.draw(() => {
|
|
1092
|
+
* t.renderMode('3d');
|
|
1093
|
+
* t.rotation3D(t.frameCount * 0.5, t.frameCount * 0.3, 0);
|
|
1094
|
+
*
|
|
1095
|
+
* t.background(0);
|
|
1096
|
+
* t.char('@');
|
|
1097
|
+
* t.charColor(255, 100, 50);
|
|
1098
|
+
* t.rect(10, 10);
|
|
1099
|
+
* });
|
|
1100
|
+
* ```
|
|
1101
|
+
*/
|
|
1102
|
+
renderMode(mode: '2d' | '3d'): void;
|
|
1103
|
+
/**
|
|
1104
|
+
* Set the 3D rotation angles for voxel rendering (only applies in '3d' mode).
|
|
1105
|
+
*
|
|
1106
|
+
* @param x Rotation around the X axis in degrees.
|
|
1107
|
+
* @param y Rotation around the Y axis in degrees.
|
|
1108
|
+
* @param z Rotation around the Z axis in degrees.
|
|
1109
|
+
*
|
|
1110
|
+
* @example
|
|
1111
|
+
* ```javascript
|
|
1112
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
1113
|
+
*
|
|
1114
|
+
* t.draw(() => {
|
|
1115
|
+
* t.renderMode('3d');
|
|
1116
|
+
* t.rotation3D(30, t.frameCount, 0); // Tilt and spin
|
|
1117
|
+
* t.background(0);
|
|
1118
|
+
* t.char('#');
|
|
1119
|
+
* t.rect(15, 15);
|
|
1120
|
+
* });
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
rotation(x: number, y?: number, z?: number): void;
|
|
1124
|
+
/**
|
|
1125
|
+
* Set the 3D translation offset for voxel rendering (only applies in '3d' mode).
|
|
1126
|
+
*
|
|
1127
|
+
* @param x Translation along the X axis.
|
|
1128
|
+
* @param y Translation along the Y axis.
|
|
1129
|
+
* @param z Translation along the Z axis.
|
|
1130
|
+
*/
|
|
1131
|
+
translation3D(x: number, y?: number, z?: number): void;
|
|
1132
|
+
/**
|
|
1133
|
+
* Set the 3D zoom level for voxel rendering (only applies in '3d' mode).
|
|
1134
|
+
*
|
|
1135
|
+
* @param zoom Zoom factor (1 = no zoom, >1 = zoom in, <1 = zoom out).
|
|
1136
|
+
*
|
|
1137
|
+
* @example
|
|
1138
|
+
* ```javascript
|
|
1139
|
+
* const t = textmode.create({ width: 800, height: 600 });
|
|
1140
|
+
*
|
|
1141
|
+
* t.draw(() => {
|
|
1142
|
+
* t.renderMode('3d');
|
|
1143
|
+
* t.zoom3D(1.5 + Math.sin(t.frameCount * 0.02) * 0.5);
|
|
1144
|
+
* t.background(0);
|
|
1145
|
+
* t.char('*');
|
|
1146
|
+
* t.rect(10, 10);
|
|
1147
|
+
* });
|
|
1148
|
+
* ```
|
|
1149
|
+
*/
|
|
1150
|
+
zoom3D(zoom: number): void;
|
|
1071
1151
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TextmodePlugin } from './managers/PluginManager';
|
|
2
2
|
import type { LoadingScreenOptions } from './loading/';
|
|
3
3
|
/**
|
|
4
|
-
* Options
|
|
4
|
+
* Options when creating a {@link Textmodifier} instance.
|
|
5
5
|
*/
|
|
6
6
|
export type TextmodeOptions = {
|
|
7
7
|
/**
|
|
@@ -34,8 +34,9 @@ export type TextmodeOptions = {
|
|
|
34
34
|
*
|
|
35
35
|
* Useful for applying textmode conversion to p5.js sketches, YouTube videos, and sooo much more.
|
|
36
36
|
*
|
|
37
|
-
* All functionality of `textmode.js` remains available.
|
|
38
|
-
*
|
|
37
|
+
* All functionality of `textmode.js` remains available.
|
|
38
|
+
* Resizing the `textmode.js` canvas is not recommended though,
|
|
39
|
+
* since the overlay target automatically updates the size.
|
|
39
40
|
*/
|
|
40
41
|
overlay?: boolean;
|
|
41
42
|
/** List of plugins to install when the Textmodifier instance is created. */
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A generic, managed collection for objects that require lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* This class provides CRUD operations (Create/Read/Update/Delete) with support for:
|
|
5
|
+
* - Adding and removing items
|
|
6
|
+
* - Reordering items (move, swap)
|
|
7
|
+
* - Deferred initialization via pending items
|
|
8
|
+
* - Automatic disposal of removed items
|
|
9
|
+
* - Event callbacks for lifecycle events
|
|
10
|
+
*
|
|
11
|
+
* @typeParam T - The type of items stored in the collection
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Create a collection with a disposal callback
|
|
16
|
+
* const layers = new TextmodeCollection<TextmodeLayer>({
|
|
17
|
+
* onDispose: (layer) => layer.$dispose(),
|
|
18
|
+
* onAdd: (layer) => pluginManager.notifyLayerCreated(layer),
|
|
19
|
+
* onRemove: (layer) => pluginManager.notifyLayerDisposed(layer),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Add items
|
|
23
|
+
* const layer = new TextmodeLayer();
|
|
24
|
+
* layers.add(layer);
|
|
25
|
+
*
|
|
26
|
+
* // Iterate
|
|
27
|
+
* for (const layer of layers) {
|
|
28
|
+
* layer.draw();
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // Remove all
|
|
32
|
+
* layers.clear();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class TextmodeCollection<T> implements Iterable<T> {
|
|
36
|
+
private _items;
|
|
37
|
+
private _pendingItems;
|
|
38
|
+
private _isReady;
|
|
39
|
+
private readonly _options;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new TextmodeCollection.
|
|
42
|
+
*
|
|
43
|
+
* @param options Configuration options for the collection
|
|
44
|
+
*/
|
|
45
|
+
constructor(options?: TextmodeCollectionOptions<T>);
|
|
46
|
+
/**
|
|
47
|
+
* Mark the collection as ready and move all pending items to the active list.
|
|
48
|
+
*
|
|
49
|
+
* Call this after async initialization is complete. Any items added before
|
|
50
|
+
* this call will be moved from the pending queue to the active collection.
|
|
51
|
+
*
|
|
52
|
+
* @param initializeItem Optional async function to initialize each pending item
|
|
53
|
+
* @returns Promise that resolves when all pending items are initialized
|
|
54
|
+
*/
|
|
55
|
+
initialize(initializeItem?: (item: T) => Promise<void>): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Check if the collection has been initialized.
|
|
58
|
+
*/
|
|
59
|
+
get isReady(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Add an item to the collection.
|
|
62
|
+
*
|
|
63
|
+
* If the collection is not yet ready, the item is added to a pending queue.
|
|
64
|
+
* Once `initialize()` is called, pending items are moved to the active collection.
|
|
65
|
+
*
|
|
66
|
+
* @param item The item to add
|
|
67
|
+
* @returns The added item (for chaining)
|
|
68
|
+
*/
|
|
69
|
+
add(item: T): T;
|
|
70
|
+
/**
|
|
71
|
+
* Add multiple items to the collection.
|
|
72
|
+
*
|
|
73
|
+
* @param items The items to add
|
|
74
|
+
* @returns The added items
|
|
75
|
+
*/
|
|
76
|
+
addMany(items: T[]): T[];
|
|
77
|
+
/**
|
|
78
|
+
* Remove an item from the collection and dispose it.
|
|
79
|
+
*
|
|
80
|
+
* @param item The item to remove
|
|
81
|
+
* @returns true if the item was found and removed, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
remove(item: T): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Remove an item at a specific index.
|
|
86
|
+
*
|
|
87
|
+
* @param index The index of the item to remove
|
|
88
|
+
* @returns The removed item, or undefined if index is out of bounds
|
|
89
|
+
*/
|
|
90
|
+
removeAt(index: number): T | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Move an item to a new index in the collection.
|
|
93
|
+
*
|
|
94
|
+
* @param item The item to move
|
|
95
|
+
* @param newIndex The target index
|
|
96
|
+
* @returns true if the item was found and moved, false otherwise
|
|
97
|
+
*/
|
|
98
|
+
move(item: T, newIndex: number): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Swap the positions of two items in the collection.
|
|
101
|
+
*
|
|
102
|
+
* @param itemA The first item
|
|
103
|
+
* @param itemB The second item
|
|
104
|
+
* @returns true if both items were found and swapped, false otherwise
|
|
105
|
+
*/
|
|
106
|
+
swap(itemA: T, itemB: T): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Remove and dispose all items from the collection.
|
|
109
|
+
*
|
|
110
|
+
* This clears both active and pending items.
|
|
111
|
+
*/
|
|
112
|
+
clear(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Dispose the collection and all its items.
|
|
115
|
+
*
|
|
116
|
+
* After calling this, the collection should not be used.
|
|
117
|
+
*/
|
|
118
|
+
dispose(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Get all active items as a readonly array.
|
|
121
|
+
*/
|
|
122
|
+
get all(): readonly T[];
|
|
123
|
+
/**
|
|
124
|
+
* Get all pending items as a readonly array.
|
|
125
|
+
*/
|
|
126
|
+
get pending(): readonly T[];
|
|
127
|
+
/**
|
|
128
|
+
* Get the number of active items.
|
|
129
|
+
*/
|
|
130
|
+
get length(): number;
|
|
131
|
+
/**
|
|
132
|
+
* Get the total number of items (active + pending).
|
|
133
|
+
*/
|
|
134
|
+
get totalLength(): number;
|
|
135
|
+
/**
|
|
136
|
+
* Check if the collection is empty (no active items).
|
|
137
|
+
*/
|
|
138
|
+
get isEmpty(): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Get an item at a specific index.
|
|
141
|
+
*
|
|
142
|
+
* @param index The index of the item
|
|
143
|
+
* @returns The item, or undefined if index is out of bounds
|
|
144
|
+
*/
|
|
145
|
+
get(index: number): T | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* Get the first item in the collection.
|
|
148
|
+
*/
|
|
149
|
+
get first(): T | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* Get the last item in the collection.
|
|
152
|
+
*/
|
|
153
|
+
get last(): T | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* Get the index of an item.
|
|
156
|
+
*
|
|
157
|
+
* @param item The item to find
|
|
158
|
+
* @returns The index, or -1 if not found
|
|
159
|
+
*/
|
|
160
|
+
indexOf(item: T): number;
|
|
161
|
+
/**
|
|
162
|
+
* Check if an item exists in the collection.
|
|
163
|
+
*
|
|
164
|
+
* @param item The item to check
|
|
165
|
+
* @returns true if the item exists (in active or pending)
|
|
166
|
+
*/
|
|
167
|
+
has(item: T): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Iterate over all active items.
|
|
170
|
+
*/
|
|
171
|
+
[Symbol.iterator](): Iterator<T>;
|
|
172
|
+
/**
|
|
173
|
+
* Execute a callback for each active item.
|
|
174
|
+
*
|
|
175
|
+
* @param callback Function to execute for each item
|
|
176
|
+
*/
|
|
177
|
+
forEach(callback: (item: T, index: number) => void): void;
|
|
178
|
+
/**
|
|
179
|
+
* Map active items to a new array.
|
|
180
|
+
*
|
|
181
|
+
* @param callback Function to transform each item
|
|
182
|
+
* @returns New array with transformed items
|
|
183
|
+
*/
|
|
184
|
+
map<U>(callback: (item: T, index: number) => U): U[];
|
|
185
|
+
/**
|
|
186
|
+
* Filter active items.
|
|
187
|
+
*
|
|
188
|
+
* @param predicate Function to test each item
|
|
189
|
+
* @returns New array with items that pass the test
|
|
190
|
+
*/
|
|
191
|
+
filter(predicate: (item: T, index: number) => boolean): T[];
|
|
192
|
+
/**
|
|
193
|
+
* Find an item matching a predicate.
|
|
194
|
+
*
|
|
195
|
+
* @param predicate Function to test each item
|
|
196
|
+
* @returns The first matching item, or undefined
|
|
197
|
+
*/
|
|
198
|
+
find(predicate: (item: T, index: number) => boolean): T | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Find the index of an item matching a predicate.
|
|
201
|
+
*
|
|
202
|
+
* @param predicate Function to test each item
|
|
203
|
+
* @returns The index of the first matching item, or -1
|
|
204
|
+
*/
|
|
205
|
+
findIndex(predicate: (item: T, index: number) => boolean): number;
|
|
206
|
+
/**
|
|
207
|
+
* Check if any item matches a predicate.
|
|
208
|
+
*
|
|
209
|
+
* @param predicate Function to test each item
|
|
210
|
+
* @returns true if any item matches
|
|
211
|
+
*/
|
|
212
|
+
some(predicate: (item: T, index: number) => boolean): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Check if all items match a predicate.
|
|
215
|
+
*
|
|
216
|
+
* @param predicate Function to test each item
|
|
217
|
+
* @returns true if all items match
|
|
218
|
+
*/
|
|
219
|
+
every(predicate: (item: T, index: number) => boolean): boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Reduce active items to a single value.
|
|
222
|
+
*
|
|
223
|
+
* @param callback Reducer function
|
|
224
|
+
* @param initialValue Initial accumulator value
|
|
225
|
+
* @returns The final accumulated value
|
|
226
|
+
*/
|
|
227
|
+
reduce<U>(callback: (accumulator: U, item: T, index: number) => U, initialValue: U): U;
|
|
228
|
+
/**
|
|
229
|
+
* Dispose a single item using the configured disposal callback.
|
|
230
|
+
*/
|
|
231
|
+
private _disposeItem;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Configuration options for TextmodeCollection.
|
|
235
|
+
*
|
|
236
|
+
* @typeParam T - The type of items stored in the collection
|
|
237
|
+
*/
|
|
238
|
+
export interface TextmodeCollectionOptions<T> {
|
|
239
|
+
/**
|
|
240
|
+
* Called when an item is added to the active collection.
|
|
241
|
+
* Not called for pending items until they become active.
|
|
242
|
+
*/
|
|
243
|
+
onAdd?: (item: T) => void;
|
|
244
|
+
/**
|
|
245
|
+
* Called when an item is about to be removed from the collection.
|
|
246
|
+
* This is called before `onDispose`.
|
|
247
|
+
*/
|
|
248
|
+
onRemove?: (item: T) => void;
|
|
249
|
+
/**
|
|
250
|
+
* Called to dispose an item when it's removed from the collection.
|
|
251
|
+
* This is where you should clean up resources.
|
|
252
|
+
*/
|
|
253
|
+
onDispose?: (item: T) => void;
|
|
254
|
+
/**
|
|
255
|
+
* Called when an item is moved to a new index.
|
|
256
|
+
*/
|
|
257
|
+
onMove?: (item: T, oldIndex: number, newIndex: number) => void;
|
|
258
|
+
/**
|
|
259
|
+
* Called when two items are swapped.
|
|
260
|
+
*/
|
|
261
|
+
onSwap?: (itemA: T, itemB: T, indexA: number, indexB: number) => void;
|
|
262
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3x3 Matrix utilities for 3D transformations.
|
|
3
|
+
*
|
|
4
|
+
* All matrices are stored in row-major order as flat arrays of 9 elements:
|
|
5
|
+
* ```
|
|
6
|
+
* [m00, m01, m02,
|
|
7
|
+
* m10, m11, m12,
|
|
8
|
+
* m20, m21, m22]
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @module utils/mat3
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A 3x3 matrix represented as a tuple of 9 numbers in row-major order.
|
|
15
|
+
*/
|
|
16
|
+
export type Mat3 = [
|
|
17
|
+
number,
|
|
18
|
+
number,
|
|
19
|
+
number,
|
|
20
|
+
number,
|
|
21
|
+
number,
|
|
22
|
+
number,
|
|
23
|
+
number,
|
|
24
|
+
number,
|
|
25
|
+
number
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Create an identity 3x3 matrix.
|
|
29
|
+
*
|
|
30
|
+
* @returns A new identity matrix
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const identity = mat3Identity();
|
|
35
|
+
* // [1, 0, 0, 0, 1, 0, 0, 0, 1]
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function mat3Identity(): Mat3;
|
|
39
|
+
/**
|
|
40
|
+
* Multiply two 3x3 matrices in row-major order.
|
|
41
|
+
*
|
|
42
|
+
* @param a First matrix (left operand)
|
|
43
|
+
* @param b Second matrix (right operand)
|
|
44
|
+
* @returns The product matrix (a × b)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const result = mat3Multiply(rotationX, rotationY);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function mat3Multiply(a: Mat3, b: Mat3): Mat3;
|
|
52
|
+
/**
|
|
53
|
+
* Transpose a 3x3 matrix (swap rows and columns).
|
|
54
|
+
*
|
|
55
|
+
* For orthonormal rotation matrices, the transpose equals the inverse.
|
|
56
|
+
*
|
|
57
|
+
* @param m The matrix to transpose
|
|
58
|
+
* @returns The transposed matrix
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const inverse = mat3Transpose(rotationMatrix);
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function mat3Transpose(m: Mat3): Mat3;
|
|
66
|
+
/**
|
|
67
|
+
* Create a rotation matrix around the X axis.
|
|
68
|
+
*
|
|
69
|
+
* @param radians Rotation angle in radians
|
|
70
|
+
* @returns Rotation matrix around X axis
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* const rotX = mat3RotationX(Math.PI / 4); // 45° rotation
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function mat3RotationX(radians: number): Mat3;
|
|
78
|
+
/**
|
|
79
|
+
* Create a rotation matrix around the Y axis.
|
|
80
|
+
*
|
|
81
|
+
* @param radians Rotation angle in radians
|
|
82
|
+
* @returns Rotation matrix around Y axis
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const rotY = mat3RotationY(Math.PI / 2); // 90° rotation
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function mat3RotationY(radians: number): Mat3;
|
|
90
|
+
/**
|
|
91
|
+
* Create a rotation matrix around the Z axis.
|
|
92
|
+
*
|
|
93
|
+
* @param radians Rotation angle in radians
|
|
94
|
+
* @returns Rotation matrix around Z axis
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const rotZ = mat3RotationZ(Math.PI); // 180° rotation
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function mat3RotationZ(radians: number): Mat3;
|
|
102
|
+
/**
|
|
103
|
+
* Build a combined rotation matrix from Euler angles (in radians).
|
|
104
|
+
*
|
|
105
|
+
* The rotation order is: Z × Y × X (applied right-to-left,
|
|
106
|
+
* so X rotation is applied first to the vector).
|
|
107
|
+
*
|
|
108
|
+
* @param radiansX Rotation around X axis in radians
|
|
109
|
+
* @param radiansY Rotation around Y axis in radians
|
|
110
|
+
* @param radiansZ Rotation around Z axis in radians
|
|
111
|
+
* @returns Combined rotation matrix
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* import { degToRad } from './math';
|
|
116
|
+
* const rotation = mat3FromEuler(
|
|
117
|
+
* degToRad(45),
|
|
118
|
+
* degToRad(30),
|
|
119
|
+
* degToRad(0)
|
|
120
|
+
* );
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare function mat3FromEuler(radiansX: number, radiansY: number, radiansZ: number): Mat3;
|
|
124
|
+
/**
|
|
125
|
+
* Build a rotation matrix from Euler angles in degrees.
|
|
126
|
+
*
|
|
127
|
+
* This is a convenience function that converts degrees to radians
|
|
128
|
+
* and returns the transposed (inverse) matrix, which is commonly
|
|
129
|
+
* needed for shader uniforms.
|
|
130
|
+
*
|
|
131
|
+
* @param degX Rotation around X axis in degrees
|
|
132
|
+
* @param degY Rotation around Y axis in degrees
|
|
133
|
+
* @param degZ Rotation around Z axis in degrees
|
|
134
|
+
* @returns Transposed rotation matrix as Float32Array (for GPU upload)
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* const modelRotation = mat3FromEulerDegrees(45, 30, 0);
|
|
139
|
+
* shader.setUniform('u_modelRotation', modelRotation);
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export declare function mat3FromEulerDegrees(degX: number, degY: number, degZ: number): Float32Array;
|
|
143
|
+
/**
|
|
144
|
+
* Convert a Mat3 to a Float32Array for GPU upload.
|
|
145
|
+
*
|
|
146
|
+
* @param m The matrix to convert
|
|
147
|
+
* @returns Float32Array containing the matrix data
|
|
148
|
+
*/
|
|
149
|
+
export declare function mat3ToFloat32Array(m: Mat3): Float32Array;
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert degrees to radians.
|
|
3
|
+
*
|
|
4
|
+
* @param degrees Angle in degrees
|
|
5
|
+
* @returns Angle in radians
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* degToRad(180); // Math.PI
|
|
10
|
+
* degToRad(90); // Math.PI / 2
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function degToRad(degrees: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Convert radians to degrees.
|
|
16
|
+
*
|
|
17
|
+
* @param radians Angle in radians
|
|
18
|
+
* @returns Angle in degrees
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* radToDeg(Math.PI); // 180
|
|
23
|
+
* radToDeg(Math.PI / 2); // 90
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function radToDeg(radians: number): number;
|
|
1
27
|
/**
|
|
2
28
|
* Calculate the angle in degrees between two points.
|
|
3
29
|
* @param x1 - X coordinate of the first point
|