@mulmoclaude/shapescript-plugin 1.4.0 → 2.3.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.
Files changed (52) hide show
  1. package/README.md +165 -28
  2. package/dist/core/definition.d.ts.map +1 -1
  3. package/dist/core/index.d.ts +2 -1
  4. package/dist/core/index.d.ts.map +1 -1
  5. package/dist/core/plugin.d.ts.map +1 -1
  6. package/dist/{core-bcFgqR_m.cjs → core-BBgBeYYe.cjs} +1 -1
  7. package/dist/{core-CpVzK-0i.js → core-yB1Eiacr.js} +2 -2
  8. package/dist/core.cjs +1 -1
  9. package/dist/core.js +4 -4
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.js +4 -4
  12. package/dist/lang/de.d.ts.map +1 -1
  13. package/dist/lang/en.d.ts.map +1 -1
  14. package/dist/lang/es.d.ts.map +1 -1
  15. package/dist/lang/fr.d.ts.map +1 -1
  16. package/dist/lang/ja.d.ts.map +1 -1
  17. package/dist/lang/ko.d.ts.map +1 -1
  18. package/dist/lang/messages.d.ts +4 -0
  19. package/dist/lang/messages.d.ts.map +1 -1
  20. package/dist/lang/ptBR.d.ts.map +1 -1
  21. package/dist/lang/zh.d.ts.map +1 -1
  22. package/dist/render/page.d.ts.map +1 -1
  23. package/dist/render.cjs +8 -4
  24. package/dist/render.js +14 -10
  25. package/dist/{samples-DPOGWslc.js → samples-CT-c9o1S.js} +281 -276
  26. package/dist/samples-D2_jOmoh.cjs +319 -0
  27. package/dist/shapescript/builders.d.ts +12 -2
  28. package/dist/shapescript/builders.d.ts.map +1 -1
  29. package/dist/shapescript/evaluator.d.ts +103 -6
  30. package/dist/shapescript/evaluator.d.ts.map +1 -1
  31. package/dist/shapescript/meshValues.d.ts +54 -0
  32. package/dist/shapescript/meshValues.d.ts.map +1 -0
  33. package/dist/shapescript/minkowski.d.ts +37 -0
  34. package/dist/shapescript/minkowski.d.ts.map +1 -0
  35. package/dist/shapescript/parser.d.ts +84 -2
  36. package/dist/shapescript/parser.d.ts.map +1 -1
  37. package/dist/shapescript/toThreeJS.d.ts +186 -10
  38. package/dist/shapescript/toThreeJS.d.ts.map +1 -1
  39. package/dist/shapescript/types.d.ts +166 -20
  40. package/dist/shapescript/types.d.ts.map +1 -1
  41. package/dist/style.css +1 -1
  42. package/dist/{toThreeJS-BX_aeGdA.js → toThreeJS-CKjSbEnA.js} +5887 -3872
  43. package/dist/toThreeJS-Cs0UJm82.cjs +10 -0
  44. package/dist/vue/Preview.vue.d.ts.map +1 -1
  45. package/dist/vue/View.vue.d.ts.map +1 -1
  46. package/dist/vue/index.d.ts +1 -1
  47. package/dist/vue/index.d.ts.map +1 -1
  48. package/dist/vue.cjs +57 -28
  49. package/dist/vue.js +1553 -1495
  50. package/package.json +1 -1
  51. package/dist/samples-DZNAeuSZ.cjs +0 -210
  52. package/dist/toThreeJS-XGDoVISb.cjs +0 -10
package/README.md CHANGED
@@ -60,16 +60,28 @@ USDZ units are metres, so `size 1` is one metre in AR.
60
60
 
61
61
  ## ShapeScript language
62
62
 
63
- - **Primitives**: `cube`, `sphere`, `cylinder`, `cone`, `torus`, `circle`, `square`, `polygon`
64
- - **Properties**: `position X Y Z`, `rotation X Y Z`, `size X Y Z`, `color R G B` (0–1), `opacity`
63
+ - **Primitives**: `cube`, `sphere`, `icosphere`, `cylinder`, `cone`, `torus`, `circle`, `square`,
64
+ `roundrect`, `polygon`
65
+ - **Properties**: `position X Y Z`, `orientation ROLL YAW PITCH` (alias `rotation`), `size X Y Z`,
66
+ `detail`, `smoothing`, `name`
67
+ - **Materials** (as properties or scoped commands): `color`, `opacity`, `metallicity`, `roughness`,
68
+ `glow`, `material NAME`; `texture` is accepted with a warning
65
69
  - **CSG**: `union`, `difference`, `intersection`, `xor`, `stencil`
66
70
  - **Builders**: `extrude`, `loft`, `lathe`, `fill`, `hull`
67
- - **Variables & expressions**: `define`, arithmetic / comparison / boolean operators, parentheses
68
- - **Control flow**: `for … in … to … step`, `if` / `else`, `switch` / `case`
71
+ - **Variables & expressions**: `define`, arithmetic / comparison / boolean operators, `in`, ranges,
72
+ parentheses, custom functions
73
+ - **Control flow**: `for … in …`, `if` / `else`, `switch` / `case`
69
74
  - **Built-ins**: `round floor ceil abs sign sqrt pow min max`, `sin cos tan asin acos atan atan2`
70
- (radians), `dot cross length normalize sum`
75
+ (radians), `dot cross length normalize sum`, `rgb hsb`, `join split trim`, `rnd`
76
+ - **Commands**: `detail N`, `seed N`, `smoothing N`, `background`, `print`, `assert`, and the relative
77
+ `rotate` / `translate` / `scale`; `camera` / `light` blocks are skipped with a warning
71
78
 
72
- A function call takes **no space** before its parenthesis: `sin(x)` is a call, `sin (x)` is not.
79
+ A call is either C-like, with **no space** before its parenthesis (`sin(x)`; `sin (x)` is not a
80
+ call), or bare, as upstream: `max 0 (j - 1)`, `sqrt 9`, `sin pi / 2` — the function takes every
81
+ value after it, so parenthesise it inside a larger expression: `(sqrt 9) + (sqrt 16)`. Arguments are
82
+ a value list; commas (`max(0, j - 1)`) also work here but not in the upstream app. This parser also
83
+ accepts several statements on one line (`define a 1 define b 2`); upstream requires one per line, so
84
+ portable scripts keep to that.
73
85
 
74
86
  ## Storage
75
87
 
@@ -125,48 +137,173 @@ hull {
125
137
  }
126
138
  extrude { polygon { sides 5 } }
