@holoscript/std 2.1.0

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/src/types.ts ADDED
@@ -0,0 +1,376 @@
1
+ /**
2
+ * Core Types for HoloScript
3
+ *
4
+ * Fundamental spatial and graphical types used throughout the language.
5
+ */
6
+
7
+ // =============================================================================
8
+ // VECTOR TYPES
9
+ // =============================================================================
10
+
11
+ /**
12
+ * 2D Vector
13
+ */
14
+ export interface Vec2 {
15
+ x: number;
16
+ y: number;
17
+ }
18
+
19
+ /**
20
+ * 3D Vector - The fundamental spatial type
21
+ */
22
+ export interface Vec3 {
23
+ x: number;
24
+ y: number;
25
+ z: number;
26
+ }
27
+
28
+ /**
29
+ * 4D Vector
30
+ */
31
+ export interface Vec4 {
32
+ x: number;
33
+ y: number;
34
+ z: number;
35
+ w: number;
36
+ }
37
+
38
+ // Array representations
39
+ export type Vec2Array = [number, number];
40
+ export type Vec3Array = [number, number, number];
41
+ export type Vec4Array = [number, number, number, number];
42
+
43
+ // =============================================================================
44
+ // QUATERNION
45
+ // =============================================================================
46
+
47
+ /**
48
+ * Quaternion for rotation representation
49
+ */
50
+ export interface Quat {
51
+ x: number;
52
+ y: number;
53
+ z: number;
54
+ w: number;
55
+ }
56
+
57
+ export type QuatArray = [number, number, number, number];
58
+
59
+ // =============================================================================
60
+ // TRANSFORM
61
+ // =============================================================================
62
+
63
+ /**
64
+ * Complete 3D transform
65
+ */
66
+ export interface Transform {
67
+ position: Vec3;
68
+ rotation: Quat;
69
+ scale: Vec3;
70
+ }
71
+
72
+ /**
73
+ * Euler angles (in degrees)
74
+ */
75
+ export interface EulerAngles {
76
+ x: number; // pitch
77
+ y: number; // yaw
78
+ z: number; // roll
79
+ }
80
+
81
+ // =============================================================================
82
+ // COLOR
83
+ // =============================================================================
84
+
85
+ /**
86
+ * RGB Color (0-1 range)
87
+ */
88
+ export interface ColorRGB {
89
+ r: number;
90
+ g: number;
91
+ b: number;
92
+ }
93
+
94
+ /**
95
+ * RGBA Color (0-1 range)
96
+ */
97
+ export interface ColorRGBA extends ColorRGB {
98
+ a: number;
99
+ }
100
+
101
+ /**
102
+ * HSL Color
103
+ */
104
+ export interface ColorHSL {
105
+ h: number; // 0-360
106
+ s: number; // 0-1
107
+ l: number; // 0-1
108
+ }
109
+
110
+ /**
111
+ * Color can be represented multiple ways
112
+ */
113
+ export type Color = string | ColorRGB | ColorRGBA | ColorHSL | number;
114
+
115
+ // =============================================================================
116
+ // BOUNDS
117
+ // =============================================================================
118
+
119
+ /**
120
+ * Axis-Aligned Bounding Box
121
+ */
122
+ export interface AABB {
123
+ min: Vec3;
124
+ max: Vec3;
125
+ }
126
+
127
+ /**
128
+ * Bounding Sphere
129
+ */
130
+ export interface BoundingSphere {
131
+ center: Vec3;
132
+ radius: number;
133
+ }
134
+
135
+ // =============================================================================
136
+ // RAY
137
+ // =============================================================================
138
+
139
+ /**
140
+ * Ray for raycasting
141
+ */
142
+ export interface Ray {
143
+ origin: Vec3;
144
+ direction: Vec3;
145
+ }
146
+
147
+ /**
148
+ * Raycast hit result
149
+ */
150
+ export interface RaycastHit {
151
+ point: Vec3;
152
+ normal: Vec3;
153
+ distance: number;
154
+ objectId?: string;
155
+ }
156
+
157
+ // =============================================================================
158
+ // UTILITY TYPES
159
+ // =============================================================================
160
+
161
+ /**
162
+ * Nullable type helper
163
+ */
164
+ export type Nullable<T> = T | null;
165
+
166
+ /**
167
+ * Optional type helper
168
+ */
169
+ export type Optional<T> = T | undefined;
170
+
171
+ /**
172
+ * Deep partial type
173
+ */
174
+ export type DeepPartial<T> = {
175
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
176
+ };
177
+
178
+ // =============================================================================
179
+ // FACTORY FUNCTIONS
180
+ // =============================================================================
181
+
182
+ /**
183
+ * Create a Vec2
184
+ */
185
+ export function vec2(x: number = 0, y: number = 0): Vec2 {
186
+ return { x, y };
187
+ }
188
+
189
+ /**
190
+ * Create a Vec3
191
+ */
192
+ export function vec3(x: number = 0, y: number = 0, z: number = 0): Vec3 {
193
+ return { x, y, z };
194
+ }
195
+
196
+ /**
197
+ * Create a Vec4
198
+ */
199
+ export function vec4(x: number = 0, y: number = 0, z: number = 0, w: number = 0): Vec4 {
200
+ return { x, y, z, w };
201
+ }
202
+
203
+ /**
204
+ * Create a Quaternion (identity by default)
205
+ */
206
+ export function quat(x: number = 0, y: number = 0, z: number = 0, w: number = 1): Quat {
207
+ return { x, y, z, w };
208
+ }
209
+
210
+ /**
211
+ * Create a Transform
212
+ */
213
+ export function transform(
214
+ position: Vec3 = vec3(),
215
+ rotation: Quat = quat(),
216
+ scale: Vec3 = vec3(1, 1, 1)
217
+ ): Transform {
218
+ return { position, rotation, scale };
219
+ }
220
+
221
+ /**
222
+ * Create an RGB color
223
+ */
224
+ export function rgb(r: number, g: number, b: number): ColorRGB {
225
+ return { r, g, b };
226
+ }
227
+
228
+ /**
229
+ * Create an RGBA color
230
+ */
231
+ export function rgba(r: number, g: number, b: number, a: number = 1): ColorRGBA {
232
+ return { r, g, b, a };
233
+ }
234
+
235
+ /**
236
+ * Create an HSL color
237
+ */
238
+ export function hsl(h: number, s: number, l: number): ColorHSL {
239
+ return { h, s, l };
240
+ }
241
+
242
+ /**
243
+ * Create an AABB
244
+ */
245
+ export function aabb(min: Vec3 = vec3(), max: Vec3 = vec3()): AABB {
246
+ return { min, max };
247
+ }
248
+
249
+ /**
250
+ * Create a Ray
251
+ */
252
+ export function ray(origin: Vec3, direction: Vec3): Ray {
253
+ return { origin, direction };
254
+ }
255
+
256
+ // =============================================================================
257
+ // CONVERSION UTILITIES
258
+ // =============================================================================
259
+
260
+ /**
261
+ * Convert Vec3 to array
262
+ */
263
+ export function vec3ToArray(v: Vec3): Vec3Array {
264
+ return [v.x, v.y, v.z];
265
+ }
266
+
267
+ /**
268
+ * Convert array to Vec3
269
+ */
270
+ export function arrayToVec3(arr: Vec3Array | number[]): Vec3 {
271
+ return { x: arr[0] || 0, y: arr[1] || 0, z: arr[2] || 0 };
272
+ }
273
+
274
+ /**
275
+ * Convert Quat to array
276
+ */
277
+ export function quatToArray(q: Quat): QuatArray {
278
+ return [q.x, q.y, q.z, q.w];
279
+ }
280
+
281
+ /**
282
+ * Convert array to Quat
283
+ */
284
+ export function arrayToQuat(arr: QuatArray | number[]): Quat {
285
+ return { x: arr[0] || 0, y: arr[1] || 0, z: arr[2] || 0, w: arr[3] ?? 1 };
286
+ }
287
+
288
+ /**
289
+ * Parse color from various formats
290
+ */
291
+ export function parseColor(color: Color): ColorRGBA {
292
+ if (typeof color === 'string') {
293
+ // Hex color
294
+ if (color.startsWith('#')) {
295
+ const hex = color.slice(1);
296
+ if (hex.length === 3) {
297
+ return {
298
+ r: parseInt(hex[0] + hex[0], 16) / 255,
299
+ g: parseInt(hex[1] + hex[1], 16) / 255,
300
+ b: parseInt(hex[2] + hex[2], 16) / 255,
301
+ a: 1,
302
+ };
303
+ } else if (hex.length === 6) {
304
+ return {
305
+ r: parseInt(hex.slice(0, 2), 16) / 255,
306
+ g: parseInt(hex.slice(2, 4), 16) / 255,
307
+ b: parseInt(hex.slice(4, 6), 16) / 255,
308
+ a: 1,
309
+ };
310
+ } else if (hex.length === 8) {
311
+ return {
312
+ r: parseInt(hex.slice(0, 2), 16) / 255,
313
+ g: parseInt(hex.slice(2, 4), 16) / 255,
314
+ b: parseInt(hex.slice(4, 6), 16) / 255,
315
+ a: parseInt(hex.slice(6, 8), 16) / 255,
316
+ };
317
+ }
318
+ }
319
+ // Named colors (basic support)
320
+ const namedColors: Record<string, ColorRGBA> = {
321
+ white: { r: 1, g: 1, b: 1, a: 1 },
322
+ black: { r: 0, g: 0, b: 0, a: 1 },
323
+ red: { r: 1, g: 0, b: 0, a: 1 },
324
+ green: { r: 0, g: 1, b: 0, a: 1 },
325
+ blue: { r: 0, g: 0, b: 1, a: 1 },
326
+ yellow: { r: 1, g: 1, b: 0, a: 1 },
327
+ cyan: { r: 0, g: 1, b: 1, a: 1 },
328
+ magenta: { r: 1, g: 0, b: 1, a: 1 },
329
+ };
330
+ return namedColors[color.toLowerCase()] || { r: 1, g: 1, b: 1, a: 1 };
331
+ }
332
+
333
+ if (typeof color === 'number') {
334
+ // Integer color (0xRRGGBB)
335
+ return {
336
+ r: ((color >> 16) & 0xff) / 255,
337
+ g: ((color >> 8) & 0xff) / 255,
338
+ b: (color & 0xff) / 255,
339
+ a: 1,
340
+ };
341
+ }
342
+
343
+ if ('h' in color) {
344
+ // HSL to RGB conversion
345
+ const { h, s, l } = color;
346
+ const c = (1 - Math.abs(2 * l - 1)) * s;
347
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
348
+ const m = l - c / 2;
349
+ let r = 0, g = 0, b = 0;
350
+
351
+ if (h < 60) { r = c; g = x; }
352
+ else if (h < 120) { r = x; g = c; }
353
+ else if (h < 180) { g = c; b = x; }
354
+ else if (h < 240) { g = x; b = c; }
355
+ else if (h < 300) { r = x; b = c; }
356
+ else { r = c; b = x; }
357
+
358
+ return { r: r + m, g: g + m, b: b + m, a: 1 };
359
+ }
360
+
361
+ if ('a' in color) {
362
+ return color as ColorRGBA;
363
+ }
364
+
365
+ return { ...color, a: 1 };
366
+ }
367
+
368
+ /**
369
+ * Color to hex string
370
+ */
371
+ export function colorToHex(color: ColorRGB | ColorRGBA): string {
372
+ const r = Math.round(color.r * 255).toString(16).padStart(2, '0');
373
+ const g = Math.round(color.g * 255).toString(16).padStart(2, '0');
374
+ const b = Math.round(color.b * 255).toString(16).padStart(2, '0');
375
+ return `#${r}${g}${b}`;
376
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022", "DOM"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "sourceMap": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }