babylon.quarks 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,85 @@ All notable changes to the `babylon.quarks` package are documented here.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and the project follows the `quarks.core` 0.x version line.
6
6
 
7
+ ## [0.21.0] — 2026-10-16
8
+
9
+ ### Added
10
+
11
+ - `QuarksResourceResolver` on `QuarksLoaderOptions` (`resolve` / `fetchJson`) so File pickers,
12
+ CDN layouts and virtual FS backends can resolve relative texture and geometry links without
13
+ calling `resolveExternalGeometries` by hand.
14
+ - `loadFromJSON(json, baseUrl?)` — same pipeline as `load(url)` when the effect document is
15
+ already in memory; `resolveResources` / static `resolveLinkedResources` for prepare-only.
16
+ - `loadAll(urls)` and `loadFromJSONAll(entries)` for battle / level preload: fetch effect docs
17
+ (optional `concurrency`), resolve every linked geometry/image across the pack so shared asset
18
+ urls hit a per-scene fetch cache once, then parse. `continueOnError` and `onProgress` (once per
19
+ settled effect) supported; without `continueOnError` the return type is `TransformNode[]`.
20
+ - `QuarksLoader.joinUrl` for portable baseUrl joining (data/blob/absolute urls left alone).
21
+
22
+ ### Changed
23
+
24
+ - `load(url)` goes through `loadFromJSON` after fetching the effect JSON. Geometry JSON fetches
25
+ are deduped per scene; inlined array fields are copied so cached documents are not aliased
26
+ across effects. Prefer `load` / `loadFromJSON` / `resolveResources` over
27
+ `resolveExternalGeometries` (kept for compatibility).
28
+
29
+ ## [0.20.0] — 2026-10-16
30
+
31
+ ### Added
32
+
33
+ - `ParticleSystem.maxParticles` (optional, no limit when unset) caps how many particles a system
34
+ keeps alive, like Unity's Max Particles: emission past the cap is dropped rather than queued.
35
+ Saved in the effect JSON only when set.
36
+ - quarks.core `BoxEmitter` (`box`) emits from the volume, faces or edges of a box, with an
37
+ optional per-axis thickness, moving particles along +Z; a box with no depth is a flat rectangle.
38
+ `EdgeEmitter` (`edge`) emits from a line along X, moving particles along +Y. Both match the
39
+ Unity shapes of the same name.
40
+
41
+ - Trail settings `uvFromHead`, `colorFromParticle`, `dieWithParticle` and `recordWorldSpace`
42
+ (all optional, off by default) for trails that behave like Unity's: the texture runs from the
43
+ particle back to the tail, the whole trail takes the particle's current color, the trail
44
+ disappears the moment its particle dies, and a local-space system lays its trail points down in
45
+ world space so they streak behind a moving emitter. Saved in the effect JSON only when switched
46
+ on.
47
+ - Emitter shapes take an optional local `transform` (`ShapeTransform`: position, rotation
48
+ quaternion, scale) like the Position / Rotation / Scale of Unity's Shape module. The spawn point
49
+ goes through scale, rotation and offset, and the start direction through scale and rotation
50
+ without changing the start speed. Every `quarks.core` shape and `MeshSurfaceEmitter` support
51
+ it; the shape JSON gets a `transform` entry only when one is set.
52
+ - `ParticleSystem.pivot` (Unity's renderer Pivot): offsets billboard and stretched billboard quads
53
+ from their particle, in particle-size units. Billboards turn the offset with the particle and
54
+ move it toward the camera by z (up, for horizontal billboards); stretched billboards measure x
55
+ from head to tail and y across. Systems with different pivots batch separately; the shaders
56
+ only compile it in (`PIVOT`) when a pivot is set.
57
+ - `ParticleSystem.flip` (Unity's renderer Flip): the fraction of billboard and stretched billboard
58
+ particles whose texture is mirrored along U and V, picked per particle at birth.
59
+ - Both are saved in the effect JSON (`pivot: [x, y, z]`, `flip: [u, v]`) only when non-zero, and
60
+ carried by `clone()`.
61
+
62
+ ### Changed
63
+
64
+ - `QuarksLoader` shares one `Texture` per scene between every effect that uses the same image with
65
+ the same sampling, and one copy of identical mesh geometry. The renderer only batches systems
66
+ that share these objects, so each loaded effect used to get batches of its own: 661 Epic Toon
67
+ FX combat effects loaded together drew 2,577 batches, and draw 180 now. Turn it off per loader
68
+ with `shareResources: false`; `QuarksLoader.clearSharedResources(scene)` forgets the shared set.
69
+
70
+ ### Fixed
71
+
72
+ - `PiecewiseBezier` and `Gradient` (`quarks.core`) resampled their 257-point lookup tables on
73
+ every refresh, which runs every simulation step for every behavior using them. The "unchanged"
74
+ check compared the control points against a `Float32Array` copy, and any value float32 can't
75
+ hold exactly (0.2, 0.3, …) never compared equal. With such curves, 1,000 systems took 22.9 ms
76
+ per frame and now take 12.7 ms.
77
+ - An idle sprite batch uploaded its cleared instance (five or six vertex buffer updates) on every
78
+ frame; it now does so once each time it goes empty. Systems with no particles are skipped when
79
+ the batch is filled, and the emitter's matrix is only fully decomposed for local-space mesh
80
+ particles.
81
+ - A trail texture now reaches the end of the ribbon on frames that draw no live tip (with
82
+ `followLocalOrigin`, while paused, or exactly on a simulation step). The newest recorded sample
83
+ stopped one segment short of the texture's end, which cut the end of the texture off and made
84
+ it pop in and out as the tip came and went.
85
+
7
86
  ## [0.17.9] — 2026-07-14
8
87
 
9
88
  ### Fixed
package/README.md CHANGED
@@ -134,6 +134,28 @@ await engine.initAsync();
134
134
 
135
135
  All render modes (billboard, stretched billboard, mesh, trail) are validated to create WebGPU pipelines with zero validation errors. The [live demos](https://soullnik.github.io/babylon.quarks-standalone/) and the [benchmark page](https://soullnik.github.io/babylon.quarks-standalone/benchmark.html) accept `?engine=webgpu` in the URL to switch engines.
136
136
 
137
+ ## Unity-style emitter options
138
+
139
+ A few optional settings mirror Shuriken so Unity exports look the same; all are off by default and
140
+ only written to the effect JSON when set.
141
+
142
+ ```ts
143
+ import {ConeEmitter, Quaternion, ShapeTransform, Vector2, Vector3} from 'quarks.core';
144
+
145
+ const system = new ParticleSystem({
146
+ // Shape module Position / Rotation / Scale: spawn points and start directions go through it.
147
+ shape: new ConeEmitter({
148
+ radius: 0.5,
149
+ transform: new ShapeTransform(new Vector3(0, 1, 0), new Quaternion(), new Vector3(2, 1, 1)),
150
+ }),
151
+ // Renderer Pivot, in particle-size units (billboards and stretched billboards).
152
+ pivot: new Vector3(0, 0.5, 0),
153
+ // Renderer Flip: mirror the texture of 50% of particles along U.
154
+ flip: new Vector2(0.5, 0),
155
+ // ...
156
+ });
157
+ ```
158
+
137
159
  ## Author & load effects
138
160
 
139
161
  Design an effect with one of these tools, then load the exported JSON with `QuarksLoader`:
@@ -148,6 +170,8 @@ import {BatchedRenderer, QuarksLoader, QuarksUtil} from 'babylon.quarks';
148
170
  const batchRenderer = new BatchedRenderer('particles', scene);
149
171
  const loader = new QuarksLoader(scene);
150
172
  const effect = await loader.load('effects/explosion.json');
173
+ // Or preload a battle pack — shared textures/geometries fetch once:
174
+ // const roots = await loader.loadAll(['fx/hit.json', 'fx/explosion.json'], { concurrency: 6 });
151
175
  QuarksUtil.addToBatchRenderer(effect, batchRenderer);
152
176
  QuarksUtil.play(effect);
153
177
  ```