127
139
  fill { square }
128
- lathe path { point 1 0 curve 0 2 1 -1 }
140
+ lathe path {
141
+ point 0 0
142
+ point 1 0
143
+ curve 1.5 1
144
+ point 1 2
145
+ point 0 2
146
+ }
147
+
148
+ // Paths: absolute points, Bézier control points, a frame moved by rotate/translate/scale.
149
+ extrude path {
150
+ point 0 0
151
+ point 1 0
152
+ point 1 1
153
+ point 0 1
154
+ point 0 0
155
+ }
156
+ fill path {
157
+ for 0 to 8 {
158
+ curve 0 1
159
+ rotate 1 / 8
160
+ }
161
+ }
129
162
 
130
163
  // Stencil changes surface material without cutting away the first shape.
131
164
  stencil {
132
165
  cube { color 1 0 0 }
133
- cube { position 0.5 0 0 color 0 1 0 }
166
+ cube {
167
+ position 0.5 0 0
168
+ color 0 1 0
169
+ }
134
170
  }
135
171
 
136
172
  define offsets ((1 2 3), (4 5 6))
137
173
  cube { position offsets[0].x offsets[1].y offsets.count }
174
+
175
+ // Materials, as upstream: hex and named colours, alpha, PBR properties, bundles.
176
+ define brass material {
177
+ color #d4a017
178
+ metallicity 1
179
+ roughness 0.3
180
+ }
181
+ material brass
182
+ sphere
183
+ cube {
184
+ position 2
185
+ color red 0.5 // red at 50% alpha
186
+ glow orange * 0.3 // emissive
187
+ }
188
+
189
+ // Ranges, the `in` operator, custom functions and bare calls.
190
+ define steps 0 to 1 step 0.25
191
+ define ease(t) { t * t * (3 - 2 * t) }
192
+ for t in steps {
193
+ if t in 0.25 to 0.75 {
194
+ cube {
195
+ position (t * 4) (ease t) 0
196
+ size max 0.1 (t / 2)
197
+ }
198
+ }
199
+ }
200
+
201
+ // A rounded slab from two arcs, extruded; a bare path draws as a line.
202
+ extrude path {
203
+ arc { angle -0.5 }
204
+ point -0.5 0
205
+ point 1.5 0
206
+ arc {
207
+ position 1 0
208
+ orientation 0.5
209
+ angle -0.5
210
+ }
211
+ curve 0 0.5
212
+ }
138
213
  ```
139
214
 
140
- Also supported: `pi`, `tau`, `true`, `false`, scientific notation, unary `+`,
141
- short-circuit `and`/`or`, string literals, `join`/`trim`, tuple arguments to `min`/`max`,
142
- zero-based tuple/string subscripts, `.count`, vector `.x/.y/.z/.w`, color
143
- `.red/.green/.blue/.alpha` (or `.r/.g/.b/.a`), custom shape definitions with options,
144
- and `polygon { sides N }` (integer 3–256). Lathe samples curved profiles, and inline
145
- builder paths use the same parser as nested paths, including loops and definitions.
215
+ Also supported: `pi`, `tau` (plugin-only; upstream has no `tau`, so portable scripts write `2 * pi`), `true`, `false`, scientific notation, unary `+`,
216
+ short-circuit `and`/`or`, string literals, `join`/`split`/`trim`, tuple arguments to `min`/`max`,
217
+ zero-based tuple/string subscripts (negative from the end, or by name: `v["y"]`), `.count`, ordinal
218
+ members `.first` `.tenth`, `.last`, `.allButFirst`, `.allButLast`, vector `.x/.y/.z/.w`, size
219
+ `.width/.height/.depth`, rotation `.roll/.yaw/.pitch`, color `.red/.green/.blue/.alpha` (or
220
+ `.r/.g/.b/.a`) and `.hue/.saturation/.brightness`, custom shape definitions with options (placed
221
+ and coloured through `position` / `orientation` / `size` / `color` / `material` on the call), and
222
+ `polygon { sides N }` (integer 3–256). Lathe samples curved profiles (drawn on either side of the
223
+ axis), and inline builder paths use the same parser as nested paths, including loops and
224
+ definitions. A `material` command inside a builder block applies to the builder's result, and
225
+ `size` on a builder or group scales it (an extrude's Z is its depth). `print` lines and the
226
+ commands that were skipped come back on the root group's `userData` (`sceneInfoOf(group)`) and in
227
+ the tool result message.
228
+
229
+ ## Units and path semantics — same as upstream
230
+
231
+ Since 2.0.0 the plugin follows the [upstream ShapeScript](https://shapescript.info/mac/)
232
+ conventions, so a script written against the upstream docs renders the same here:
233
+
234
+ - `size` is the **diameter** of `sphere`, `cylinder`, `cone`, `circle`, `polygon` and `torus`
235
+ (a bare `sphere` fits the unit cube) and the edge length of `cube` / `square`.
236
+ - `orientation` (alias `rotation`) and `rotate` take **half-turns** as `roll yaw pitch` —
237
+ rotations about Z, Y and X applied in that order, `0.5` = 90°, positive clockwise (Euclid's
238
+ sign). A lone value is a roll; four values are `angle x y z`. Trig *functions* still use radians.
239
+ - Path `point` / `curve` coordinates are **absolute** in the path's frame; `rotate`, `translate`
240
+ and `scale` inside a path move that frame for later points. `curve` is a quadratic Bézier
241
+ **control point** — the outline passes through the neighbouring `point`s, and two `curve`s in
242
+ a row get an implicit on-curve midpoint (eight in an octagon draw a circle). A path block may
243
+ carry `position` / `orientation` / `size` of its own, which is how a `loft` section is placed in
244
+ 3D; `lathe` refuses a placed profile.
245
+ - `rnd` uses upstream's generator (`x = x · 1664525 + 1013904223 mod 2³²`, seed 0) and `seed N`
246
+ reseeds it for the enclosing block only.
247
+ - **Scope** (2.1.0): a shape block, `group`, builder or custom block resets transforms and
248
+ materials at its closing brace; `for` / `if` / `switch` bodies scope only symbols, so a
249
+ `translate` inside a loop carries on after it, as upstream's scope rules say.
250
+ - A **bare `path`** draws as a line (2.1.0), as upstream; `fill` / `extrude` / `lathe` / `loft`
251
+ make a surface or solid of it.
252
+ - `size 1 2` pads to `1 2 1` (Euclid's `Vector(size:)`), so `cylinder { size 1 2 }` is a
253
+ cylinder of diameter 1 and height 2.
254
+ - `extrude` is centred on its profile plane, spanning ±depth/2 (2.1.0; it ran 0…depth
255
+ before), and a lathe always faces outward whichever way its profile is drawn.
256
+
257
+ Deviations that remain: an *open* path whose first or last point is a `curve` treats it as a
258
+ corner (upstream extrapolates a tangent), path points are 2D, nested sub-paths (holes) are not
259
+ supported, and `smoothing` is flat (0) or smooth rather than an angle threshold. The gap list
260
+ lives in [`plans/feat-shapescript-upstream-parity.md`](../../../plans/feat-shapescript-upstream-parity.md).
146
261
 
147
262
  ## Compatibility and limits
148
263
 
149
264
  This is the plugin's documented modeling subset, **not complete compatibility with
150
- [upstream ShapeScript](https://shapescript.info/mac/)**. It preserves existing plugin
151
- conventions: primitive sphere/circle sizes specify radii; rotation/orientation properties
152
- and trig functions use radians; relative rotate/orientation commands and path rotation
153
- use turns (`1 = 360°`). Path point/curve coordinates are relative steps, and curve
154
- control coordinates are offsets from the endpoint. Upstream uses different conventions.
265
+ upstream ShapeScript**.
155
266
 
156
267
  Loft accepts ordered, closed planar sections with one perimeter each, resamples differing
157
268
  vertex counts, interpolates linearly, and triangulates the end caps. Sections must enclose
158
269
  a volume. Hull accepts geometry from child meshes and filled paths. Primitive profiles
159
- for fill/extrude must lie in XY; holes, swept/twisted extrusion, and arbitrary 3D path
160
- commands are not implemented. Imports, textures, text/fonts, lights/camera declarations,
161
- arbitrary objects, and general user-defined functions remain outside this subset.
162
- Unsupported commands and failed CSG operations return errors instead of silently
163
- substituting different geometry. As with other polygonal CSG engines, degenerate or
164
- self-intersecting inputs may fail.
270
+ for fill/extrude must lie in XY; holes, twisted extrusion (`twist`) and arbitrary 3D path
271
+ commands are not implemented. `extrude along` sweeps a section along a path (mitred at
272
+ corners, capped at the ends of an open path); an open path extrudes to a two-sided wall, as
273
+ upstream. `minkowski { a b }` is the hull of two convex solids' vertex sums, and for a
274
+ non-convex operand the merged per-face hulls (overlapping shells, not a boolean union — fine to
275
+ draw, not to feed to another boolean); `inset(mesh d)` slides every vertex to where its faces'
276
+ offset planes meet. `import`, `text` / `font`, `svgpath`, `object` values and paths as values
277
+ are refused with a message naming the feature. Textures,
278
+ normal maps, `camera` and `light` blocks are accepted and skipped with a warning that the
279
+ tool result and the View both report. Unsupported commands and failed CSG operations return
280
+ errors instead of silently substituting different geometry. As with other polygonal CSG
281
+ engines, degenerate or self-intersecting inputs may fail.
282
+
283
+ The upstream project's own example scripts are test fixtures
284
+ (`test/fixtures/upstream-examples/`, MIT): all nine — Ball, Chessboard, Cog, Dodecahedron, Earth,
285
+ Fillet, Spirals, Spring and Train — render.
286
+
287
+ ## Shapes as values, meshes and polygons
288
+
289
+ Since 2.2.0 a shape is a value, as upstream: `define ico icosphere { detail 0 }` keeps its mesh, `ico`
290
+ places it (with `position` / `orientation` / `size` on the call), and its members are readable —
291
+ `polygons` and `triangles` (each with `.center`, `.points`, `.bounds`), `bounds` (`.min` `.max`
292
+ `.center` `.size` `.width` `.height` `.depth`) and `volume`. The icosphere follows Euclid's
293
+ construction face for face, so scripts that index its faces (upstream's Dodecahedron) get the same
294
+ faces. `for v in … { expr }` and `if c { a } else { b }` are expressions, a function may build
295
+ shapes (`define face(data) { polygon { … } }`) and be called bare as a statement (`face data`), and
296
+ `mesh { … }` assembles the polygons its body produces — `polygon { color red point a point b point c }`
297
+ with 3D points, a tuple per point allowed — into one flat-shaded, vertex-coloured mesh. A value a
298
+ statement produces that is not a shape is an "unused value" error, as upstream. Paths as values and
299
+ `object` values remain unsupported.
300
+
165
301
 
166
302
  `rnd` and `rand()` draw from a seeded generator (`randomSeed`, default
167
- `DEFAULT_RANDOM_SEED`) rather than `Math.random()`: one script is evaluated twice — once
168
- on the server, which validates it, and again in the browser, which renders it — and an
169
- unseeded generator lets those two runs take different branches.
303
+ `DEFAULT_RANDOM_SEED` = 0, overridable in-script with `seed`) rather than `Math.random()`:
304
+ one script is evaluated twice — once on the server, which validates it, and again in the
305
+ browser, which renders it — and an unseeded generator lets those two runs take different
306
+ branches.
170
307
 
171
308
  Conversion limits cover nodes (100,000), loop/path work (100,000 iterations), detail (3–256),
172
309
  aggregate vertices (5,000,000, including CSG intermediates), and a coarse 30-second wall-clock
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/core/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;CA4K3B,CAAC"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/core/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;CAuR3B,CAAC"}
@@ -12,6 +12,7 @@ export { executeExportShapeScriptUsdz, EXPORT_USDZ_TOOL_NAME, EXPORT_USDZ_DESCRI
12
12
  export type { ExportUsdzResult } from "../export/tool";
13
13
  export { samples } from "./samples";
14
14
  export { parseShapeScript } from "../shapescript/parser";
15
- export { astToThreeJS } from "../shapescript/toThreeJS";
15
+ export { astToThreeJS, sceneInfoOf } from "../shapescript/toThreeJS";
16
+ export type { ShapeScriptSceneInfo } from "../shapescript/toThreeJS";
16
17
  export type { SceneNode } from "../shapescript/types";
17
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,gCAAgC,EAChC,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrF,YAAY,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACnH,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAIlJ,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,gCAAgC,EAChC,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrF,YAAY,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACnH,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAIlJ,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iCAAiC,EAAyB,MAAM,SAAS,CAAC;AACxI,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU1D;;;;;;;2EAO2E;AAC3E,MAAM,WAAW,yBAA0B,SAAQ,WAAW;IAC5D,KAAK,CAAC,EAAE;QACN,yEAAyE;QACzE,SAAS,EAAE,OAAO,CAAC;QACnB;4CACoC;QACpC,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AA+DD,eAAO,MAAM,kBAAkB,GAAU,SAAS,yBAAyB,EAAE,MAAM,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CAoCpJ,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,sBAAsB,EAAE,OAAO,EAAE,sBAAsB,CAM9F,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACtC,eAAO,MAAM,yBAAyB,YA/CY,yBAAyB,QAAQ,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CA+C1F,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iCAAiC,EAAyB,MAAM,SAAS,CAAC;AACxI,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU1D;;;;;;;2EAO2E;AAC3E,MAAM,WAAW,yBAA0B,SAAQ,WAAW;IAC5D,KAAK,CAAC,EAAE;QACN,yEAAyE;QACzE,SAAS,EAAE,OAAO,CAAC;QACnB;4CACoC;QACpC,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AA4ED,eAAO,MAAM,kBAAkB,GAAU,SAAS,yBAAyB,EAAE,MAAM,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CAoCpJ,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,sBAAsB,EAAE,OAAO,EAAE,sBAAsB,CAM9F,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACtC,eAAO,MAAM,yBAAyB,YA/CY,yBAAyB,QAAQ,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CA+C1F,CAAC"}
@@ -1 +1 @@
1
- const e=require("./samples-DZNAeuSZ.cjs"),t=require("./toThreeJS-XGDoVISb.cjs");var n=`exportShapeScriptUsdz`,r=t.t+3e4,i="Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR — scale the model in the script if that is not what the user wants.",a=`Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat — to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press "Download USDZ" in the model's view themselves.`,o={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to export. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to export (e.g. one presentShapeScript saved under artifacts/shapes/).`},title:{type:`string`,description:"Name for the exported file; it is slugified into the filename. Defaults to the .shape file's own name when `path` is given."}},required:[]};function s(e){return typeof e==`string`&&e.trim()!==``?e:void 0}function c(e){return(e.split(/[\\/]/).pop()??e).replace(/\.shape$/i,``)}async function l(t,n){let r=s(n.script),i=s(n.path),a=s(n.title);if(r&&i)throw Error("Provide either `script` or `path`, not both");if(r)return{script:r,title:a};if(!i)throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)");let o=e.u(t,i);if(!o)throw Error("`path` must name a .shape file, without `.` / `..` segments");if(!await o.files.exists(o.rel))throw Error(`No ShapeScript exists at ${i}`);return{script:await o.files.read(o.rel),title:a??c(i)}}async function u(t,n){let{script:r,title:i}=await l(t,n),a=await e.a(r),{relPath:o,filePath:s}=e._(i);return await t.files.artifacts.write(o,a),{message:`Saved USDZ to ${s} (${a.byteLength} bytes). Open it with AR Quick Look or any USD viewer.`,filePath:s,bytes:a.byteLength}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
1
+ const e=require("./samples-D2_jOmoh.cjs"),t=require("./toThreeJS-Cs0UJm82.cjs");var n=`exportShapeScriptUsdz`,r=t.t+3e4,i="Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR — scale the model in the script if that is not what the user wants.",a=`Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat — to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press "Download USDZ" in the model's view themselves.`,o={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to export. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to export (e.g. one presentShapeScript saved under artifacts/shapes/).`},title:{type:`string`,description:"Name for the exported file; it is slugified into the filename. Defaults to the .shape file's own name when `path` is given."}},required:[]};function s(e){return typeof e==`string`&&e.trim()!==``?e:void 0}function c(e){return(e.split(/[\\/]/).pop()??e).replace(/\.shape$/i,``)}async function l(t,n){let r=s(n.script),i=s(n.path),a=s(n.title);if(r&&i)throw Error("Provide either `script` or `path`, not both");if(r)return{script:r,title:a};if(!i)throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)");let o=e.u(t,i);if(!o)throw Error("`path` must name a .shape file, without `.` / `..` segments");if(!await o.files.exists(o.rel))throw Error(`No ShapeScript exists at ${i}`);return{script:await o.files.read(o.rel),title:a??c(i)}}async function u(t,n){let{script:r,title:i}=await l(t,n),a=await e.a(r),{relPath:o,filePath:s}=e._(i);return await t.files.artifacts.write(o,a),{message:`Saved USDZ to ${s} (${a.byteLength} bytes). Open it with AR Quick Look or any USD viewer.`,filePath:s,bytes:a.byteLength}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
@@ -1,5 +1,5 @@
1
- import { _ as e, a as t, u as n } from "./samples-DPOGWslc.js";
2
- import { t as r } from "./toThreeJS-BX_aeGdA.js";
1
+ import { _ as e, a as t, u as n } from "./samples-CT-c9o1S.js";
2
+ import { t as r } from "./toThreeJS-CKjSbEnA.js";
3
3
  //#region src/export/tool.ts
4
4
  var i = "exportShapeScriptUsdz", a = r + 3e4, o = "Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR — scale the model in the script if that is not what the user wants.", s = "Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat — to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press \"Download USDZ\" in the model's view themselves.", c = {
5
5
  type: "object",
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DZNAeuSZ.cjs"),t=require("./toThreeJS-XGDoVISb.cjs"),n=require("./core-bcFgqR_m.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.zn,exports.locateShape=e.u,exports.parseShapeScript=t.In,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Bn,exports.readSaveShapeResult=t.Vn,exports.samples=e.t,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-D2_jOmoh.cjs"),t=require("./toThreeJS-Cs0UJm82.cjs"),n=require("./core-BBgBeYYe.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.Bn,exports.locateShape=e.u,exports.parseShapeScript=t.s,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Vn,exports.readSaveShapeResult=t.Hn,exports.samples=e.t,exports.sceneInfoOf=t.i,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
package/dist/core.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-DPOGWslc.js";
2
- import { Bn as v, In as y, Vn as b, r as x, zn as S } from "./toThreeJS-BX_aeGdA.js";
3
- import { a as C, i as w, n as T, o as E, r as D, t as O } from "./core-CpVzK-0i.js";
4
- export { O as EXPORT_USDZ_DESCRIPTION, T as EXPORT_USDZ_PROMPT, D as EXPORT_USDZ_SCHEMA, w as EXPORT_USDZ_TOOL_NAME, C as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, x as astToThreeJS, E as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, S as isShapeScriptDispatchArgs, h as locateShape, y as parseShapeScript, p as pluginCore, n as presentShapeScript, v as readLoadShapeResult, b as readSaveShapeResult, m as samples, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-CT-c9o1S.js";
2
+ import { Bn as v, Hn as y, Vn as b, i as x, r as S, s as C } from "./toThreeJS-CKjSbEnA.js";
3
+ import { a as w, i as T, n as E, o as D, r as O, t as k } from "./core-yB1Eiacr.js";
4
+ export { k as EXPORT_USDZ_DESCRIPTION, E as EXPORT_USDZ_PROMPT, O as EXPORT_USDZ_SCHEMA, T as EXPORT_USDZ_TOOL_NAME, w as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, S as astToThreeJS, D as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, v as isShapeScriptDispatchArgs, h as locateShape, C as parseShapeScript, p as pluginCore, n as presentShapeScript, b as readLoadShapeResult, y as readSaveShapeResult, m as samples, x as sceneInfoOf, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DZNAeuSZ.cjs"),t=require("./toThreeJS-XGDoVISb.cjs"),n=require("./core-bcFgqR_m.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.zn,exports.locateShape=e.u,exports.parseShapeScript=t.In,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Bn,exports.readSaveShapeResult=t.Vn,exports.samples=e.t,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-D2_jOmoh.cjs"),t=require("./toThreeJS-Cs0UJm82.cjs"),n=require("./core-BBgBeYYe.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.Bn,exports.locateShape=e.u,exports.parseShapeScript=t.s,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Vn,exports.readSaveShapeResult=t.Hn,exports.samples=e.t,exports.sceneInfoOf=t.i,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-DPOGWslc.js";
2
- import { Bn as v, In as y, Vn as b, r as x, zn as S } from "./toThreeJS-BX_aeGdA.js";
3
- import { a as C, i as w, n as T, o as E, r as D, t as O } from "./core-CpVzK-0i.js";
4
- export { O as EXPORT_USDZ_DESCRIPTION, T as EXPORT_USDZ_PROMPT, D as EXPORT_USDZ_SCHEMA, w as EXPORT_USDZ_TOOL_NAME, C as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, x as astToThreeJS, E as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, S as isShapeScriptDispatchArgs, h as locateShape, y as parseShapeScript, p as pluginCore, n as presentShapeScript, v as readLoadShapeResult, b as readSaveShapeResult, m as samples, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-CT-c9o1S.js";
2
+ import { Bn as v, Hn as y, Vn as b, i as x, r as S, s as C } from "./toThreeJS-CKjSbEnA.js";
3
+ import { a as w, i as T, n as E, o as D, r as O, t as k } from "./core-yB1Eiacr.js";
4
+ export { k as EXPORT_USDZ_DESCRIPTION, E as EXPORT_USDZ_PROMPT, O as EXPORT_USDZ_SCHEMA, T as EXPORT_USDZ_TOOL_NAME, w as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, S as astToThreeJS, D as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, v as isShapeScriptDispatchArgs, h as locateShape, C as parseShapeScript, p as pluginCore, n as presentShapeScript, b as readLoadShapeResult, y as readSaveShapeResult, m as samples, x as sceneInfoOf, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
@@ -1 +1 @@
1
- {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/lang/de.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/lang/de.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/lang/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/lang/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/lang/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/lang/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fr.d.ts","sourceRoot":"","sources":["../../src/lang/fr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"fr.d.ts","sourceRoot":"","sources":["../../src/lang/fr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/lang/ja.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/lang/ja.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ko.d.ts","sourceRoot":"","sources":["../../src/lang/ko.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"ko.d.ts","sourceRoot":"","sources":["../../src/lang/ko.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -10,5 +10,9 @@ export interface Messages {
10
10
  saveError: string;
11
11
  downloadUsdz: string;
12
12
  exportError: string;
13
+ /** Heading for commands the script used that this viewer does not draw. */
14
+ sceneWarnings: string;
15
+ /** Heading for the script's `print` lines. */
16
+ printOutput: string;
13
17
  }
14
18
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/lang/messages.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/lang/messages.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ptBR.d.ts","sourceRoot":"","sources":["../../src/lang/ptBR.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,IAAI,EAAE,QAYX,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"ptBR.d.ts","sourceRoot":"","sources":["../../src/lang/ptBR.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,IAAI,EAAE,QAcX,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"zh.d.ts","sourceRoot":"","sources":["../../src/lang/zh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"zh.d.ts","sourceRoot":"","sources":["../../src/lang/zh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAcT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/render/page.ts"],"names":[],"mappings":"AAYA,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IAC5B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,GAAG,cAAc,CAAC;CAC5C;AAED,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAGxE;AAyFD;8EAC8E;AAC9E,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAWlE"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/render/page.ts"],"names":[],"mappings":"AAYA,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IAC5B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,GAAG,cAAc,CAAC;CAC5C;AAED,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAGxE;AA6FD;8EAC8E;AAC9E,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAWlE"}
package/dist/render.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));const c=require("./toThreeJS-XGDoVISb.cjs");let l=require("node:fs/promises"),u=require("node:module"),d=require("node:url"),f=require("node:path");f=s(f,1);function p(e){let t=Math.ceil(Math.sqrt(e));return{columns:t,rows:Math.ceil(e/t)}}function m(e,t,n){return`import { AmbientLight, Box3, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));const c=require("./toThreeJS-Cs0UJm82.cjs");let l=require("node:fs/promises"),u=require("node:module"),d=require("node:url"),f=require("node:path");f=s(f,1);function p(e){let t=Math.ceil(Math.sqrt(e));return{columns:t,rows:Math.ceil(e/t)}}function m(e,t,n){return`import { AmbientLight, Box3, Color, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
2
2
 
3
3
  const config = ${t};
4
4
  const { columns, rows } = ${n};
@@ -17,10 +17,14 @@ const bounds = new Box3().setFromObject(model);
17
17
  const sphere = bounds.getBoundingSphere(new Sphere());
18
18
  const radius = sphere.radius > 0 && isFinite(sphere.radius) ? sphere.radius : 1;
19
19
 
20
- const renderer = new WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
20
+ // An alpha buffer, so a translucent \`background r g b a\` blends over the sheet's white paper.
21
+ const renderer = new WebGLRenderer({ antialias: true, preserveDrawingBuffer: true, alpha: true });
21
22
  renderer.setPixelRatio(1);
22
23
  renderer.setSize(config.width, config.height, false);
23
- renderer.setClearColor(0xffffff, 1);
24
+ // The script's own \`background r g b [a]\` when it set one, else white paper.
25
+ const background = Array.isArray(model.userData?.background) ? model.userData.background : null;
26
+ if (background) renderer.setClearColor(new Color(background[0], background[1], background[2]), background[3] ?? 1);
27
+ else renderer.setClearColor(0xffffff, 1);
24
28
 
25
29
  const scene = new Scene();
26
30
  scene.add(model);
@@ -79,4 +83,4 @@ window.__shapeSheet = sheet.toDataURL("image/png");`}function g(e){let{threeUrl:
79
83
  <canvas id="sheet"></canvas>
80
84
  <script type="module">
81
85
  ${`${m(t,JSON.stringify({views:r,width:i,height:a,zoom:o,projection:s,scene:n}),JSON.stringify(p(r.length)))}\n${h()}`}
82
- <\/script>`}var _=1e3;function v(e){return e instanceof Error?e.message:String(e)}var y=60*_,b=30*_,x=9e4,S="renderShapeScript needs Puppeteer's headless Chromium, which this host does not have. Run `npx puppeteer browsers install chrome`, then retry. Everything else, including presentShapeScript, works without it.",C=class extends Error{};function w(e,t){try{e?.(t)}catch{}}function T(){let e={}.url;if(typeof e==`string`&&e.length>0)return e;if(typeof __filename==`string`)return(0,d.pathToFileURL)(__filename).href;throw Error(`shapescript render: cannot locate this module to resolve three from`)}var E=(0,u.createRequire)(T());function D(e){return c.Rn(e)&&typeof e.launch==`function`}async function ee(){try{let e=await import(`puppeteer`);return D(e)?e:c.Rn(e)&&D(e.default)?e.default:null}catch{return null}}function te(){try{return(0,u.createRequire)(E.resolve(`@mulmoclaude/shapescript-plugin/package.json`))}catch{return E}}function O(){let e=te().resolve(`three`);return e.endsWith(`three.cjs`)?e.replace(/three\.cjs$/,`three.module.js`):e}var k=`https://shapescript.invalid`,A=`${k}/render.html`,j=`./three.module.js`;async function M(e,t,n){let r;try{r=new URL(e)}catch{return null}if(r.origin!==k)return null;let i=f.default.posix.basename(r.pathname);return i===`render.html`?{contentType:`text/html; charset=utf-8`,body:t}:/^three[\w.-]*\.js$/.test(i)?{contentType:`text/javascript; charset=utf-8`,body:await(0,l.readFile)(f.default.join(n,i),`utf-8`)}:null}async function N(e,t){let n=f.default.dirname(O());await e.setRequestInterception(!0),e.on(`request`,e=>{(async()=>{try{let r=await M(e.url(),t,n);await(r?e.respond({status:200,...r}):e.abort())}catch{}})()})}async function P(e){let t=await ee();if(!t)throw new C(S);let n=c.r(c.In(e.script)).toJSON(),r=g({...e,threeUrl:j,sceneJson:n}),i;try{i=await t.launch({headless:!0,timeout:b,args:[`--enable-unsafe-swiftshader`,`--use-gl=swiftshader`]})}catch(e){throw new C(`${S} (launch failed: ${v(e)})`)}try{let e=await i.newPage();await e.setViewport({width:800,height:600});let t=[];e.on(`pageerror`,e=>t.push(e.message)),await N(e,r),await e.goto(A,{waitUntil:`load`});try{await e.waitForFunction(`typeof window.__shapeSheet === 'string'`,{timeout:y})}catch(e){let n=t.length>0?`the render page failed: ${t.join(`; `)}`:v(e);throw Error(n,{cause:e})}let n=await e.evaluate(`window.__shapeSheet`);if(typeof n!=`string`||!n.startsWith(`data:image/png;base64,`))throw Error(`the render page produced no image`);return n.slice(22)}finally{await i.close().catch(t=>w(e.onWarning,`chromium close failed: ${v(t)}`))}}var F=30,I=25,L=1,R=480,z=900,B=160,V=85,H=x+3e4,U=`renderShapeScript`,W="Render a ShapeScript model to a PNG image and save it, so you can LOOK at the model you wrote and check it before showing it to the user. Returns the image path — read that file to see the result. By default it renders four camera angles onto one sheet, because a single view cannot settle what is in front of what. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file.",G=`Use renderShapeScript to CHECK a 3D model you wrote before presenting it — it saves a PNG and returns the path, which you then read to see what the model actually looks like. Fix what you see and re-render. Rendering needs a local headless browser; if it reports one is missing, say so and continue with presentShapeScript rather than retrying.`,K={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to render. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to render (e.g. one presentShapeScript saved under artifacts/shapes/).`},azimuth:{type:`number`,description:`Camera rotation around the model in degrees, 0 = looking from +Z. Default ${F}. In the default four-view sheet this is the FIRST view's angle; the others are offset from it.`},elevation:{type:`number`,description:`Camera height in degrees above the horizon, 90 = straight down. Default ${I}. Avoid 0 and 90 for the main view — an axis-aligned shot flattens depth.`},zoom:{type:`number`,description:`Multiplier on the automatic framing, which fits the whole model. 1 = fit (default), 2 = twice as close, 0.5 = further out. Prefer this over guessing a camera distance: it means the same thing at any model scale.`},views:{type:`string`,enum:[`quad`,`single`],description:"`quad` (default) renders four angles on one sheet — use it to judge shape and layout. `single` renders only `azimuth`/`elevation`, for a close look at one detail."},projection:{type:`string`,enum:[`perspective`,`orthographic`],description:"`perspective` (default) looks natural; `orthographic` keeps parallel edges parallel, which is better for comparing proportions."},width:{type:`number`,description:`Pixel width of ONE view. Default ${R}, clamped to ${B}–${z}.`},height:{type:`number`,description:`Pixel height of ONE view. Default ${R}, clamped to ${B}–${z}.`}},required:[]};function q(e,t){return typeof e!=`number`||!Number.isFinite(e)?t:Math.min(z,Math.max(B,Math.round(e)))}function J(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}var Y=e=>`${Math.round(e)}°`;function X(e,t,n){let r=(e,t,n)=>({azimuth:e,elevation:t,label:`${n} — az ${Y(e)}, el ${Y(t)}`});return n?[r(e,t,`view`)]:[r(e,t,`front-right`),r(e+90,t,`back-right`),r(e+180,t,`back-left`),r(e,V,`top`)]}async function Z(e,t){let n=typeof t.script==`string`&&t.script.trim()!==``?t.script:void 0,r=typeof t.path==`string`&&t.path.trim()!==``?t.path:void 0;if(n&&r)throw Error("Provide either `script` or `path`, not both");if(n)return n;if(r)return e.readShape(r);throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)")}function Q(e,t,n,r){return{script:t,views:n,width:q(e.width,R),height:q(e.height,R),zoom:Math.max(J(e.zoom,L),.01),projection:e.projection===`orthographic`?`orthographic`:`perspective`,...r?{onWarning:r}:{}}}function $(e,t){let n=t.map(e=>e.label).join(`; `);return`Saved render to ${e} (${t.length===1?`1 view`:`${t.length} views`}: ${n}). Read that file to see the model.`}async function ne(e,t){let n=await Z(e,t),r=X(J(t.azimuth,F),J(t.elevation,I),t.views===`single`);try{let i=await P(Q(t,n,r,e.onWarning));return{message:$(await e.saveImage(i),r),rendered:!0}}catch(t){if(t instanceof C)return w(e.onWarning,`renderShapeScript: unavailable — ${t.message}`),{message:t.message,rendered:!1};throw t}}exports.CHROMIUM_HINT=S,exports.LAUNCH_TIMEOUT_MS=b,exports.RENDER_BUDGET_MS=x,exports.RENDER_SHAPE_SCRIPT_DESCRIPTION=W,exports.RENDER_SHAPE_SCRIPT_PROMPT=G,exports.RENDER_SHAPE_SCRIPT_SCHEMA=K,exports.RENDER_SHAPE_SCRIPT_TOOL_NAME=U,exports.RENDER_TIMEOUT_MS=y,exports.RENDER_TOOL_TIMEOUT_MS=H,exports.RenderUnavailableError=C,exports.buildRenderPage=g,exports.executeRenderShapeScript=ne,exports.gridFor=p,exports.renderOptionsFrom=Q,exports.renderShapeScriptSheet=P,exports.savedMessage=$,exports.viewAngles=X;
86
+ <\/script>`}var _=1e3;function v(e){return e instanceof Error?e.message:String(e)}var y=60*_,b=30*_,x=9e4,S="renderShapeScript needs Puppeteer's headless Chromium, which this host does not have. Run `npx puppeteer browsers install chrome`, then retry. Everything else, including presentShapeScript, works without it.",C=class extends Error{};function w(e,t){try{e?.(t)}catch{}}function T(){let e={}.url;if(typeof e==`string`&&e.length>0)return e;if(typeof __filename==`string`)return(0,d.pathToFileURL)(__filename).href;throw Error(`shapescript render: cannot locate this module to resolve three from`)}var E=(0,u.createRequire)(T());function D(e){return c.zn(e)&&typeof e.launch==`function`}async function ee(){try{let e=await import(`puppeteer`);return D(e)?e:c.zn(e)&&D(e.default)?e.default:null}catch{return null}}function te(){try{return(0,u.createRequire)(E.resolve(`@mulmoclaude/shapescript-plugin/package.json`))}catch{return E}}function O(){let e=te().resolve(`three`);return e.endsWith(`three.cjs`)?e.replace(/three\.cjs$/,`three.module.js`):e}var k=`https://shapescript.invalid`,A=`${k}/render.html`,j=`./three.module.js`;async function M(e,t,n){let r;try{r=new URL(e)}catch{return null}if(r.origin!==k)return null;let i=f.default.posix.basename(r.pathname);return i===`render.html`?{contentType:`text/html; charset=utf-8`,body:t}:/^three[\w.-]*\.js$/.test(i)?{contentType:`text/javascript; charset=utf-8`,body:await(0,l.readFile)(f.default.join(n,i),`utf-8`)}:null}async function N(e,t){let n=f.default.dirname(O());await e.setRequestInterception(!0),e.on(`request`,e=>{(async()=>{try{let r=await M(e.url(),t,n);await(r?e.respond({status:200,...r}):e.abort())}catch{}})()})}async function P(e){let t=await ee();if(!t)throw new C(S);let n=c.r(c.s(e.script)).toJSON(),r=g({...e,threeUrl:j,sceneJson:n}),i;try{i=await t.launch({headless:!0,timeout:b,args:[`--enable-unsafe-swiftshader`,`--use-gl=swiftshader`]})}catch(e){throw new C(`${S} (launch failed: ${v(e)})`)}try{let e=await i.newPage();await e.setViewport({width:800,height:600});let t=[];e.on(`pageerror`,e=>t.push(e.message)),await N(e,r),await e.goto(A,{waitUntil:`load`});try{await e.waitForFunction(`typeof window.__shapeSheet === 'string'`,{timeout:y})}catch(e){let n=t.length>0?`the render page failed: ${t.join(`; `)}`:v(e);throw Error(n,{cause:e})}let n=await e.evaluate(`window.__shapeSheet`);if(typeof n!=`string`||!n.startsWith(`data:image/png;base64,`))throw Error(`the render page produced no image`);return n.slice(22)}finally{await i.close().catch(t=>w(e.onWarning,`chromium close failed: ${v(t)}`))}}var F=30,I=25,L=1,R=480,z=900,B=160,V=85,H=x+3e4,U=`renderShapeScript`,W="Render a ShapeScript model to a PNG image and save it, so you can LOOK at the model you wrote and check it before showing it to the user. Returns the image path — read that file to see the result. By default it renders four camera angles onto one sheet, because a single view cannot settle what is in front of what. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file.",G=`Use renderShapeScript to CHECK a 3D model you wrote before presenting it — it saves a PNG and returns the path, which you then read to see what the model actually looks like. Fix what you see and re-render. Rendering needs a local headless browser; if it reports one is missing, say so and continue with presentShapeScript rather than retrying.`,K={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to render. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to render (e.g. one presentShapeScript saved under artifacts/shapes/).`},azimuth:{type:`number`,description:`Camera rotation around the model in degrees, 0 = looking from +Z. Default ${F}. In the default four-view sheet this is the FIRST view's angle; the others are offset from it.`},elevation:{type:`number`,description:`Camera height in degrees above the horizon, 90 = straight down. Default ${I}. Avoid 0 and 90 for the main view — an axis-aligned shot flattens depth.`},zoom:{type:`number`,description:`Multiplier on the automatic framing, which fits the whole model. 1 = fit (default), 2 = twice as close, 0.5 = further out. Prefer this over guessing a camera distance: it means the same thing at any model scale.`},views:{type:`string`,enum:[`quad`,`single`],description:"`quad` (default) renders four angles on one sheet — use it to judge shape and layout. `single` renders only `azimuth`/`elevation`, for a close look at one detail."},projection:{type:`string`,enum:[`perspective`,`orthographic`],description:"`perspective` (default) looks natural; `orthographic` keeps parallel edges parallel, which is better for comparing proportions."},width:{type:`number`,description:`Pixel width of ONE view. Default ${R}, clamped to ${B}–${z}.`},height:{type:`number`,description:`Pixel height of ONE view. Default ${R}, clamped to ${B}–${z}.`}},required:[]};function q(e,t){return typeof e!=`number`||!Number.isFinite(e)?t:Math.min(z,Math.max(B,Math.round(e)))}function J(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}var Y=e=>`${Math.round(e)}°`;function X(e,t,n){let r=(e,t,n)=>({azimuth:e,elevation:t,label:`${n} — az ${Y(e)}, el ${Y(t)}`});return n?[r(e,t,`view`)]:[r(e,t,`front-right`),r(e+90,t,`back-right`),r(e+180,t,`back-left`),r(e,V,`top`)]}async function Z(e,t){let n=typeof t.script==`string`&&t.script.trim()!==``?t.script:void 0,r=typeof t.path==`string`&&t.path.trim()!==``?t.path:void 0;if(n&&r)throw Error("Provide either `script` or `path`, not both");if(n)return n;if(r)return e.readShape(r);throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)")}function Q(e,t,n,r){return{script:t,views:n,width:q(e.width,R),height:q(e.height,R),zoom:Math.max(J(e.zoom,L),.01),projection:e.projection===`orthographic`?`orthographic`:`perspective`,...r?{onWarning:r}:{}}}function $(e,t){let n=t.map(e=>e.label).join(`; `);return`Saved render to ${e} (${t.length===1?`1 view`:`${t.length} views`}: ${n}). Read that file to see the model.`}async function ne(e,t){let n=await Z(e,t),r=X(J(t.azimuth,F),J(t.elevation,I),t.views===`single`);try{let i=await P(Q(t,n,r,e.onWarning));return{message:$(await e.saveImage(i),r),rendered:!0}}catch(t){if(t instanceof C)return w(e.onWarning,`renderShapeScript: unavailable — ${t.message}`),{message:t.message,rendered:!1};throw t}}exports.CHROMIUM_HINT=S,exports.LAUNCH_TIMEOUT_MS=b,exports.RENDER_BUDGET_MS=x,exports.RENDER_SHAPE_SCRIPT_DESCRIPTION=W,exports.RENDER_SHAPE_SCRIPT_PROMPT=G,exports.RENDER_SHAPE_SCRIPT_SCHEMA=K,exports.RENDER_SHAPE_SCRIPT_TOOL_NAME=U,exports.RENDER_TIMEOUT_MS=y,exports.RENDER_TOOL_TIMEOUT_MS=H,exports.RenderUnavailableError=C,exports.buildRenderPage=g,exports.executeRenderShapeScript=ne,exports.gridFor=p,exports.renderOptionsFrom=Q,exports.renderShapeScriptSheet=P,exports.savedMessage=$,exports.viewAngles=X;
package/dist/render.js CHANGED
@@ -1,4 +1,4 @@
1
- import { In as e, Rn as t, r as n } from "./toThreeJS-BX_aeGdA.js";
1
+ import { r as e, s as t, zn as n } from "./toThreeJS-CKjSbEnA.js";
2
2
  import { readFile as r } from "node:fs/promises";
3
3
  import { createRequire as i } from "node:module";
4
4
  import { pathToFileURL as a } from "node:url";
@@ -12,7 +12,7 @@ function s(e) {
12
12
  };
13
13
  }
14
14
  function c(e, t, n) {
15
- return `import { AmbientLight, Box3, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
15
+ return `import { AmbientLight, Box3, Color, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
16
16
 
17
17
  const config = ${t};
18
18
  const { columns, rows } = ${n};
@@ -31,10 +31,14 @@ const bounds = new Box3().setFromObject(model);
31
31
  const sphere = bounds.getBoundingSphere(new Sphere());
32
32
  const radius = sphere.radius > 0 && isFinite(sphere.radius) ? sphere.radius : 1;
33
33
 
34
- const renderer = new WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
34
+ // An alpha buffer, so a translucent \`background r g b a\` blends over the sheet's white paper.
35
+ const renderer = new WebGLRenderer({ antialias: true, preserveDrawingBuffer: true, alpha: true });
35
36
  renderer.setPixelRatio(1);
36
37
  renderer.setSize(config.width, config.height, false);
37
- renderer.setClearColor(0xffffff, 1);
38
+ // The script's own \`background r g b [a]\` when it set one, else white paper.
39
+ const background = Array.isArray(model.userData?.background) ? model.userData.background : null;
40
+ if (background) renderer.setClearColor(new Color(background[0], background[1], background[2]), background[3] ?? 1);
41
+ else renderer.setClearColor(0xffffff, 1);
38
42
 
39
43
  const scene = new Scene();
40
44
  scene.add(model);
@@ -92,12 +96,12 @@ function y() {
92
96
  }
93
97
  var b = i(y());
94
98
  function x(e) {
95
- return t(e) && typeof e.launch == "function";
99
+ return n(e) && typeof e.launch == "function";
96
100
  }
97
101
  async function S() {
98
102
  try {
99
103
  let e = await import("puppeteer");
100
- return x(e) ? e : t(e) && x(e.default) ? e.default : null;
104
+ return x(e) ? e : n(e) && x(e.default) ? e.default : null;
101
105
  } catch {
102
106
  return null;
103
107
  }
@@ -145,11 +149,11 @@ async function k(e, t) {
145
149
  })();
146
150
  });
147
151
  }
148
- async function A(t) {
152
+ async function A(n) {
149
153
  let r = await S();
150
154
  if (!r) throw new _(g);
151
- let i = n(e(t.script)).toJSON(), a = u({
152
- ...t,
155
+ let i = e(t(n.script)).toJSON(), a = u({
156
+ ...n,
153
157
  threeUrl: D,
154
158
  sceneJson: i
155
159
  }), o;
@@ -180,7 +184,7 @@ async function A(t) {
180
184
  if (typeof n != "string" || !n.startsWith("data:image/png;base64,")) throw Error("the render page produced no image");
181
185
  return n.slice(22);
182
186
  } finally {
183
- await o.close().catch((e) => v(t.onWarning, `chromium close failed: ${f(e)}`));
187
+ await o.close().catch((e) => v(n.onWarning, `chromium close failed: ${f(e)}`));
184
188
  }
185
189
  }
186
190
  //#endregion