@gui-chat-plugin/present3d 0.0.1 → 0.0.3

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.
@@ -1,2171 +0,0 @@
1
- var P = Object.defineProperty;
2
- var x = (n, e, s) => e in n ? P(n, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : n[e] = s;
3
- var d = (n, e, s) => x(n, typeof e != "symbol" ? e + "" : e, s);
4
- import * as l from "three";
5
- import { Evaluator as M, Brush as B, INTERSECTION as g, SUBTRACTION as C, ADDITION as w } from "three-bvh-csg";
6
- const U = "present3D", k = {
7
- type: "function",
8
- name: U,
9
- description: "Display interactive 3D visualizations using the full ShapeScript language with expressions, variables, control flow, and functions.",
10
- parameters: {
11
- type: "object",
12
- properties: {
13
- title: {
14
- type: "string",
15
- description: "Title for the 3D visualization"
16
- },
17
- script: {
18
- type: "string",
19
- description: `ShapeScript code defining the 3D scene. Full language features supported.
20
-
21
- ## SYNTAX OVERVIEW:
22
-
23
- ### Expressions & Operators:
24
- - Arithmetic: +, -, *, /, % with proper precedence
25
- - Comparison: =, <>, <, <=, >, >=
26
- - Boolean: and, or, not
27
- - Parentheses for grouping: (2 + 3) * 4
28
-
29
- ### Variables:
30
- define radius 2
31
- define red (1 0 0)
32
- sphere { size radius color red }
33
-
34
- ### Control Flow:
35
-
36
- For loops with variables:
37
- for i in 1 to 5 {
38
- cube { position (i * 2) 0 0 size 1 }
39
- }
40
-
41
- For loops with step:
42
- for i in 0 to 10 step 2 {
43
- sphere { position 0 i 0 }
44
- }
45
-
46
- If/else conditionals:
47
- define showSphere 1
48
- if showSphere {
49
- sphere { size 2 }
50
- } else {
51
- cube { size 2 }
52
- }
53
-
54
- Switch statements:
55
- define shape 2
56
- switch shape {
57
- case 1
58
- cube
59
- case 2
60
- sphere
61
- else
62
- cone
63
- }
64
-
65
- ### Built-in Functions:
66
-
67
- Math: round, floor, ceil, abs, sign, sqrt, pow, min, max
68
- Trig: sin, cos, tan, asin, acos, atan, atan2 (uses radians)
69
- Vector: dot, cross, length, normalize, sum
70
-
71
- IMPORTANT: Function calls require NO space between name and parenthesis:
72
- - sin(x) ✓ function call
73
- - sin (x) ✗ NOT a function call (identifier + parenthesized expression)
74
-
75
- Examples:
76
- for i in 1 to 8 {
77
- define angle (i * 0.785) // 45 degrees in radians
78
- cube { position (cos(angle) * 3) 0 (sin(angle) * 3) }
79
- }
80
-
81
- ### Primitives & Properties:
82
-
83
- Shapes: cube, sphere, cylinder, cone, torus
84
- Properties: position X Y Z, rotation X Y Z, size X Y Z
85
- Materials: color R G B (0-1), opacity (0-1)
86
-
87
- ### CSG Operations:
88
- union, difference, intersection, xor, stencil
89
-
90
- Example:
91
- difference {
92
- sphere { size 2 color (1 0.5 0) }
93
- cube { size 1.5 }
94
- }
95
-
96
- ### Comments:
97
- // Single-line comment
98
- /* Multi-line
99
- comment */
100
-
101
- ## COMPLETE EXAMPLES:
102
-
103
- Linear arrangement with expressions:
104
- define spacing 1.5
105
- for i in 1 to 4 {
106
- cylinder { position ((i - 2.5) * spacing) 0 0 size 0.4 1 }
107
- }
108
-
109
- Circular pattern:
110
- define count 12
111
- for i in 1 to count {
112
- define angle ((i / count) * 6.283) // 2 * PI
113
- cube {
114
- position (cos(angle) * 3) 0 (sin(angle) * 3)
115
- color (i / count) 0.5 (1 - i / count)
116
- size 0.5
117
- }
118
- }
119
-
120
- Conditional geometry:
121
- define makeHollow 1
122
- if makeHollow {
123
- difference {
124
- sphere { size 2 color (1 0 0) }
125
- sphere { size 1.7 }
126
- }
127
- } else {
128
- sphere { size 2 color (1 0 0) }
129
- }
130
-
131
- Mathematical visualization:
132
- for x in -5 to 5 {
133
- for z in -5 to 5 {
134
- define height (sin(x * 0.5) * cos(z * 0.5) * 2)
135
- cube {
136
- position (x * 0.3) height (z * 0.3)
137
- size 0.25 (abs(height) + 0.1) 0.25
138
- color (0.5 + height * 0.25) 0.3 (0.5 - height * 0.25)
139
- }
140
- }
141
- }`
142
- }
143
- },
144
- required: ["title", "script"]
145
- }
146
- }, O = async (n, e) => {
147
- const { script: s, title: r } = e;
148
- if (!s || s.trim() === "")
149
- throw new Error("ShapeScript code is required but was not provided");
150
- return {
151
- message: `Created 3D visualization: ${r}`,
152
- title: r,
153
- data: { script: s },
154
- instructions: "Acknowledge that the 3D visualization has been created and is displayed to the user. They can interact with it by rotating, zooming, and panning the camera."
155
- };
156
- }, Y = {
157
- toolDefinition: k,
158
- execute: O,
159
- generatingMessage: "Creating 3D visualization...",
160
- waitingMessage: "Tell the user that the 3D visualization was created and will be presented shortly.",
161
- isEnabled: () => !0
162
- }, H = O, Q = [
163
- {
164
- name: "Basic Shapes",
165
- args: {
166
- title: "Basic 3D Shapes",
167
- script: `// Basic shapes demonstration
168
- cube { position -2 0 0 size 1 color (1 0.3 0.3) }
169
- sphere { position 0 0 0 size 1 color (0.3 1 0.3) }
170
- cylinder { position 2 0 0 size 0.5 1 color (0.3 0.3 1) }`
171
- }
172
- },
173
- {
174
- name: "Circular Pattern",
175
- args: {
176
- title: "Circular Pattern",
177
- script: `// Create a circular pattern of cubes
178
- define count 12
179
- for i in 1 to count {
180
- define angle ((i / count) * 6.283)
181
- cube {
182
- position (cos(angle) * 3) 0 (sin(angle) * 3)
183
- color (i / count) 0.5 (1 - i / count)
184
- size 0.5
185
- }
186
- }`
187
- }
188
- },
189
- {
190
- name: "CSG Difference",
191
- args: {
192
- title: "Hollow Sphere",
193
- script: `// Create a hollow sphere using CSG difference
194
- difference {
195
- sphere { size 2 color (1 0.5 0) }
196
- sphere { size 1.7 color (1 1 1) }
197
- cube { position 0 0 2 size 2 }
198
- }`
199
- }
200
- }
201
- ];
202
- var t = /* @__PURE__ */ ((n) => (n.CUBE = "CUBE", n.SPHERE = "SPHERE", n.CYLINDER = "CYLINDER", n.CONE = "CONE", n.TORUS = "TORUS", n.CIRCLE = "CIRCLE", n.SQUARE = "SQUARE", n.POLYGON = "POLYGON", n.EXTRUDE = "EXTRUDE", n.LOFT = "LOFT", n.LATHE = "LATHE", n.FILL = "FILL", n.HULL = "HULL", n.GROUP = "GROUP", n.PATH = "PATH", n.POINT = "POINT", n.CURVE = "CURVE", n.DETAIL = "DETAIL", n.BACKGROUND = "BACKGROUND", n.TEXTURE = "TEXTURE", n.UNION = "UNION", n.DIFFERENCE = "DIFFERENCE", n.INTERSECTION = "INTERSECTION", n.XOR = "XOR", n.STENCIL = "STENCIL", n.FOR = "FOR", n.IN = "IN", n.TO = "TO", n.STEP = "STEP", n.IF = "IF", n.ELSE = "ELSE", n.SWITCH = "SWITCH", n.CASE = "CASE", n.DEFINE = "DEFINE", n.OPTION = "OPTION", n.POSITION = "POSITION", n.ROTATION = "ROTATION", n.ORIENTATION = "ORIENTATION", n.SIZE = "SIZE", n.COLOR = "COLOR", n.OPACITY = "OPACITY", n.ROTATE = "ROTATE", n.TRANSLATE = "TRANSLATE", n.SCALE = "SCALE", n.NUMBER = "NUMBER", n.IDENTIFIER = "IDENTIFIER", n.STRING = "STRING", n.PLUS = "PLUS", n.MINUS = "MINUS", n.STAR = "STAR", n.DIVIDE = "DIVIDE", n.PERCENT = "PERCENT", n.LPAREN = "LPAREN", n.RPAREN = "RPAREN", n.LBRACKET = "LBRACKET", n.RBRACKET = "RBRACKET", n.DOT = "DOT", n.EQUALS = "EQUALS", n.NOT_EQUALS = "NOT_EQUALS", n.LESS = "LESS", n.LESS_EQUAL = "LESS_EQUAL", n.GREATER = "GREATER", n.GREATER_EQUAL = "GREATER_EQUAL", n.AND = "AND", n.OR = "OR", n.NOT = "NOT", n.LBRACE = "LBRACE", n.RBRACE = "RBRACE", n.COMMA = "COMMA", n.SLASH = "SLASH", n.NEWLINE = "NEWLINE", n.EOF = "EOF", n.COMMENT = "COMMENT", n))(t || {});
203
- class R extends Error {
204
- constructor(e, s, r) {
205
- super(
206
- s !== void 0 && r !== void 0 ? `Parse error at line ${s}, column ${r}: ${e}` : `Parse error: ${e}`
207
- ), this.line = s, this.column = r, this.name = "ParseError";
208
- }
209
- }
210
- class D {
211
- constructor(e) {
212
- d(this, "input");
213
- d(this, "pos", 0);
214
- d(this, "line", 1);
215
- d(this, "column", 1);
216
- this.input = e;
217
- }
218
- peek(e = 0) {
219
- return this.input[this.pos + e] || "";
220
- }
221
- advance() {
222
- const e = this.input[this.pos++];
223
- return e === `
224
- ` ? (this.line++, this.column = 1) : this.column++, e;
225
- }
226
- skipWhitespace() {
227
- for (; this.pos < this.input.length; ) {
228
- const e = this.peek();
229
- if (e === " " || e === " " || e === "\r")
230
- this.advance();
231
- else if (e === "/" && this.peek(1) === "/")
232
- for (; this.peek() && this.peek() !== `
233
- `; )
234
- this.advance();
235
- else if (e === "/" && this.peek(1) === "*") {
236
- this.advance(), this.advance();
237
- let s = 1;
238
- for (; this.pos < this.input.length && s > 0; )
239
- this.peek() === "/" && this.peek(1) === "*" ? (s++, this.advance(), this.advance()) : this.peek() === "*" && this.peek(1) === "/" ? (s--, this.advance(), this.advance()) : this.advance();
240
- } else
241
- break;
242
- }
243
- }
244
- readNumber() {
245
- const e = this.line, s = this.column;
246
- let r = "";
247
- for (this.peek() === "-" && (r += this.advance()); this.pos < this.input.length; ) {
248
- const i = this.peek();
249
- if (i >= "0" && i <= "9" || i === ".")
250
- r += this.advance();
251
- else
252
- break;
253
- }
254
- return {
255
- type: t.NUMBER,
256
- value: parseFloat(r),
257
- line: e,
258
- column: s
259
- };
260
- }
261
- readIdentifier() {
262
- const e = this.line, s = this.column;
263
- let r = "";
264
- for (; this.pos < this.input.length; ) {
265
- const o = this.peek();
266
- if (o >= "a" && o <= "z" || o >= "A" && o <= "Z" || o >= "0" && o <= "9" || o === "_")
267
- r += this.advance();
268
- else
269
- break;
270
- }
271
- return {
272
- type: {
273
- cube: t.CUBE,
274
- sphere: t.SPHERE,
275
- cylinder: t.CYLINDER,
276
- cone: t.CONE,
277
- torus: t.TORUS,
278
- circle: t.CIRCLE,
279
- square: t.SQUARE,
280
- polygon: t.POLYGON,
281
- extrude: t.EXTRUDE,
282
- loft: t.LOFT,
283
- lathe: t.LATHE,
284
- fill: t.FILL,
285
- hull: t.HULL,
286
- group: t.GROUP,
287
- path: t.PATH,
288
- point: t.POINT,
289
- curve: t.CURVE,
290
- detail: t.DETAIL,
291
- background: t.BACKGROUND,
292
- texture: t.TEXTURE,
293
- union: t.UNION,
294
- difference: t.DIFFERENCE,
295
- intersection: t.INTERSECTION,
296
- xor: t.XOR,
297
- stencil: t.STENCIL,
298
- for: t.FOR,
299
- in: t.IN,
300
- to: t.TO,
301
- step: t.STEP,
302
- if: t.IF,
303
- else: t.ELSE,
304
- switch: t.SWITCH,
305
- case: t.CASE,
306
- define: t.DEFINE,
307
- option: t.OPTION,
308
- position: t.POSITION,
309
- rotation: t.ROTATION,
310
- orientation: t.ORIENTATION,
311
- size: t.SIZE,
312
- color: t.COLOR,
313
- opacity: t.OPACITY,
314
- rotate: t.ROTATE,
315
- translate: t.TRANSLATE,
316
- scale: t.SCALE,
317
- and: t.AND,
318
- or: t.OR,
319
- not: t.NOT
320
- }[r.toLowerCase()] || t.IDENTIFIER,
321
- value: r,
322
- line: e,
323
- column: s
324
- };
325
- }
326
- readString() {
327
- const e = this.line, s = this.column;
328
- let r = "";
329
- for (this.advance(); this.pos < this.input.length; ) {
330
- const i = this.peek();
331
- if (i === '"') {
332
- this.advance();
333
- break;
334
- } else if (i === "\\") {
335
- this.advance();
336
- const a = this.peek();
337
- a === '"' || a === "\\" ? r += this.advance() : a === "n" ? (r += `
338
- `, this.advance()) : a === "t" ? (r += " ", this.advance()) : (r += a, this.advance());
339
- } else
340
- r += this.advance();
341
- }
342
- return {
343
- type: t.STRING,
344
- value: r,
345
- line: e,
346
- column: s
347
- };
348
- }
349
- tokenize() {
350
- const e = [];
351
- for (; this.pos < this.input.length; ) {
352
- const s = this.pos;
353
- this.skipWhitespace();
354
- const r = this.pos > s;
355
- if (this.pos >= this.input.length) break;
356
- const i = this.peek(), a = this.line, o = this.column;
357
- if (i >= "0" && i <= "9" || i === "-" && this.peek(1) >= "0" && this.peek(1) <= "9" && (e.length === 0 || e[e.length - 1].type === t.LPAREN || e[e.length - 1].type === t.COMMA || e[e.length - 1].type === t.LBRACE || e[e.length - 1].type === t.LBRACKET || this.isOperator(e[e.length - 1].type))) {
358
- const c = this.readNumber();
359
- c.precedingWhitespace = r, e.push(c);
360
- } else if (i >= "a" && i <= "z" || i >= "A" && i <= "Z") {
361
- const c = this.readIdentifier();
362
- c.precedingWhitespace = r, e.push(c);
363
- } else if (i === '"') {
364
- const c = this.readString();
365
- c.precedingWhitespace = r, e.push(c);
366
- } else if (i === "<" && this.peek(1) === ">")
367
- this.advance(), this.advance(), e.push({
368
- type: t.NOT_EQUALS,
369
- value: "<>",
370
- line: a,
371
- column: o,
372
- precedingWhitespace: r
373
- });
374
- else if (i === "<" && this.peek(1) === "=")
375
- this.advance(), this.advance(), e.push({
376
- type: t.LESS_EQUAL,
377
- value: "<=",
378
- line: a,
379
- column: o,
380
- precedingWhitespace: r
381
- });
382
- else if (i === ">" && this.peek(1) === "=")
383
- this.advance(), this.advance(), e.push({
384
- type: t.GREATER_EQUAL,
385
- value: ">=",
386
- line: a,
387
- column: o,
388
- precedingWhitespace: r
389
- });
390
- else if (i === "+")
391
- this.advance(), e.push({
392
- type: t.PLUS,
393
- value: "+",
394
- line: a,
395
- column: o,
396
- precedingWhitespace: r
397
- });
398
- else if (i === "-")
399
- this.advance(), e.push({
400
- type: t.MINUS,
401
- value: "-",
402
- line: a,
403
- column: o,
404
- precedingWhitespace: r
405
- });
406
- else if (i === "*")
407
- this.advance(), e.push({
408
- type: t.STAR,
409
- value: "*",
410
- line: a,
411
- column: o,
412
- precedingWhitespace: r
413
- });
414
- else if (i === "/")
415
- this.advance(), e.push({
416
- type: t.DIVIDE,
417
- value: "/",
418
- line: a,
419
- column: o,
420
- precedingWhitespace: r
421
- });
422
- else if (i === "%")
423
- this.advance(), e.push({
424
- type: t.PERCENT,
425
- value: "%",
426
- line: a,
427
- column: o,
428
- precedingWhitespace: r
429
- });
430
- else if (i === "(")
431
- this.advance(), e.push({
432
- type: t.LPAREN,
433
- value: "(",
434
- line: a,
435
- column: o,
436
- precedingWhitespace: r
437
- });
438
- else if (i === ")")
439
- this.advance(), e.push({
440
- type: t.RPAREN,
441
- value: ")",
442
- line: a,
443
- column: o,
444
- precedingWhitespace: r
445
- });
446
- else if (i === "[")
447
- this.advance(), e.push({
448
- type: t.LBRACKET,
449
- value: "[",
450
- line: a,
451
- column: o,
452
- precedingWhitespace: r
453
- });
454
- else if (i === "]")
455
- this.advance(), e.push({
456
- type: t.RBRACKET,
457
- value: "]",
458
- line: a,
459
- column: o,
460
- precedingWhitespace: r
461
- });
462
- else if (i === "{")
463
- this.advance(), e.push({
464
- type: t.LBRACE,
465
- value: "{",
466
- line: a,
467
- column: o,
468
- precedingWhitespace: r
469
- });
470
- else if (i === "}")
471
- this.advance(), e.push({
472
- type: t.RBRACE,
473
- value: "}",
474
- line: a,
475
- column: o,
476
- precedingWhitespace: r
477
- });
478
- else if (i === ",")
479
- this.advance(), e.push({
480
- type: t.COMMA,
481
- value: ",",
482
- line: a,
483
- column: o,
484
- precedingWhitespace: r
485
- });
486
- else if (i === ".")
487
- this.advance(), e.push({
488
- type: t.DOT,
489
- value: ".",
490
- line: a,
491
- column: o,
492
- precedingWhitespace: r
493
- });
494
- else if (i === "=")
495
- this.advance(), e.push({
496
- type: t.EQUALS,
497
- value: "=",
498
- line: a,
499
- column: o,
500
- precedingWhitespace: r
501
- });
502
- else if (i === "<")
503
- this.advance(), e.push({
504
- type: t.LESS,
505
- value: "<",
506
- line: a,
507
- column: o,
508
- precedingWhitespace: r
509
- });
510
- else if (i === ">")
511
- this.advance(), e.push({
512
- type: t.GREATER,
513
- value: ">",
514
- line: a,
515
- column: o,
516
- precedingWhitespace: r
517
- });
518
- else if (i === `
519
- `)
520
- this.advance(), e.push({
521
- type: t.NEWLINE,
522
- value: `
523
- `,
524
- line: a,
525
- column: o,
526
- precedingWhitespace: r
527
- });
528
- else
529
- throw new R(`Unexpected character: '${i}'`, a, o);
530
- }
531
- return e.push({
532
- type: t.EOF,
533
- value: "",
534
- line: this.line,
535
- column: this.column,
536
- precedingWhitespace: !1
537
- }), e;
538
- }
539
- isOperator(e) {
540
- return e === t.PLUS || e === t.MINUS || e === t.STAR || e === t.DIVIDE || e === t.PERCENT || e === t.EQUALS || e === t.NOT_EQUALS || e === t.LESS || e === t.LESS_EQUAL || e === t.GREATER || e === t.GREATER_EQUAL || e === t.AND || e === t.OR;
541
- }
542
- }
543
- class F {
544
- constructor(e) {
545
- d(this, "tokens");
546
- d(this, "pos", 0);
547
- this.tokens = e;
548
- }
549
- current() {
550
- return this.tokens[this.pos];
551
- }
552
- peek(e = 1) {
553
- return this.tokens[this.pos + e] || this.tokens[this.tokens.length - 1];
554
- }
555
- advance() {
556
- return this.tokens[this.pos++];
557
- }
558
- expect(e) {
559
- const s = this.current();
560
- if (s.type !== e)
561
- throw new R(
562
- `Expected ${e} but got ${s.type}`,
563
- s.line,
564
- s.column
565
- );
566
- return this.advance();
567
- }
568
- // Expect an identifier, but allow keywords to be used as identifiers
569
- expectIdentifier() {
570
- const e = this.current();
571
- if (e.type === t.IDENTIFIER)
572
- return this.advance();
573
- if (typeof e.value == "string")
574
- return this.advance();
575
- throw new R(
576
- `Expected identifier but got ${e.type}`,
577
- e.line,
578
- e.column
579
- );
580
- }
581
- skipNewlines() {
582
- for (; this.current().type === t.NEWLINE; )
583
- this.advance();
584
- }
585
- // Expression parsing with precedence climbing
586
- parseExpression(e = 0) {
587
- let s = this.parsePrimary();
588
- for (; ; ) {
589
- const r = this.current(), i = this.getPrecedence(r.type);
590
- if (i < e) break;
591
- const a = this.tokenTypeToOperator(r.type);
592
- if (!a) break;
593
- this.advance();
594
- const o = this.parseExpression(i + 1);
595
- s = {
596
- type: "binary",
597
- operator: a,
598
- left: s,
599
- right: o
600
- };
601
- }
602
- return s;
603
- }
604
- parsePrimary() {
605
- const e = this.current();
606
- if (e.type === t.MINUS || e.type === t.NOT)
607
- return this.advance(), {
608
- type: "unary",
609
- operator: e.type === t.MINUS ? "-" : "not",
610
- operand: this.parsePrimary()
611
- };
612
- if (e.type === t.LPAREN) {
613
- this.advance();
614
- const s = [];
615
- if (s.push(this.parseExpression()), this.current().type === t.COMMA)
616
- for (; this.current().type === t.COMMA && (this.advance(), this.current().type !== t.RPAREN); )
617
- s.push(this.parseExpression());
618
- else {
619
- const r = this.current();
620
- if ((r.type === t.NUMBER || r.type === t.IDENTIFIER || r.type === t.MINUS || r.type === t.LPAREN) && r.type !== t.RPAREN)
621
- for (; ; ) {
622
- const a = this.current();
623
- if (a.type === t.NUMBER || a.type === t.IDENTIFIER || a.type === t.MINUS || a.type === t.LPAREN)
624
- s.push(this.parseExpression());
625
- else
626
- break;
627
- }
628
- }
629
- return this.expect(t.RPAREN), s.length === 1 ? s[0] : { type: "tuple", elements: s };
630
- }
631
- if (e.type === t.NUMBER)
632
- return this.advance(), {
633
- type: "number",
634
- value: e.value
635
- };
636
- if (e.type === t.STRING)
637
- return this.advance(), {
638
- type: "identifier",
639
- // Treat strings as special identifiers for now
640
- name: e.value
641
- };
642
- if (e.type === t.IDENTIFIER) {
643
- const s = e.value;
644
- if (this.advance(), this.current().type === t.LPAREN && !this.current().precedingWhitespace) {
645
- this.advance();
646
- const r = [];
647
- if (this.current().type !== t.RPAREN)
648
- for (r.push(this.parseExpression()); this.current().type === t.COMMA && (this.advance(), this.current().type !== t.RPAREN); )
649
- r.push(this.parseExpression());
650
- return this.expect(t.RPAREN), {
651
- type: "call",
652
- name: s,
653
- args: r
654
- };
655
- }
656
- return {
657
- type: "identifier",
658
- name: s
659
- };
660
- }
661
- if (typeof e.value == "string") {
662
- const s = e.value;
663
- return this.advance(), {
664
- type: "identifier",
665
- name: s
666
- };
667
- }
668
- throw new R(
669
- `Unexpected token in expression: ${e.type}`,
670
- e.line,
671
- e.column
672
- );
673
- }
674
- getPrecedence(e) {
675
- switch (e) {
676
- case t.OR:
677
- return 1;
678
- case t.AND:
679
- return 2;
680
- case t.EQUALS:
681
- case t.NOT_EQUALS:
682
- return 3;
683
- case t.LESS:
684
- case t.LESS_EQUAL:
685
- case t.GREATER:
686
- case t.GREATER_EQUAL:
687
- return 4;
688
- case t.PLUS:
689
- case t.MINUS:
690
- return 5;
691
- case t.STAR:
692
- case t.DIVIDE:
693
- case t.PERCENT:
694
- return 6;
695
- default:
696
- return 0;
697
- }
698
- }
699
- tokenTypeToOperator(e) {
700
- switch (e) {
701
- case t.PLUS:
702
- return "+";
703
- case t.MINUS:
704
- return "-";
705
- case t.STAR:
706
- return "*";
707
- case t.DIVIDE:
708
- return "/";
709
- case t.PERCENT:
710
- return "%";
711
- case t.EQUALS:
712
- return "=";
713
- case t.NOT_EQUALS:
714
- return "<>";
715
- case t.LESS:
716
- return "<";
717
- case t.LESS_EQUAL:
718
- return "<=";
719
- case t.GREATER:
720
- return ">";
721
- case t.GREATER_EQUAL:
722
- return ">=";
723
- case t.AND:
724
- return "and";
725
- case t.OR:
726
- return "or";
727
- default:
728
- return null;
729
- }
730
- }
731
- // Parse vector or expression
732
- // Handles both: "x y z" (space-separated) and "(x, y, z)" (tuple)
733
- parseVectorOrExpression() {
734
- const e = this.parseExpression(), s = this.current(), r = s.type === t.IDENTIFIER && this.peek().type === t.LBRACE;
735
- if ((s.type === t.NUMBER || s.type === t.IDENTIFIER || s.type === t.MINUS || s.type === t.LPAREN) && !r && s.type !== t.COMMA) {
736
- const a = [e];
737
- for (; ; ) {
738
- const o = this.current(), c = o.type === t.IDENTIFIER && this.peek().type === t.LBRACE;
739
- if ((o.type === t.NUMBER || o.type === t.IDENTIFIER || o.type === t.MINUS || o.type === t.LPAREN) && !c)
740
- a.push(this.parseExpression());
741
- else
742
- break;
743
- }
744
- if (a.length > 1)
745
- return { type: "tuple", elements: a };
746
- }
747
- return e.type === "tuple", e;
748
- }
749
- parseProperties() {
750
- const e = {};
751
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
752
- switch (this.skipNewlines(), this.current().type) {
753
- case t.POSITION:
754
- this.advance(), e.position = this.parseVectorOrExpression();
755
- break;
756
- case t.ROTATION:
757
- this.advance(), e.rotation = this.parseVectorOrExpression();
758
- break;
759
- case t.ORIENTATION:
760
- this.advance(), e.orientation = this.parseVectorOrExpression();
761
- break;
762
- case t.SIZE:
763
- this.advance(), e.size = this.parseVectorOrExpression();
764
- break;
765
- case t.COLOR:
766
- this.advance(), e.color = this.parseVectorOrExpression();
767
- break;
768
- case t.OPACITY:
769
- this.advance(), e.opacity = this.parseExpression();
770
- break;
771
- case t.RBRACE:
772
- return e;
773
- default:
774
- return e;
775
- }
776
- this.skipNewlines();
777
- }
778
- return e;
779
- }
780
- parseBlockContents() {
781
- this.skipNewlines();
782
- const e = [];
783
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
784
- const s = this.parseNode();
785
- s && e.push(s), this.skipNewlines();
786
- }
787
- return e;
788
- }
789
- parseBlock() {
790
- this.expect(t.LBRACE);
791
- const e = this.parseBlockContents();
792
- return this.expect(t.RBRACE), e;
793
- }
794
- parseShape(e) {
795
- this.advance();
796
- let s = {};
797
- return this.current().type === t.LBRACE && (this.expect(t.LBRACE), s = this.parseProperties(), this.expect(t.RBRACE)), {
798
- type: "shape",
799
- primitive: e,
800
- properties: s
801
- };
802
- }
803
- parseCSG(e) {
804
- this.advance();
805
- const s = this.parseBlock();
806
- return {
807
- type: "csg",
808
- operation: e,
809
- children: s
810
- };
811
- }
812
- parseForLoop() {
813
- this.advance();
814
- let e = "i";
815
- if (this.current().type === t.IDENTIFIER && (e = this.current().value, this.advance()), this.current().type === t.IN) {
816
- this.advance();
817
- const a = this.parseExpression();
818
- if (this.current().type === t.TO) {
819
- this.advance();
820
- const o = this.parseExpression();
821
- let c;
822
- this.current().type === t.STEP && (this.advance(), c = this.parseExpression());
823
- const u = this.parseBlock();
824
- return {
825
- type: "for",
826
- variable: e,
827
- from: a,
828
- to: o,
829
- step: c,
830
- body: u
831
- };
832
- } else {
833
- const o = this.parseBlock();
834
- return {
835
- type: "for",
836
- variable: e,
837
- from: { type: "number", value: 0 },
838
- to: { type: "number", value: 0 },
839
- iterableValues: a,
840
- body: o
841
- };
842
- }
843
- }
844
- let s = { type: "number", value: 1 };
845
- this.current().type === t.NUMBER && (s = this.parseExpression()), this.expect(t.TO);
846
- const r = this.parseExpression(), i = this.parseBlock();
847
- return {
848
- type: "for",
849
- variable: e,
850
- from: s,
851
- to: r,
852
- body: i
853
- };
854
- }
855
- parseIf() {
856
- this.advance();
857
- const e = this.parseExpression(), s = this.parseBlock();
858
- let r;
859
- return this.skipNewlines(), this.current().type === t.ELSE && (this.advance(), this.skipNewlines(), this.current().type === t.IF ? r = [this.parseIf()] : r = this.parseBlock()), {
860
- type: "if",
861
- condition: e,
862
- thenBody: s,
863
- elseBody: r
864
- };
865
- }
866
- parseSwitch() {
867
- this.advance();
868
- const e = this.parseExpression();
869
- this.expect(t.LBRACE), this.skipNewlines();
870
- const s = [];
871
- let r;
872
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
873
- if (this.current().type === t.CASE) {
874
- this.advance();
875
- const i = [];
876
- for (i.push(this.parseExpression()); this.current().type !== t.NEWLINE && this.current().type !== t.LBRACE && this.current().type !== t.EOF; )
877
- i.push(this.parseExpression());
878
- this.skipNewlines();
879
- let a;
880
- if (this.current().type === t.LBRACE)
881
- a = this.parseBlock();
882
- else
883
- for (a = []; this.current().type !== t.CASE && this.current().type !== t.ELSE && this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
884
- const o = this.parseNode();
885
- o && a.push(o), this.skipNewlines();
886
- }
887
- s.push({ values: i, body: a });
888
- } else if (this.current().type === t.ELSE)
889
- if (this.advance(), this.skipNewlines(), this.current().type === t.LBRACE)
890
- r = this.parseBlock();
891
- else
892
- for (r = []; this.current().type !== t.CASE && this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
893
- const i = this.parseNode();
894
- i && r.push(i), this.skipNewlines();
895
- }
896
- else
897
- this.skipNewlines(), this.current().type !== t.CASE && this.current().type !== t.ELSE && this.current().type !== t.RBRACE && this.advance();
898
- this.skipNewlines();
899
- }
900
- return this.expect(t.RBRACE), {
901
- type: "switch",
902
- value: e,
903
- cases: s,
904
- defaultCase: r
905
- };
906
- }
907
- parseDefine() {
908
- this.advance();
909
- const s = this.expectIdentifier().value;
910
- if (this.current().type === t.LBRACE) {
911
- this.advance();
912
- const i = [], a = [];
913
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; )
914
- if (this.current().type === t.OPTION) {
915
- this.advance();
916
- const o = this.expectIdentifier().value, c = this.parseVectorOrExpression();
917
- i.push({
918
- type: "option",
919
- name: o,
920
- defaultValue: c
921
- });
922
- } else {
923
- const o = this.parseNode();
924
- o && a.push(o);
925
- }
926
- return this.expect(t.RBRACE), {
927
- type: "define",
928
- name: s,
929
- options: i,
930
- body: a
931
- };
932
- }
933
- const r = this.parseVectorOrExpression();
934
- return {
935
- type: "define",
936
- name: s,
937
- value: r
938
- };
939
- }
940
- parseDetail() {
941
- return this.advance(), {
942
- type: "detail",
943
- value: this.parseExpression()
944
- };
945
- }
946
- parseBackground() {
947
- return this.advance(), {
948
- type: "background",
949
- value: this.parseExpression()
950
- };
951
- }
952
- parseTexture() {
953
- return this.advance(), {
954
- type: "texture",
955
- value: this.parseExpression()
956
- };
957
- }
958
- parseGroup() {
959
- this.advance(), this.expect(t.LBRACE);
960
- const e = this.parseBlockContents();
961
- return this.expect(t.RBRACE), {
962
- type: "group",
963
- children: e
964
- };
965
- }
966
- parseBuilder(e) {
967
- this.advance();
968
- let s = !1;
969
- this.current().type === t.PATH && (s = !0, this.advance()), this.expect(t.LBRACE), this.skipNewlines();
970
- const r = {};
971
- let i;
972
- const a = [];
973
- if (s) {
974
- const o = [];
975
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
976
- const c = this.current();
977
- if (c.type === t.POINT) {
978
- this.advance();
979
- const u = this.parsePathValue();
980
- let p = { type: "number", value: 0 };
981
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (p = this.parsePathValue()), o.push({ type: "point", x: u, y: p });
982
- } else if (c.type === t.CURVE) {
983
- this.advance();
984
- const u = this.parsePathValue(), p = this.parsePathValue();
985
- let E, f;
986
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (E = this.parsePathValue(), (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (f = this.parsePathValue())), o.push({ type: "curve", x: u, y: p, controlX: E, controlY: f });
987
- } else
988
- break;
989
- this.skipNewlines();
990
- }
991
- i = {
992
- type: "path",
993
- commands: o
994
- };
995
- } else
996
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
997
- const o = this.current();
998
- if (o.type === t.PATH && e === "extrude") {
999
- i = this.parsePath(), this.skipNewlines();
1000
- continue;
1001
- }
1002
- if (o.type === t.SIZE || o.type === t.COLOR || o.type === t.OPACITY || o.type === t.POSITION || o.type === t.ROTATION || o.type === t.ORIENTATION) {
1003
- const u = this.parseProperties();
1004
- Object.assign(r, u), this.skipNewlines();
1005
- continue;
1006
- }
1007
- const c = this.parseNode();
1008
- c && a.push(c), this.skipNewlines();
1009
- }
1010
- return this.expect(t.RBRACE), e === "extrude" ? {
1011
- type: "extrude",
1012
- path: i,
1013
- properties: r,
1014
- children: a.length > 0 ? a : void 0
1015
- } : (i && a.unshift(i), {
1016
- type: e,
1017
- properties: r,
1018
- children: a
1019
- });
1020
- }
1021
- parsePathValue() {
1022
- let e = this.parsePathPrimary();
1023
- for (; ; ) {
1024
- const s = this.current();
1025
- if (s.type === t.STAR || s.type === t.DIVIDE || s.type === t.PERCENT || s.type === t.PLUS || s.type === t.MINUS && !this.isStartOfNewValue()) {
1026
- const r = this.tokenTypeToOperator(s.type);
1027
- if (!r) break;
1028
- this.advance();
1029
- const i = this.parsePathPrimary();
1030
- e = {
1031
- type: "binary",
1032
- operator: r,
1033
- left: e,
1034
- right: i
1035
- };
1036
- } else
1037
- break;
1038
- }
1039
- return e;
1040
- }
1041
- isStartOfNewValue() {
1042
- const e = this.current();
1043
- return e.type !== t.MINUS ? !1 : !!e.precedingWhitespace && (this.peek().type === t.NUMBER || this.peek().type === t.IDENTIFIER || this.peek().type === t.LPAREN);
1044
- }
1045
- parsePathPrimary() {
1046
- const e = this.current();
1047
- if (e.type === t.LPAREN) {
1048
- this.advance();
1049
- const s = this.parseExpression();
1050
- return this.expect(t.RPAREN), s;
1051
- }
1052
- if (e.type === t.MINUS)
1053
- return this.advance(), {
1054
- type: "unary",
1055
- operator: "-",
1056
- operand: this.parsePathPrimary()
1057
- };
1058
- if (e.type === t.NUMBER) {
1059
- const s = e.value;
1060
- return this.advance(), {
1061
- type: "number",
1062
- value: s
1063
- };
1064
- }
1065
- if (e.type === t.IDENTIFIER) {
1066
- const s = e.value;
1067
- if (this.advance(), this.current().type === t.LPAREN && !this.current().precedingWhitespace) {
1068
- this.advance();
1069
- const r = [];
1070
- if (this.current().type !== t.RPAREN)
1071
- for (r.push(this.parseExpression()); this.current().type === t.COMMA; )
1072
- this.advance(), r.push(this.parseExpression());
1073
- return this.expect(t.RPAREN), {
1074
- type: "call",
1075
- name: s,
1076
- args: r
1077
- };
1078
- }
1079
- return {
1080
- type: "identifier",
1081
- name: s
1082
- };
1083
- }
1084
- throw new R(
1085
- `Expected path value, got ${e.type}`,
1086
- e.line,
1087
- e.column
1088
- );
1089
- }
1090
- parsePath() {
1091
- this.advance(), this.expect(t.LBRACE), this.skipNewlines();
1092
- const e = [];
1093
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
1094
- const s = this.current();
1095
- switch (s.type) {
1096
- case t.DEFINE: {
1097
- this.parseDefine();
1098
- break;
1099
- }
1100
- case t.DETAIL: {
1101
- this.advance();
1102
- const r = this.parseExpression();
1103
- e.push({ type: "detail", value: r });
1104
- break;
1105
- }
1106
- case t.POINT: {
1107
- this.advance();
1108
- const r = this.parsePathValue();
1109
- let i = { type: "number", value: 0 };
1110
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (i = this.parsePathValue()), e.push({ type: "point", x: r, y: i });
1111
- break;
1112
- }
1113
- case t.CURVE: {
1114
- this.advance();
1115
- const r = this.parsePathValue(), i = this.parsePathValue();
1116
- let a, o;
1117
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (a = this.parsePathValue(), (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (o = this.parsePathValue())), e.push({ type: "curve", x: r, y: i, controlX: a, controlY: o });
1118
- break;
1119
- }
1120
- case t.ROTATE: {
1121
- this.advance();
1122
- const r = this.parseExpression();
1123
- e.push({ type: "rotate", angle: r });
1124
- break;
1125
- }
1126
- case t.TRANSLATE: {
1127
- this.advance();
1128
- const r = this.parsePathValue(), i = this.parsePathValue();
1129
- e.push({ type: "translate", x: r, y: i });
1130
- break;
1131
- }
1132
- case t.FOR: {
1133
- this.advance();
1134
- let r = "_i";
1135
- this.current().type === t.IDENTIFIER && this.peek(1).type === t.IN && (r = this.current().value, this.advance(), this.expect(t.IN));
1136
- const i = this.parseExpression();
1137
- this.expect(t.TO);
1138
- const a = this.parseExpression(), o = this.current().type === t.STEP ? (this.advance(), this.parseExpression()) : { type: "number", value: 1 };
1139
- this.expect(t.LBRACE), this.skipNewlines();
1140
- const c = [];
1141
- for (; this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
1142
- const u = this.current();
1143
- switch (u.type) {
1144
- case t.POINT: {
1145
- this.advance();
1146
- const p = this.parsePathValue();
1147
- let E = { type: "number", value: 0 };
1148
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (E = this.parsePathValue()), c.push({ type: "point", x: p, y: E });
1149
- break;
1150
- }
1151
- case t.CURVE: {
1152
- this.advance();
1153
- const p = this.parsePathValue(), E = this.parsePathValue();
1154
- let f, y;
1155
- (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (f = this.parsePathValue(), (this.current().type === t.NUMBER || this.current().type === t.MINUS || this.current().type === t.IDENTIFIER || this.current().type === t.LPAREN) && (y = this.parsePathValue())), c.push({ type: "curve", x: p, y: E, controlX: f, controlY: y });
1156
- break;
1157
- }
1158
- case t.ROTATE: {
1159
- this.advance();
1160
- const p = this.parseExpression();
1161
- c.push({ type: "rotate", angle: p });
1162
- break;
1163
- }
1164
- case t.TRANSLATE: {
1165
- this.advance();
1166
- const p = this.parsePathValue(), E = this.parsePathValue();
1167
- c.push({ type: "translate", x: p, y: E });
1168
- break;
1169
- }
1170
- default:
1171
- throw new R(
1172
- `Unexpected token in path for loop: ${u.type}`,
1173
- u.line,
1174
- u.column
1175
- );
1176
- }
1177
- this.skipNewlines();
1178
- }
1179
- this.expect(t.RBRACE), e.push({
1180
- type: "for",
1181
- variable: r,
1182
- from: i,
1183
- to: a,
1184
- step: o,
1185
- commands: c
1186
- });
1187
- break;
1188
- }
1189
- default:
1190
- throw new R(
1191
- `Unexpected token in path: ${s.type}`,
1192
- s.line,
1193
- s.column
1194
- );
1195
- }
1196
- this.skipNewlines();
1197
- }
1198
- return this.expect(t.RBRACE), {
1199
- type: "path",
1200
- commands: e
1201
- };
1202
- }
1203
- parseNode() {
1204
- this.skipNewlines();
1205
- const e = this.current(), s = {
1206
- [t.CUBE]: "cube",
1207
- [t.SPHERE]: "sphere",
1208
- [t.CYLINDER]: "cylinder",
1209
- [t.CONE]: "cone",
1210
- [t.TORUS]: "torus",
1211
- [t.CIRCLE]: "circle",
1212
- [t.SQUARE]: "square",
1213
- [t.POLYGON]: "polygon"
1214
- }, r = {
1215
- [t.UNION]: "union",
1216
- [t.DIFFERENCE]: "difference",
1217
- [t.INTERSECTION]: "intersection",
1218
- [t.XOR]: "xor",
1219
- [t.STENCIL]: "stencil"
1220
- }, i = {
1221
- [t.EXTRUDE]: "extrude",
1222
- [t.LOFT]: "loft",
1223
- [t.LATHE]: "lathe",
1224
- [t.FILL]: "fill",
1225
- [t.HULL]: "hull"
1226
- }, a = {
1227
- [t.COLOR]: "color",
1228
- [t.ROTATE]: "rotate",
1229
- [t.TRANSLATE]: "translate",
1230
- [t.SCALE]: "scale",
1231
- [t.POSITION]: "translate",
1232
- // position is an alias for translate
1233
- [t.ORIENTATION]: "orientation"
1234
- // orientation sets absolute rotation (not relative like rotate)
1235
- };
1236
- if (e.type in s)
1237
- return this.parseShape(s[e.type]);
1238
- if (e.type in r)
1239
- return this.parseCSG(r[e.type]);
1240
- if (e.type in i)
1241
- return this.parseBuilder(i[e.type]);
1242
- if (e.type in a)
1243
- return this.advance(), {
1244
- type: a[e.type],
1245
- value: this.parseVectorOrExpression()
1246
- };
1247
- switch (e.type) {
1248
- case t.FOR:
1249
- return this.parseForLoop();
1250
- case t.IF:
1251
- return this.parseIf();
1252
- case t.SWITCH:
1253
- return this.parseSwitch();
1254
- case t.DEFINE:
1255
- return this.parseDefine();
1256
- case t.GROUP:
1257
- return this.parseGroup();
1258
- case t.DETAIL:
1259
- return this.parseDetail();
1260
- case t.BACKGROUND:
1261
- return this.parseBackground();
1262
- case t.TEXTURE:
1263
- return this.parseTexture();
1264
- case t.PATH:
1265
- return this.parsePath();
1266
- case t.RBRACE:
1267
- case t.EOF:
1268
- return null;
1269
- case t.IDENTIFIER: {
1270
- const o = e.value;
1271
- this.advance();
1272
- const c = {};
1273
- if (this.current().type === t.LBRACE) {
1274
- for (this.expect(t.LBRACE), this.skipNewlines(); this.current().type !== t.RBRACE && this.current().type !== t.EOF; ) {
1275
- if (this.current().type === t.POSITION || this.current().type === t.ROTATION || this.current().type === t.SIZE || this.current().type === t.COLOR || this.current().type === t.OPACITY) {
1276
- const u = this.parseProperties();
1277
- Object.assign(c, u);
1278
- } else if (this.current().type === t.IDENTIFIER) {
1279
- const u = this.current().value;
1280
- this.advance();
1281
- const p = this.parseVectorOrExpression();
1282
- c[u] = p;
1283
- } else
1284
- break;
1285
- this.skipNewlines();
1286
- }
1287
- this.expect(t.RBRACE);
1288
- }
1289
- return {
1290
- type: "customShape",
1291
- name: o,
1292
- properties: c
1293
- };
1294
- }
1295
- default:
1296
- throw new R(
1297
- `Unexpected token: ${e.type}`,
1298
- e.line,
1299
- e.column
1300
- );
1301
- }
1302
- }
1303
- parse() {
1304
- const e = [];
1305
- for (; this.current().type !== t.EOF; ) {
1306
- const s = this.parseNode();
1307
- s && e.push(s), this.skipNewlines();
1308
- }
1309
- return e;
1310
- }
1311
- }
1312
- function X(n) {
1313
- try {
1314
- const r = new D(n).tokenize().filter((a) => a.type !== t.NEWLINE);
1315
- return new F(r).parse();
1316
- } catch (e) {
1317
- throw e instanceof R ? e : new R(
1318
- e instanceof Error ? e.message : "Unknown parse error"
1319
- );
1320
- }
1321
- }
1322
- class L {
1323
- constructor() {
1324
- d(this, "scopes", []);
1325
- this.pushScope();
1326
- }
1327
- pushScope() {
1328
- this.scopes.push(/* @__PURE__ */ new Map());
1329
- }
1330
- popScope() {
1331
- this.scopes.length > 1 && this.scopes.pop();
1332
- }
1333
- set(e, s) {
1334
- this.scopes[this.scopes.length - 1].set(e, s);
1335
- }
1336
- get(e) {
1337
- for (let s = this.scopes.length - 1; s >= 0; s--)
1338
- if (this.scopes[s].has(e))
1339
- return this.scopes[s].get(e);
1340
- }
1341
- has(e) {
1342
- return this.get(e) !== void 0;
1343
- }
1344
- }
1345
- const T = {
1346
- // Arithmetic
1347
- round: (n) => Math.round(h(n)),
1348
- floor: (n) => Math.floor(h(n)),
1349
- ceil: (n) => Math.ceil(h(n)),
1350
- abs: (n) => Math.abs(h(n)),
1351
- sign: (n) => Math.sign(h(n)),
1352
- sqrt: (n) => Math.sqrt(h(n)),
1353
- pow: (n, e) => Math.pow(h(n), h(e)),
1354
- min: (...n) => Math.min(...n.map(h)),
1355
- max: (...n) => Math.max(...n.map(h)),
1356
- // Trigonometric (uses radians)
1357
- sin: (n) => Math.sin(h(n)),
1358
- cos: (n) => Math.cos(h(n)),
1359
- tan: (n) => Math.tan(h(n)),
1360
- asin: (n) => Math.asin(h(n)),
1361
- acos: (n) => Math.acos(h(n)),
1362
- atan: (n) => Math.atan(h(n)),
1363
- atan2: (n, e) => Math.atan2(h(n), h(e)),
1364
- // Vector operations
1365
- dot: (n, e) => {
1366
- const s = I(n), r = I(e);
1367
- let i = 0;
1368
- for (let a = 0; a < Math.min(s.length, r.length); a++)
1369
- i += h(s[a]) * h(r[a]);
1370
- return i;
1371
- },
1372
- cross: (n, e) => {
1373
- const s = I(n), r = I(e);
1374
- if (s.length < 3 || r.length < 3)
1375
- throw new Error("cross product requires 3D vectors");
1376
- const i = h(s[0]), a = h(s[1]), o = h(s[2]), c = h(r[0]), u = h(r[1]), p = h(r[2]);
1377
- return [a * p - o * u, o * c - i * p, i * u - a * c];
1378
- },
1379
- length: (n) => {
1380
- const e = I(n);
1381
- let s = 0;
1382
- for (const r of e) {
1383
- const i = h(r);
1384
- s += i * i;
1385
- }
1386
- return Math.sqrt(s);
1387
- },
1388
- normalize: (n) => {
1389
- const e = I(n), s = T.length(n);
1390
- return s === 0 ? e : e.map((r) => h(r) / s);
1391
- },
1392
- sum: (n) => I(n).reduce((s, r) => s + h(r), 0),
1393
- // String functions
1394
- join: (...n) => {
1395
- const e = n.length > 0 && typeof n[n.length - 1] == "string" ? n.pop() : "";
1396
- return n.map(String).join(e);
1397
- },
1398
- trim: (n) => String(n).trim(),
1399
- // Random (for procedural generation)
1400
- rand: () => Math.random()
1401
- };
1402
- function h(n) {
1403
- if (typeof n == "number") return n;
1404
- if (typeof n == "boolean") return n ? 1 : 0;
1405
- if (typeof n == "string") {
1406
- const e = parseFloat(n);
1407
- if (isNaN(e)) throw new Error(`Cannot convert "${n}" to number`);
1408
- return e;
1409
- }
1410
- if (Array.isArray(n) && n.length > 0)
1411
- return h(n[0]);
1412
- throw new Error(`Cannot convert ${typeof n} to number`);
1413
- }
1414
- function I(n) {
1415
- return Array.isArray(n) ? n : [n];
1416
- }
1417
- function b(n) {
1418
- return typeof n == "boolean" ? n : typeof n == "number" ? n !== 0 : typeof n == "string" || Array.isArray(n) ? n.length > 0 : !1;
1419
- }
1420
- class V {
1421
- constructor(e) {
1422
- d(this, "symbols");
1423
- this.symbols = e || new L();
1424
- }
1425
- getSymbols() {
1426
- return this.symbols;
1427
- }
1428
- evaluate(e) {
1429
- if (typeof e == "number" || typeof e == "string" || Array.isArray(e))
1430
- return e;
1431
- switch (e.type) {
1432
- case "number":
1433
- return e.value;
1434
- case "identifier": {
1435
- if (e.name === "rnd")
1436
- return Math.random();
1437
- const s = this.symbols.get(e.name);
1438
- if (s === void 0)
1439
- throw new Error(`Undefined variable: ${e.name}`);
1440
- return s;
1441
- }
1442
- case "binary": {
1443
- const s = this.evaluate(e.left), r = this.evaluate(e.right);
1444
- switch (e.operator) {
1445
- case "+":
1446
- if (Array.isArray(s) && Array.isArray(r)) {
1447
- const i = [...s];
1448
- for (let a = 0; a < i.length && a < r.length; a++)
1449
- i[a] = h(i[a]) + h(r[a]);
1450
- return i;
1451
- }
1452
- return h(s) + h(r);
1453
- case "-":
1454
- if (Array.isArray(s) && Array.isArray(r)) {
1455
- const i = [...s];
1456
- for (let a = 0; a < i.length && a < r.length; a++)
1457
- i[a] = h(i[a]) - h(r[a]);
1458
- return i;
1459
- }
1460
- return h(s) - h(r);
1461
- case "*":
1462
- if (Array.isArray(s) && Array.isArray(r)) {
1463
- const i = Math.min(s.length, r.length), a = [];
1464
- for (let o = 0; o < i; o++)
1465
- a.push(h(s[o]) * h(r[o]));
1466
- return a;
1467
- }
1468
- return Array.isArray(s) ? s.map((i) => h(i) * h(r)) : Array.isArray(r) ? r.map((i) => h(s) * h(i)) : h(s) * h(r);
1469
- case "/":
1470
- if (Array.isArray(s) && Array.isArray(r)) {
1471
- const i = Math.min(s.length, r.length), a = [];
1472
- for (let o = 0; o < i; o++)
1473
- a.push(h(s[o]) / h(r[o]));
1474
- return a;
1475
- }
1476
- return Array.isArray(s) ? s.map((i) => h(i) / h(r)) : h(s) / h(r);
1477
- case "%":
1478
- return h(s) % h(r);
1479
- case "=":
1480
- if (Array.isArray(s) && Array.isArray(r)) {
1481
- if (s.length !== r.length) return !1;
1482
- for (let i = 0; i < s.length; i++)
1483
- if (h(s[i]) !== h(r[i])) return !1;
1484
- return !0;
1485
- }
1486
- return s === r;
1487
- case "<>":
1488
- if (Array.isArray(s) && Array.isArray(r)) {
1489
- if (s.length !== r.length) return !0;
1490
- for (let i = 0; i < s.length; i++)
1491
- if (h(s[i]) !== h(r[i])) return !0;
1492
- return !1;
1493
- }
1494
- return s !== r;
1495
- case "<":
1496
- return h(s) < h(r);
1497
- case "<=":
1498
- return h(s) <= h(r);
1499
- case ">":
1500
- return h(s) > h(r);
1501
- case ">=":
1502
- return h(s) >= h(r);
1503
- case "and":
1504
- return b(s) && b(r);
1505
- case "or":
1506
- return b(s) || b(r);
1507
- default:
1508
- throw new Error(`Unknown binary operator: ${e.operator}`);
1509
- }
1510
- }
1511
- case "unary": {
1512
- const s = this.evaluate(e.operand);
1513
- switch (e.operator) {
1514
- case "-":
1515
- return Array.isArray(s) ? s.map((r) => -h(r)) : -h(s);
1516
- case "not":
1517
- return !b(s);
1518
- default:
1519
- throw new Error(`Unknown unary operator: ${e.operator}`);
1520
- }
1521
- }
1522
- case "call": {
1523
- const s = T[e.name.toLowerCase()];
1524
- if (!s)
1525
- throw new Error(`Unknown function: ${e.name}`);
1526
- const r = e.args.map((i) => this.evaluate(i));
1527
- return s(...r);
1528
- }
1529
- case "tuple":
1530
- return e.elements.map((s) => this.evaluate(s));
1531
- case "member":
1532
- case "subscript":
1533
- throw new Error(
1534
- `Member access and subscripting not yet implemented: ${e.type}`
1535
- );
1536
- default:
1537
- throw new Error(
1538
- `Unknown expression type: ${e.type}`
1539
- );
1540
- }
1541
- }
1542
- evaluateToNumber(e) {
1543
- const s = this.evaluate(e);
1544
- return h(s);
1545
- }
1546
- evaluateToBoolean(e) {
1547
- const s = this.evaluate(e);
1548
- return b(s);
1549
- }
1550
- evaluateToVector3(e) {
1551
- if (Array.isArray(e) && typeof e[0] == "number")
1552
- return e;
1553
- const s = this.evaluate(e);
1554
- if (Array.isArray(s)) {
1555
- const i = s.length > 0 ? h(s[0]) : 0, a = s.length > 1 ? h(s[1]) : 0, o = s.length > 2 ? h(s[2]) : 0;
1556
- return [i, a, o];
1557
- }
1558
- const r = h(s);
1559
- return [r, r, r];
1560
- }
1561
- evaluateToColor(e) {
1562
- if (Array.isArray(e) && typeof e[0] == "number")
1563
- return e;
1564
- const s = this.evaluate(e);
1565
- if (Array.isArray(s)) {
1566
- const i = s.length > 0 ? h(s[0]) : 0, a = s.length > 1 ? h(s[1]) : 0, o = s.length > 2 ? h(s[2]) : 0;
1567
- return [i, a, o];
1568
- }
1569
- const r = h(s);
1570
- return [r, r, r];
1571
- }
1572
- }
1573
- class G {
1574
- constructor(e = {}) {
1575
- d(this, "options");
1576
- d(this, "evaluator");
1577
- d(this, "symbols");
1578
- d(this, "detailLevel", 32);
1579
- // Default detail level for curved shapes
1580
- // Transform state stack for relative transforms
1581
- d(this, "transformStack", []);
1582
- this.options = e, this.symbols = new L(), this.evaluator = new V(this.symbols), this.pushTransform();
1583
- }
1584
- convert(e) {
1585
- const s = new l.Group();
1586
- for (const r of e) {
1587
- const i = this.convertNode(r);
1588
- i && s.add(i);
1589
- }
1590
- return s;
1591
- }
1592
- convertNode(e) {
1593
- switch (e.type) {
1594
- case "shape":
1595
- return this.convertShape(e);
1596
- case "csg":
1597
- return this.convertCSG(e);
1598
- case "block":
1599
- return this.convertBlock(e);
1600
- case "for":
1601
- return this.convertForLoop(e);
1602
- case "if":
1603
- return this.convertIf(e);
1604
- case "switch":
1605
- return this.convertSwitch(e);
1606
- case "define":
1607
- return this.handleDefine(e), null;
1608
- // Define doesn't create geometry
1609
- case "extrude":
1610
- return this.convertExtrude(e);
1611
- case "loft":
1612
- return this.convertLoft(e);
1613
- case "lathe":
1614
- return this.convertLathe(e);
1615
- case "fill":
1616
- return this.convertFill(e);
1617
- case "hull":
1618
- return this.convertHull(e);
1619
- case "group":
1620
- return this.convertBlock(e);
1621
- case "detail":
1622
- return this.handleDetail(e), null;
1623
- // Detail doesn't create geometry
1624
- case "color":
1625
- return this.handleColorCommand(e), null;
1626
- case "rotate":
1627
- return this.handleRotateCommand(e), null;
1628
- case "orientation":
1629
- return this.handleOrientationCommand(e), null;
1630
- case "translate":
1631
- return this.handleTranslateCommand(e), null;
1632
- case "scale":
1633
- return this.handleScaleCommand(e), null;
1634
- case "customShape":
1635
- return this.convertCustomShape(e);
1636
- default:
1637
- return console.warn(`Unknown node type: ${e.type}`), null;
1638
- }
1639
- }
1640
- convertBlock(e) {
1641
- const s = new l.Group();
1642
- this.symbols.pushScope(), this.pushTransform();
1643
- for (const r of e.children) {
1644
- const i = this.convertNode(r);
1645
- i && s.add(i);
1646
- }
1647
- return this.popTransform(), this.symbols.popScope(), s;
1648
- }
1649
- convertShape(e) {
1650
- const s = this.createGeometry(e), r = this.createMaterial(e), i = new l.Mesh(s, r);
1651
- return this.applyExplicitTransforms(i, e.properties), this.applyCurrentTransform(i), i;
1652
- }
1653
- createGeometry(e) {
1654
- let s = [1, 1, 1];
1655
- switch (e.properties.size && (s = this.evaluateVector3(e.properties.size)), s[1] === 0 && s[2] === 0 && s[0] !== 0 && (s = [s[0], s[0], s[0]]), e.primitive) {
1656
- case "cube":
1657
- return new l.BoxGeometry(s[0], s[1], s[2]);
1658
- case "sphere":
1659
- return new l.SphereGeometry(
1660
- s[0],
1661
- this.detailLevel,
1662
- this.detailLevel
1663
- );
1664
- case "cylinder": {
1665
- const r = e.properties.radiusTop ? this.evaluateNumber(e.properties.radiusTop) : s[0], i = e.properties.radiusBottom ? this.evaluateNumber(e.properties.radiusBottom) : s[0], a = e.properties.height ? this.evaluateNumber(e.properties.height) : s[1];
1666
- return new l.CylinderGeometry(
1667
- r,
1668
- i,
1669
- a,
1670
- this.detailLevel
1671
- );
1672
- }
1673
- case "cone": {
1674
- const r = s[0], i = e.properties.height ? this.evaluateNumber(e.properties.height) : s[1];
1675
- return new l.ConeGeometry(r, i, this.detailLevel);
1676
- }
1677
- case "torus": {
1678
- const r = e.properties.outerRadius ? this.evaluateNumber(e.properties.outerRadius) : s[0], i = e.properties.innerRadius ? this.evaluateNumber(e.properties.innerRadius) : 0.4;
1679
- return new l.TorusGeometry(
1680
- r,
1681
- i,
1682
- Math.max(3, Math.floor(this.detailLevel / 2)),
1683
- this.detailLevel
1684
- );
1685
- }
1686
- case "circle": {
1687
- const r = s[0] || 1;
1688
- return new l.CircleGeometry(r, this.detailLevel);
1689
- }
1690
- case "square": {
1691
- const r = s[0] || 1;
1692
- return new l.PlaneGeometry(r, r);
1693
- }
1694
- case "polygon": {
1695
- const r = s[0] || 1, i = 6;
1696
- return new l.CircleGeometry(r, i);
1697
- }
1698
- default:
1699
- return console.warn(`Unknown primitive: ${e.primitive}`), new l.BoxGeometry(1, 1, 1);
1700
- }
1701
- }
1702
- createMaterial(e) {
1703
- const s = e.properties.color ? this.evaluateColor(e.properties.color) : [0.8, 0.8, 0.8], r = new l.Color(s[0], s[1], s[2]), i = e.properties.opacity ? this.evaluateNumber(e.properties.opacity) : 1, a = i < 1;
1704
- return new l.MeshStandardMaterial({
1705
- color: r,
1706
- opacity: i,
1707
- transparent: a,
1708
- wireframe: this.options.wireframe ?? !1
1709
- });
1710
- }
1711
- convertCSG(e) {
1712
- if (e.children.length === 0)
1713
- return new l.Group();
1714
- const s = this.currentTransform().matrix.clone();
1715
- try {
1716
- const r = new M();
1717
- this.symbols.pushScope(), this.pushTransform();
1718
- const i = this.currentTransform();
1719
- i.matrix.identity(), i.color = void 0;
1720
- const a = [];
1721
- for (const u of e.children) {
1722
- const p = this.convertNode(u);
1723
- if (p instanceof l.Mesh) {
1724
- const E = p.clone();
1725
- E.updateMatrixWorld(!0), a.push(E);
1726
- } else p instanceof l.Group && p.traverse((E) => {
1727
- if (E instanceof l.Mesh) {
1728
- const f = E.clone();
1729
- f.updateMatrixWorld(!0), a.push(f);
1730
- }
1731
- });
1732
- }
1733
- if (this.popTransform(), this.symbols.popScope(), a.length === 0)
1734
- return new l.Group();
1735
- const o = a.map((u) => {
1736
- const p = new B(u.geometry, u.material);
1737
- return p.position.copy(u.position), p.rotation.copy(u.rotation), p.scale.copy(u.scale), p.updateMatrixWorld(!0), p;
1738
- });
1739
- let c = o[0];
1740
- for (let u = 1; u < o.length; u++) {
1741
- const p = o[u];
1742
- switch (e.operation) {
1743
- case "union":
1744
- c = r.evaluate(c, p, w);
1745
- break;
1746
- case "difference":
1747
- c = r.evaluate(c, p, C);
1748
- break;
1749
- case "intersection":
1750
- c = r.evaluate(c, p, g);
1751
- break;
1752
- case "xor": {
1753
- const E = r.evaluate(
1754
- c.clone(),
1755
- p.clone(),
1756
- C
1757
- ), f = r.evaluate(
1758
- p.clone(),
1759
- c.clone(),
1760
- C
1761
- );
1762
- c = r.evaluate(E, f, w);
1763
- break;
1764
- }
1765
- case "stencil":
1766
- c = r.evaluate(c, p, g);
1767
- break;
1768
- }
1769
- }
1770
- return c.material || (c.material = o[0].material), c.applyMatrix4(s), c.updateMatrixWorld(!0), c;
1771
- } catch {
1772
- const r = new l.Group();
1773
- this.symbols.pushScope();
1774
- for (const i of e.children) {
1775
- const a = this.convertNode(i);
1776
- a && r.add(a);
1777
- }
1778
- return this.symbols.popScope(), r.applyMatrix4(s), r.updateMatrixWorld(!0), r;
1779
- }
1780
- }
1781
- convertForLoop(e) {
1782
- const s = new l.Group();
1783
- if (this.symbols.pushScope(), this.pushTransform(), e.iterableValues) {
1784
- const r = this.evaluator.evaluate(e.iterableValues), i = Array.isArray(r) ? r : [r];
1785
- for (let a = 0; a < i.length; a++) {
1786
- this.symbols.set(e.variable, i[a]);
1787
- for (const o of e.body) {
1788
- const c = this.convertNode(o);
1789
- c && s.add(c);
1790
- }
1791
- }
1792
- } else {
1793
- const r = this.evaluateNumber(e.from), i = this.evaluateNumber(e.to), a = e.step ? this.evaluateNumber(e.step) : 1, o = [];
1794
- if (a > 0)
1795
- for (let c = r; c <= i; c += a)
1796
- o.push(c);
1797
- else if (a < 0)
1798
- for (let c = r; c >= i; c += a)
1799
- o.push(c);
1800
- for (let c = 0; c < o.length; c++) {
1801
- const u = o[c];
1802
- this.symbols.set(e.variable, u);
1803
- for (const p of e.body) {
1804
- const E = this.convertNode(p);
1805
- E && s.add(E);
1806
- }
1807
- }
1808
- }
1809
- return this.popTransform(), this.symbols.popScope(), s;
1810
- }
1811
- convertIf(e) {
1812
- const s = new l.Group(), r = this.evaluator.evaluateToBoolean(e.condition);
1813
- if (this.symbols.pushScope(), this.pushTransform(), r)
1814
- for (const i of e.thenBody) {
1815
- const a = this.convertNode(i);
1816
- a && s.add(a);
1817
- }
1818
- else if (e.elseBody)
1819
- for (const i of e.elseBody) {
1820
- const a = this.convertNode(i);
1821
- a && s.add(a);
1822
- }
1823
- return this.popTransform(), this.symbols.popScope(), s;
1824
- }
1825
- convertSwitch(e) {
1826
- const s = new l.Group(), r = this.evaluator.evaluate(e.value);
1827
- this.symbols.pushScope(), this.pushTransform();
1828
- let i = !1;
1829
- for (const a of e.cases) {
1830
- for (const o of a.values) {
1831
- const c = this.evaluator.evaluate(o);
1832
- if (this.valuesEqual(r, c)) {
1833
- for (const u of a.body) {
1834
- const p = this.convertNode(u);
1835
- p && s.add(p);
1836
- }
1837
- i = !0;
1838
- break;
1839
- }
1840
- }
1841
- if (i) break;
1842
- }
1843
- if (!i && e.defaultCase)
1844
- for (const a of e.defaultCase) {
1845
- const o = this.convertNode(a);
1846
- o && s.add(o);
1847
- }
1848
- return this.popTransform(), this.symbols.popScope(), s;
1849
- }
1850
- handleDefine(e) {
1851
- if (e.value !== void 0) {
1852
- const s = this.evaluator.evaluate(e.value);
1853
- this.symbols.set(e.name, s);
1854
- } else (e.body !== void 0 || e.options !== void 0) && this.symbols.set(e.name, e);
1855
- }
1856
- convertCustomShape(e) {
1857
- const s = this.symbols.get(e.name);
1858
- if (!s || typeof s != "object" || !("type" in s))
1859
- return console.warn(`Custom shape '${e.name}' not found`), null;
1860
- const r = s;
1861
- if (!r.body)
1862
- return console.warn(`Custom shape '${e.name}' has no body`), null;
1863
- if (this.symbols.pushScope(), this.pushTransform(), r.options)
1864
- for (const a of r.options) {
1865
- const o = this.evaluator.evaluate(a.defaultValue);
1866
- this.symbols.set(a.name, o);
1867
- }
1868
- for (const [a, o] of Object.entries(e.properties)) {
1869
- const c = this.evaluator.evaluate(o);
1870
- this.symbols.set(a, c);
1871
- }
1872
- const i = new l.Group();
1873
- for (const a of r.body) {
1874
- const o = this.convertNode(a);
1875
- o && i.add(o);
1876
- }
1877
- return this.popTransform(), this.symbols.popScope(), i;
1878
- }
1879
- pushTransform() {
1880
- var s;
1881
- const e = this.currentTransform();
1882
- this.transformStack.push({
1883
- matrix: e.matrix.clone(),
1884
- color: (s = e.color) == null ? void 0 : s.clone()
1885
- });
1886
- }
1887
- popTransform() {
1888
- this.transformStack.length > 1 && this.transformStack.pop();
1889
- }
1890
- currentTransform() {
1891
- return this.transformStack.length === 0 ? {
1892
- matrix: new l.Matrix4(),
1893
- color: void 0
1894
- } : this.transformStack[this.transformStack.length - 1];
1895
- }
1896
- applyCurrentTransform(e) {
1897
- const s = this.currentTransform();
1898
- e.applyMatrix4(s.matrix);
1899
- }
1900
- applyExplicitTransforms(e, s) {
1901
- if (s.position) {
1902
- const r = this.evaluateVector3(s.position);
1903
- e.position.set(...r);
1904
- }
1905
- if (s.rotation) {
1906
- const r = this.evaluateVector3(s.rotation);
1907
- e.rotation.set(...r);
1908
- }
1909
- if (s.orientation) {
1910
- const r = this.evaluateVector3(s.orientation);
1911
- e.rotation.set(...r);
1912
- }
1913
- }
1914
- handleDetail(e) {
1915
- this.detailLevel = this.evaluateNumber(e.value), this.symbols.set("detail", this.detailLevel);
1916
- }
1917
- handleColorCommand(e) {
1918
- const s = this.evaluateVector3OrColor(e.value);
1919
- this.currentTransform().color = new l.Color(
1920
- s[0],
1921
- s[1],
1922
- s[2]
1923
- );
1924
- }
1925
- handleRotateCommand(e) {
1926
- const s = this.evaluateVector3(e.value), r = this.currentTransform(), i = new l.Matrix4(), a = new l.Euler(
1927
- s[0] * Math.PI * 2,
1928
- s[1] * Math.PI * 2,
1929
- s[2] * Math.PI * 2,
1930
- "XYZ"
1931
- );
1932
- i.makeRotationFromEuler(a), r.matrix.multiply(i);
1933
- }
1934
- handleOrientationCommand(e) {
1935
- const s = this.evaluateVector3(e.value), r = this.currentTransform(), i = new l.Vector3(), a = new l.Vector3();
1936
- r.matrix.decompose(i, new l.Quaternion(), a);
1937
- const o = new l.Euler(
1938
- s[0] * Math.PI * 2,
1939
- s[1] * Math.PI * 2,
1940
- s[2] * Math.PI * 2,
1941
- "XYZ"
1942
- );
1943
- r.matrix.compose(
1944
- i,
1945
- new l.Quaternion().setFromEuler(o),
1946
- a
1947
- );
1948
- }
1949
- handleTranslateCommand(e) {
1950
- const s = this.currentTransform(), [r, i, a] = this.evaluateTranslateVector(e.value), o = new l.Matrix4().makeTranslation(r, i, a);
1951
- s.matrix.multiply(o);
1952
- }
1953
- handleScaleCommand(e) {
1954
- const s = this.evaluateVector3(e.value), r = this.currentTransform(), i = new l.Matrix4().makeScale(
1955
- s[0],
1956
- s[1],
1957
- s[2]
1958
- );
1959
- r.matrix.multiply(i);
1960
- }
1961
- convertExtrude(e) {
1962
- const s = e.path ? this.buildPath(e.path) : new l.Shape([new l.Vector2(0, 0)]), i = (e.properties.size ? this.evaluateVector3(e.properties.size) : [1, 1, 1])[2] || 1, a = new l.ExtrudeGeometry(s, {
1963
- depth: i,
1964
- bevelEnabled: !1,
1965
- curveSegments: Math.max(1, Math.floor(this.detailLevel / 4))
1966
- }), o = this.createMaterial(e), c = new l.Mesh(a, o);
1967
- return this.applyExplicitTransforms(c, e.properties), this.applyCurrentTransform(c), c;
1968
- }
1969
- buildPath(e) {
1970
- const s = new l.Shape();
1971
- let r = 0, i = 0, a = 0;
1972
- const o = (c) => {
1973
- switch (c.type) {
1974
- case "point": {
1975
- const u = this.evaluateNumber(c.x), p = this.evaluateNumber(c.y), E = Math.cos(a), f = Math.sin(a), y = u * E - p * f, v = u * f + p * E;
1976
- r += y, i += v, s.curves.length === 0 ? s.moveTo(r, i) : s.lineTo(r, i);
1977
- break;
1978
- }
1979
- case "curve": {
1980
- const u = this.evaluateNumber(c.x), p = this.evaluateNumber(c.y), E = Math.cos(a), f = Math.sin(a), y = u * E - p * f, v = u * f + p * E;
1981
- if (r += y, i += v, c.controlX !== void 0 && c.controlY !== void 0) {
1982
- const N = this.evaluateNumber(c.controlX), A = this.evaluateNumber(c.controlY), m = N * E - A * f, S = N * f + A * E;
1983
- s.quadraticCurveTo(
1984
- r + m,
1985
- i + S,
1986
- r,
1987
- i
1988
- );
1989
- } else
1990
- s.lineTo(r, i);
1991
- break;
1992
- }
1993
- case "rotate": {
1994
- const u = this.evaluateNumber(c.angle);
1995
- a += u * Math.PI * 2;
1996
- break;
1997
- }
1998
- case "translate": {
1999
- const u = this.evaluateNumber(c.x), p = this.evaluateNumber(c.y);
2000
- r += u, i += p;
2001
- break;
2002
- }
2003
- case "for": {
2004
- this.symbols.pushScope();
2005
- const u = this.evaluateNumber(c.from), p = this.evaluateNumber(c.to), E = c.step ? this.evaluateNumber(c.step) : 1, f = [];
2006
- if (E > 0)
2007
- for (let y = u; y <= p; y += E)
2008
- f.push(y);
2009
- else if (E < 0)
2010
- for (let y = u; y >= p; y += E)
2011
- f.push(y);
2012
- for (const y of f) {
2013
- this.symbols.set(c.variable, y);
2014
- for (const v of c.commands)
2015
- o(v);
2016
- }
2017
- this.symbols.popScope();
2018
- break;
2019
- }
2020
- }
2021
- };
2022
- for (const c of e.commands)
2023
- o(c);
2024
- return s;
2025
- }
2026
- convertLathe(e) {
2027
- this.symbols.pushScope(), this.pushTransform();
2028
- let s = null;
2029
- for (const f of e.children)
2030
- if (f.type === "path") {
2031
- s = f;
2032
- break;
2033
- }
2034
- if (!s)
2035
- return console.warn("Lathe requires a path child"), this.popTransform(), this.symbols.popScope(), new l.Group();
2036
- const r = [];
2037
- let i = 0, a = 0, o = 0;
2038
- const c = (f) => {
2039
- switch (f.type) {
2040
- case "point":
2041
- case "curve": {
2042
- const y = this.evaluateNumber(f.x), v = this.evaluateNumber(f.y), N = Math.cos(o), A = Math.sin(o), m = y * N - v * A, S = y * A + v * N;
2043
- i += m, a += S, r.push(new l.Vector2(i, a));
2044
- break;
2045
- }
2046
- case "rotate": {
2047
- const y = this.evaluateNumber(f.angle);
2048
- o += y * Math.PI * 2;
2049
- break;
2050
- }
2051
- case "translate": {
2052
- const y = this.evaluateNumber(f.x), v = this.evaluateNumber(f.y);
2053
- i += y, a += v;
2054
- break;
2055
- }
2056
- case "for": {
2057
- this.symbols.pushScope();
2058
- const y = this.evaluateNumber(f.from), v = this.evaluateNumber(f.to), N = f.step ? this.evaluateNumber(f.step) : 1, A = [];
2059
- if (N > 0)
2060
- for (let m = y; m <= v; m += N)
2061
- A.push(m);
2062
- else if (N < 0)
2063
- for (let m = y; m >= v; m += N)
2064
- A.push(m);
2065
- for (const m of A) {
2066
- this.symbols.set(f.variable, m);
2067
- for (const S of f.commands)
2068
- c(S);
2069
- }
2070
- this.symbols.popScope();
2071
- break;
2072
- }
2073
- }
2074
- };
2075
- for (const f of s.commands)
2076
- c(f);
2077
- if (r.length < 2)
2078
- return console.warn("Lathe path must have at least 2 points"), this.popTransform(), this.symbols.popScope(), new l.Group();
2079
- const u = new l.LatheGeometry(
2080
- r,
2081
- this.detailLevel
2082
- // Number of segments around the axis
2083
- ), p = this.createMaterial(e), E = new l.Mesh(u, p);
2084
- return this.applyExplicitTransforms(E, e.properties), this.applyCurrentTransform(E), this.popTransform(), this.symbols.popScope(), E;
2085
- }
2086
- convertGroupBuilder(e) {
2087
- this.symbols.pushScope(), this.pushTransform();
2088
- const s = new l.Group();
2089
- for (const r of e.children) {
2090
- const i = this.convertNode(r);
2091
- i && s.add(i);
2092
- }
2093
- return this.applyExplicitTransforms(s, e.properties), this.applyCurrentTransform(s), this.popTransform(), this.symbols.popScope(), s;
2094
- }
2095
- convertLoft(e) {
2096
- return this.convertGroupBuilder(e);
2097
- }
2098
- convertFill(e) {
2099
- this.symbols.pushScope(), this.pushTransform();
2100
- let s = null;
2101
- for (const c of e.children)
2102
- if (c.type === "path") {
2103
- s = c;
2104
- break;
2105
- }
2106
- if (!s)
2107
- return console.warn("Fill requires a path child"), this.popTransform(), this.symbols.popScope(), new l.Group();
2108
- const r = this.buildPath(s), i = new l.ShapeGeometry(r), a = this.createMaterial(e), o = new l.Mesh(i, a);
2109
- return this.applyExplicitTransforms(o, e.properties), this.applyCurrentTransform(o), this.popTransform(), this.symbols.popScope(), o;
2110
- }
2111
- convertHull(e) {
2112
- return this.convertGroupBuilder(e);
2113
- }
2114
- // Helper methods
2115
- evaluateNumber(e) {
2116
- return e === void 0 ? 0 : typeof e == "number" ? e : this.evaluator.evaluateToNumber(e);
2117
- }
2118
- evaluateVector3(e) {
2119
- return e === void 0 ? [0, 0, 0] : Array.isArray(e) && typeof e[0] == "number" ? e : this.evaluator.evaluateToVector3(e);
2120
- }
2121
- evaluateTranslateVector(e) {
2122
- const s = this.evaluator.evaluate(e);
2123
- if (typeof s == "number")
2124
- return [s, 0, 0];
2125
- if (Array.isArray(s)) {
2126
- const r = s.length > 0 && typeof s[0] == "number" ? s[0] : 0, i = s.length > 1 && typeof s[1] == "number" ? s[1] : 0, a = s.length > 2 && typeof s[2] == "number" ? s[2] : 0;
2127
- return [r, i, a];
2128
- }
2129
- return [0, 0, 0];
2130
- }
2131
- evaluateColor(e) {
2132
- return e === void 0 ? [0.8, 0.8, 0.8] : Array.isArray(e) && typeof e[0] == "number" ? e : this.evaluator.evaluateToColor(e);
2133
- }
2134
- evaluateVector3OrColor(e) {
2135
- const s = this.evaluator.evaluate(e), r = (i) => typeof i == "number" ? i : typeof i == "boolean" ? i ? 1 : 0 : typeof i == "string" ? parseFloat(i) || 0 : Array.isArray(i) && i.length > 0 ? r(i[0]) : 0;
2136
- if (typeof s == "number")
2137
- return [s, s, s];
2138
- if (Array.isArray(s)) {
2139
- if (s.length === 1)
2140
- return [r(s[0]), r(s[0]), r(s[0])];
2141
- if (s.length === 2)
2142
- return [r(s[0]), r(s[1]), 0];
2143
- if (s.length >= 3)
2144
- return [r(s[0]), r(s[1]), r(s[2])];
2145
- }
2146
- return [0.8, 0.8, 0.8];
2147
- }
2148
- valuesEqual(e, s) {
2149
- if (typeof e != typeof s) return !1;
2150
- if (Array.isArray(e) && Array.isArray(s)) {
2151
- if (e.length !== s.length) return !1;
2152
- for (let r = 0; r < e.length; r++)
2153
- if (!this.valuesEqual(e[r], s[r])) return !1;
2154
- return !0;
2155
- }
2156
- return e === s;
2157
- }
2158
- }
2159
- function $(n, e = {}) {
2160
- return new G(e).convert(n);
2161
- }
2162
- export {
2163
- U as T,
2164
- k as a,
2165
- O as b,
2166
- X as c,
2167
- $ as d,
2168
- H as e,
2169
- Y as p,
2170
- Q as s
2171
- };