lecodes-cli 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "lecodes-cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "dependencies": {
5
- "@letary/chisel": "^0.5.1"
5
+ "@letary/chisel": "^0.6.0"
6
6
  },
7
7
  "devDependencies": {
8
8
  "lecodes-design": "workspace:*",
@@ -241,8 +241,8 @@ export class Canvas {
241
241
  }
242
242
 
243
243
  /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File
244
- * is a host buffer handle {id,name,size}: append it to a FormData to upload, load it as a texture
245
- * (`Texture2D.load(file)`), or hand it to a share/save sheet. */
244
+ * is an opaque host buffer handle (`name`/`size` only): append it to a FormData to upload, load it
245
+ * as a texture (`Texture2D.load(file)`), or hand it to a share/save sheet. */
246
246
  toFile(name = "canvas.png", type = "image/png"): Promise<File> {
247
247
  const surfaceId = this._bakeSurface()
248
248
  return new Promise<File>((res, rej) => {
@@ -37,7 +37,7 @@ export class Texture2D {
37
37
  })
38
38
  }
39
39
  return new Promise<Texture2D>((resolve, reject) => {
40
- _creator2d.createTexture((source as any).id ?? (source as any)._id, (id, w, h) => resolve(new Texture2D(id, w, h)), reject)
40
+ _creator2d.createTexture((source as any)._id, (id, w, h) => resolve(new Texture2D(id, w, h)), reject)
41
41
  })
42
42
  }
43
43
 
@@ -36,6 +36,36 @@ const applyUniform = (id: number, key: string, value: UniformValue): void => {
36
36
 
37
37
  export type MaterialColorOptions = { color?: ColorInput, map?: Texture | Canvas | null }
38
38
 
39
+ /** `Material.particles` options — the default point-sprite material for particle systems. */
40
+ export type ParticlesMaterialOptions = {
41
+ /** Sprite texture — a single image or a flipbook sheet of frames. Unset = soft round dot. */
42
+ map?: Texture | null
43
+ /** Flipbook grid: `N` = an N×N sheet, `[cols, rows]` = a non-square one. Frames run
44
+ * left-to-right, top-to-bottom; drive the index via `particles.frame`. Default 1. */
45
+ sheet?: number | [number, number]
46
+ /** Extra brightness multiplier for a glow look (0 = off). */
47
+ emissive?: number
48
+ /** Compositing: `"alpha"` (default — smoke, dust) or `"add"` (fire, sparks, magic). */
49
+ blend?: "alpha" | "add"
50
+ /** Soft radial falloff toward the sprite edge. Defaults to true without a map, false with one. */
51
+ soft?: boolean
52
+ /** How each particle is drawn: `'point'` (default — GPU point sprites, cheapest), `'quad'`
53
+ * (real camera-facing quads — no driver size cap, geometric rotation), or `'stretch'`
54
+ * (quads stretched along velocity — sparks, rain, speed streaks). `'ribbon'` is what `Trail`
55
+ * uses internally. */
56
+ render?: "point" | "quad" | "stretch" | "ribbon"
57
+ /** (`render: 'stretch'`) extra sprite length in world units per unit of speed:
58
+ * length = size + stretch·|velocity|. Default 0.05. */
59
+ stretch?: number
60
+ }
61
+
62
+ /** @internal — the sheet option as whole [cols, rows], both ≥ 1. The particles shader divides
63
+ * by these with no guard of its own, so this clamp is the only thing between it and a NaN UV. */
64
+ export const _sheetColsRows = (sheet: number | [number, number] | undefined): [number, number] => {
65
+ const [ c, r ] = typeof sheet === "number" ? [ sheet, sheet ] : sheet ?? [ 1, 1 ]
66
+ return [ Math.max(1, Math.floor(c) || 1), Math.max(1, Math.floor(r) || 1) ]
67
+ }
68
+
39
69
  /** `Material.lit` options — PBR scalars on top of the color/map pair. */
40
70
  export type LitMaterialOptions = MaterialColorOptions & {
41
71
  /** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */
@@ -116,6 +146,28 @@ export class Material {
116
146
  return m
117
147
  }
118
148
 
149
+ /** Default particle material — camera-facing point sprites with tint/opacity/rotation/flipbook
150
+ * driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look
151
+ * knob is primed here; JS writes after construction override them. */
152
+ static particles(options: ParticlesMaterialOptions = {}): Material {
153
+ const quad = options.render !== undefined && options.render !== "point"
154
+ // Both fetchLocal literals inline so the compiler's preload header captures the shader names.
155
+ const m = quad
156
+ ? new Material({ _id: _creatorUtils.fetchLocal("particles-quad.filamat") } as any)
157
+ : new Material({ _id: _creatorUtils.fetchLocal("particles.filamat") } as any)
158
+ m._useMapFlag = false
159
+ m.uniforms.sheetSize = _sheetColsRows(options.sheet)
160
+ m.uniforms.emissive = options.emissive ?? 0
161
+ m.uniforms.additive = options.blend === "add" ? 1 : 0
162
+ m.uniforms.softness = (options.soft ?? !options.map) ? 1 : 0
163
+ if (quad) {
164
+ m.uniforms.mode = options.render === "ribbon" ? 2 : options.render === "stretch" ? 1 : 0
165
+ m.uniforms.stretch = options.stretch ?? (options.render === "stretch" ? 0.05 : 0)
166
+ }
167
+ if (options.map) m.map = options.map
168
+ return m
169
+ }
170
+
119
171
  /** Material that samples a VideoPlayer's texture. */
120
172
  static video(map?: Texture): Material {
121
173
  const m = new Material({ _id: _creatorUtils.fetchLocal("video.filamat") } as any)