hz-particles 1.0.14 → 1.2.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.
@@ -1,4 +1,4 @@
1
- class Z {
1
+ class cs {
2
2
  constructor(t = {}) {
3
3
  this.config = t, this._posOut = [0, 0, 0], this._rotMatrix = null, this._invRotMatrix = null, this._cachedRotX = void 0, this._cachedRotY = void 0, this._cachedRotZ = void 0;
4
4
  }
@@ -6,21 +6,21 @@ class Z {
6
6
  * Rebuild the cached rotation matrix if config values changed.
7
7
  */
8
8
  _updateRotationMatrix() {
9
- const t = this.config.shapeRotationX || 0, e = this.config.shapeRotationY || 0, i = this.config.shapeRotationZ || 0;
9
+ const t = this.config.emissionRotationX || 0, e = this.config.emissionRotationY || 0, i = this.config.emissionRotationZ || 0;
10
10
  if (t === this._cachedRotX && e === this._cachedRotY && i === this._cachedRotZ)
11
11
  return;
12
12
  this._cachedRotX = t, this._cachedRotY = e, this._cachedRotZ = i;
13
- const a = t * Math.PI / 180, r = e * Math.PI / 180, n = i * Math.PI / 180, o = Math.cos(a), s = Math.sin(a), l = Math.cos(r), u = Math.sin(r), d = Math.cos(n), f = Math.sin(n);
13
+ const s = t * Math.PI / 180, n = e * Math.PI / 180, o = i * Math.PI / 180, a = Math.cos(s), c = Math.sin(s), l = Math.cos(n), u = Math.sin(n), f = Math.cos(o), h = Math.sin(o);
14
14
  this._rotMatrix = [
15
- l * d,
16
- s * u * d - o * f,
17
- o * u * d + s * f,
18
15
  l * f,
19
- s * u * f + o * d,
20
- o * u * f - s * d,
16
+ c * u * f - a * h,
17
+ a * u * f + c * h,
18
+ l * h,
19
+ c * u * h + a * f,
20
+ a * u * h - c * f,
21
21
  -u,
22
- s * l,
23
- o * l
22
+ c * l,
23
+ a * l
24
24
  ], this._invRotMatrix = [
25
25
  this._rotMatrix[0],
26
26
  this._rotMatrix[3],
@@ -34,90 +34,90 @@ class Z {
34
34
  ];
35
35
  }
36
36
  emitParticle(t, e, i) {
37
- const a = this._posOut;
38
- if (this.config.emissionShape === "cube" ? this._emitFromCube(a) : this.config.emissionShape === "sphere" ? this._emitFromSphere(a) : this.config.emissionShape === "square" ? this._emitFromSquare(a) : this.config.emissionShape === "circle" ? this._emitFromCircle(a) : this.config.emissionShape === "cylinder" ? this._emitFromCylinder(a) : this.config.emissionShape === "plain" ? this._emitFromPlain(a) : this.config.emissionShape === "cone" ? this._emitFromCone(a) : this.config.emissionShape === "torus" ? this._emitFromTorus(a) : this.config.emissionShape === "line" ? this._emitFromLine(a) : this.config.emissionShape === "hemisphere" ? this._emitFromHemisphere(a) : this.config.emissionShape === "disc" ? this._emitFromDisc(a) : this.config.emissionShape === "annulus" ? this._emitFromAnnulus(a) : this.config.emissionShape === "capsule" ? this._emitFromCapsule(a) : this.config.emissionShape === "arc" ? this._emitFromArc(a) : this.config.emissionShape === "spiral" ? this._emitFromSpiral(a) : this.config.emissionShape === "frustum" ? this._emitFromFrustum(a) : this.config.emissionShape === "cubeSurface" ? this._emitFromCubeSurface(a) : this.config.emissionShape === "sphereSurface" ? this._emitFromSphereSurface(a) : this.config.emissionShape === "boxFrame" ? this._emitFromBoxFrame(a) : this.config.emissionShape === "polygon" ? this._emitFromPolygon(a) : (a[0] = 0, a[1] = 0, a[2] = 0), this.config.shapeRotationX || this.config.shapeRotationY || this.config.shapeRotationZ) {
37
+ const s = this._posOut;
38
+ if (this.config.emissionShape === "cube" || this.config.emissionShape === "box" ? this._emitFromCube(s) : this.config.emissionShape === "sphere" ? this._emitFromSphere(s) : this.config.emissionShape === "square" ? this._emitFromSquare(s) : this.config.emissionShape === "circle" ? this._emitFromCircle(s) : this.config.emissionShape === "cylinder" ? this._emitFromCylinder(s) : this.config.emissionShape === "plain" ? this._emitFromPlain(s) : this.config.emissionShape === "cone" ? this._emitFromCone(s) : this.config.emissionShape === "torus" ? this._emitFromTorus(s) : this.config.emissionShape === "line" ? this._emitFromLine(s) : this.config.emissionShape === "hemisphere" ? this._emitFromHemisphere(s) : this.config.emissionShape === "disc" ? this._emitFromDisc(s) : this.config.emissionShape === "annulus" ? this._emitFromAnnulus(s) : this.config.emissionShape === "capsule" ? this._emitFromCapsule(s) : this.config.emissionShape === "arc" ? this._emitFromArc(s) : this.config.emissionShape === "spiral" ? this._emitFromSpiral(s) : this.config.emissionShape === "frustum" ? this._emitFromFrustum(s) : this.config.emissionShape === "cubeSurface" ? this._emitFromCubeSurface(s) : this.config.emissionShape === "sphereSurface" ? this._emitFromSphereSurface(s) : this.config.emissionShape === "boxFrame" ? this._emitFromBoxFrame(s) : this.config.emissionShape === "polygon" ? this._emitFromPolygon(s) : this.config.emissionShape === "rectangle" ? this._emitFromRectangle(s) : (s[0] = 0, s[1] = 0, s[2] = 0), this.config.emissionRotationX || this.config.emissionRotationY || this.config.emissionRotationZ) {
39
39
  this._updateRotationMatrix();
40
- const o = this._rotMatrix, s = a[0], l = a[1], u = a[2];
41
- a[0] = o[0] * s + o[1] * l + o[2] * u, a[1] = o[3] * s + o[4] * l + o[5] * u, a[2] = o[6] * s + o[7] * l + o[8] * u;
40
+ const a = this._rotMatrix, c = s[0], l = s[1], u = s[2];
41
+ s[0] = a[0] * c + a[1] * l + a[2] * u, s[1] = a[3] * c + a[4] * l + a[5] * u, s[2] = a[6] * c + a[7] * l + a[8] * u;
42
42
  }
43
- (this.config.shapeTranslationX || this.config.shapeTranslationY || this.config.shapeTranslationZ) && (a[0] += this.config.shapeTranslationX || 0, a[1] += this.config.shapeTranslationY || 0, a[2] += this.config.shapeTranslationZ || 0);
44
- const r = e * 8;
45
- t[r] = a[0], t[r + 1] = a[1], t[r + 2] = a[2];
46
- const n = e * 4;
47
- this.calculateVelocity(a[0], a[1], a[2], i, n), this.setParticleColor(t, r), this.setParticleLifetime(t, r);
43
+ (this.config.emissionPositionX || this.config.emissionPositionY || this.config.emissionPositionZ) && (s[0] += this.config.emissionPositionX || 0, s[1] += this.config.emissionPositionY || 0, s[2] += this.config.emissionPositionZ || 0);
44
+ const n = e * 8;
45
+ t[n] = s[0], t[n + 1] = s[1], t[n + 2] = s[2];
46
+ const o = e * 4;
47
+ this.calculateVelocity(s[0], s[1], s[2], i, o), this.setParticleColor(t, n), this.setParticleLifetime(t, n);
48
48
  }
49
49
  // Apply rotation using cached matrix
50
50
  applyRotation(t, e, i) {
51
51
  this._updateRotationMatrix();
52
- const a = this._rotMatrix;
52
+ const s = this._rotMatrix;
53
53
  return [
54
- a[0] * t + a[1] * e + a[2] * i,
55
- a[3] * t + a[4] * e + a[5] * i,
56
- a[6] * t + a[7] * e + a[8] * i
54
+ s[0] * t + s[1] * e + s[2] * i,
55
+ s[3] * t + s[4] * e + s[5] * i,
56
+ s[6] * t + s[7] * e + s[8] * i
57
57
  ];
58
58
  }
59
59
  // Apply inverse rotation using cached matrix
60
60
  inverseRotation(t, e, i) {
61
61
  this._updateRotationMatrix();
62
- const a = this._invRotMatrix;
62
+ const s = this._invRotMatrix;
63
63
  return [
64
- a[0] * t + a[1] * e + a[2] * i,
65
- a[3] * t + a[4] * e + a[5] * i,
66
- a[6] * t + a[7] * e + a[8] * i
64
+ s[0] * t + s[1] * e + s[2] * i,
65
+ s[3] * t + s[4] * e + s[5] * i,
66
+ s[6] * t + s[7] * e + s[8] * i
67
67
  ];
68
68
  }
69
69
  _emitFromCube(t) {
70
70
  let e = this.config.innerLength || 0, i = this.config.outerLength || this.config.cubeLength;
71
71
  if (e > 0) {
72
- const a = Math.floor(Math.random() * 6), r = Math.random() - 0.5, n = Math.random() - 0.5;
73
- let o, s, l;
74
- switch (a) {
72
+ const s = Math.floor(Math.random() * 6), n = Math.random() - 0.5, o = Math.random() - 0.5;
73
+ let a, c, l;
74
+ switch (s) {
75
75
  case 0:
76
- o = r, s = n, l = 0.5;
76
+ a = n, c = o, l = 0.5;
77
77
  break;
78
78
  case 1:
79
- o = r, s = n, l = -0.5;
79
+ a = n, c = o, l = -0.5;
80
80
  break;
81
81
  case 2:
82
- o = 0.5, s = r, l = n;
82
+ a = 0.5, c = n, l = o;
83
83
  break;
84
84
  case 3:
85
- o = -0.5, s = r, l = n;
85
+ a = -0.5, c = n, l = o;
86
86
  break;
87
87
  case 4:
88
- o = r, s = 0.5, l = n;
88
+ a = n, c = 0.5, l = o;
89
89
  break;
90
90
  case 5:
91
- o = r, s = -0.5, l = n;
91
+ a = n, c = -0.5, l = o;
92
92
  break;
93
93
  }
94
- const u = Math.random(), d = e + u * (i - e);
95
- t[0] = o * d, t[1] = s * d, t[2] = l * d;
94
+ const u = Math.random(), f = e + u * (i - e);
95
+ t[0] = a * f, t[1] = c * f, t[2] = l * f;
96
96
  } else
97
97
  t[0] = (Math.random() - 0.5) * i, t[1] = (Math.random() - 0.5) * i, t[2] = (Math.random() - 0.5) * i;
98
98
  }
99
99
  _emitFromSphere(t) {
100
- const e = Math.random() * 2 * Math.PI, i = Math.acos(2 * Math.random() - 1), a = Math.sin(i) * Math.cos(e), r = Math.sin(i) * Math.sin(e), n = Math.cos(i);
101
- let o;
102
- this.config.innerRadius === 0 ? o = this.config.outerRadius * Math.cbrt(Math.random()) : o = this.config.innerRadius + (this.config.outerRadius - this.config.innerRadius) * Math.random(), t[0] = a * o, t[1] = r * o, t[2] = n * o;
100
+ const e = Math.random() * 2 * Math.PI, i = Math.acos(2 * Math.random() - 1), s = Math.sin(i) * Math.cos(e), n = Math.sin(i) * Math.sin(e), o = Math.cos(i);
101
+ let a;
102
+ this.config.innerRadius === 0 ? a = this.config.outerRadius * Math.cbrt(Math.random()) : a = this.config.innerRadius + (this.config.outerRadius - this.config.innerRadius) * Math.random(), t[0] = s * a, t[1] = n * a, t[2] = o * a;
103
103
  }
104
104
  _emitFromSquare(t) {
105
105
  const e = this.config.squareInnerSize || 0, i = this.config.squareSize || 2;
106
106
  if (e > 0) {
107
- const a = Math.floor(Math.random() * 4);
108
- let r = e + (i - e) * Math.random();
109
- switch (a) {
107
+ const s = Math.floor(Math.random() * 4);
108
+ let n = e + (i - e) * Math.random();
109
+ switch (s) {
110
110
  case 0:
111
- t[0] = (Math.random() * 2 - 1) * r, t[1] = r;
111
+ t[0] = (Math.random() * 2 - 1) * n, t[1] = n;
112
112
  break;
113
113
  case 1:
114
- t[0] = r, t[1] = (Math.random() * 2 - 1) * r;
114
+ t[0] = n, t[1] = (Math.random() * 2 - 1) * n;
115
115
  break;
116
116
  case 2:
117
- t[0] = (Math.random() * 2 - 1) * r, t[1] = -r;
117
+ t[0] = (Math.random() * 2 - 1) * n, t[1] = -n;
118
118
  break;
119
119
  case 3:
120
- t[0] = -r, t[1] = (Math.random() * 2 - 1) * r;
120
+ t[0] = -n, t[1] = (Math.random() * 2 - 1) * n;
121
121
  break;
122
122
  }
123
123
  } else
@@ -125,153 +125,157 @@ class Z {
125
125
  t[2] = 0;
126
126
  }
127
127
  _emitFromCircle(t) {
128
- const e = this.config.circleInnerRadius || 0, i = this.config.circleOuterRadius || 2, a = Math.random() * Math.PI * 2;
129
- let r;
130
- e > 0 ? r = e + (i - e) * Math.random() : r = i * Math.sqrt(Math.random()), t[0] = Math.cos(a) * r, t[1] = Math.sin(a) * r, t[2] = 0;
128
+ const e = this.config.circleInnerRadius || 0, i = this.config.circleOuterRadius || 2, s = Math.random() * Math.PI * 2;
129
+ let n;
130
+ e > 0 ? n = e + (i - e) * Math.random() : n = i * Math.sqrt(Math.random()), t[0] = Math.cos(s) * n, t[1] = Math.sin(s) * n, t[2] = 0;
131
131
  }
132
132
  _emitFromPlain(t) {
133
133
  const e = this.config.planeWidth || 2, i = this.config.planeDepth || 2;
134
134
  t[0] = (Math.random() - 0.5) * e, t[1] = 0, t[2] = (Math.random() - 0.5) * i;
135
135
  }
136
136
  _emitFromCone(t) {
137
- const e = this.config.coneInnerRadius || 0, i = this.config.coneOuterRadius || 2, a = this.config.coneHeight || 4, r = Math.random() * Math.PI * 2, n = Math.random(), o = n * a, s = i * (1 - n);
137
+ const e = this.config.coneInnerRadius || 0, i = this.config.coneOuterRadius || 2, s = this.config.coneHeight || 4, n = Math.random() * Math.PI * 2, o = Math.random(), a = o * s, c = i * (1 - o);
138
138
  let l;
139
139
  if (e > 0) {
140
- const u = e * (1 - n);
141
- l = u + (s - u) * Math.random();
140
+ const u = e * (1 - o);
141
+ l = u + (c - u) * Math.random();
142
142
  } else
143
- l = s * Math.sqrt(Math.random());
144
- t[0] = Math.cos(r) * l, t[1] = o, t[2] = Math.sin(r) * l;
143
+ l = c * Math.sqrt(Math.random());
144
+ t[0] = Math.cos(n) * l, t[1] = a, t[2] = Math.sin(n) * l;
145
145
  }
146
146
  _emitFromTorus(t) {
147
- const e = this.config.torusMajorRadius || 2, i = this.config.torusMinorRadius || 0.5, a = Math.random() * Math.PI * 2, r = Math.random() * Math.PI * 2, n = i * Math.sqrt(Math.random());
148
- t[0] = (e + n * Math.cos(r)) * Math.cos(a), t[1] = n * Math.sin(r), t[2] = (e + n * Math.cos(r)) * Math.sin(a);
147
+ const e = this.config.torusMajorRadius || 2, i = this.config.torusMinorRadius || 0.5, s = Math.random() * Math.PI * 2, n = Math.random() * Math.PI * 2, o = i * Math.sqrt(Math.random());
148
+ t[0] = (e + o * Math.cos(n)) * Math.cos(s), t[1] = o * Math.sin(n), t[2] = (e + o * Math.cos(n)) * Math.sin(s);
149
149
  }
150
150
  _emitFromLine(t) {
151
151
  const e = this.config.lineLength || 4, i = Math.random();
152
152
  t[0] = 0, t[1] = (i - 0.5) * e, t[2] = 0;
153
153
  }
154
154
  _emitFromHemisphere(t) {
155
- const e = this.config.hemisphereInnerRadius || 0, i = this.config.hemisphereOuterRadius || 2, a = Math.random() * Math.PI * 2, r = Math.acos(Math.random()), n = Math.sin(r) * Math.cos(a), o = Math.cos(r), s = Math.sin(r) * Math.sin(a);
155
+ const e = this.config.hemisphereInnerRadius || 0, i = this.config.hemisphereOuterRadius || 2, s = Math.random() * Math.PI * 2, n = Math.acos(Math.random()), o = Math.sin(n) * Math.cos(s), a = Math.cos(n), c = Math.sin(n) * Math.sin(s);
156
156
  let l;
157
- e > 0 ? l = e + (i - e) * Math.random() : l = i * Math.cbrt(Math.random()), t[0] = n * l, t[1] = o * l, t[2] = s * l;
157
+ e > 0 ? l = e + (i - e) * Math.random() : l = i * Math.cbrt(Math.random()), t[0] = o * l, t[1] = a * l, t[2] = c * l;
158
158
  }
159
159
  _emitFromDisc(t) {
160
- const e = this.config.discRadius || 2, i = Math.random() * Math.PI * 2, a = e * Math.sqrt(Math.random());
161
- t[0] = Math.cos(i) * a, t[1] = 0, t[2] = Math.sin(i) * a;
160
+ const e = this.config.discRadius || 2, i = Math.random() * Math.PI * 2, s = e * Math.sqrt(Math.random());
161
+ t[0] = Math.cos(i) * s, t[1] = 0, t[2] = Math.sin(i) * s;
162
162
  }
163
163
  _emitFromAnnulus(t) {
164
- const e = this.config.annulusInnerRadius || 1, i = this.config.annulusOuterRadius || 2, a = Math.random() * Math.PI * 2, r = e + (i - e) * Math.random();
165
- t[0] = Math.cos(a) * r, t[1] = 0, t[2] = Math.sin(a) * r;
164
+ const e = this.config.annulusInnerRadius || 1, i = this.config.annulusOuterRadius || 2, s = Math.random() * Math.PI * 2, n = e + (i - e) * Math.random();
165
+ t[0] = Math.cos(s) * n, t[1] = 0, t[2] = Math.sin(s) * n;
166
166
  }
167
167
  _emitFromCapsule(t) {
168
- const e = this.config.capsuleRadius || 0.5, i = this.config.capsuleHeight || 4, a = i * 0.5, r = Math.PI * e * e * i, n = 4 / 3 * Math.PI * e * e * e, o = r / (r + n);
169
- if (Math.random() < o) {
170
- const s = Math.random() * Math.PI * 2, l = e * Math.sqrt(Math.random());
171
- t[0] = Math.cos(s) * l, t[1] = (Math.random() - 0.5) * i, t[2] = Math.sin(s) * l;
168
+ const e = this.config.capsuleRadius || 0.5, i = this.config.capsuleHeight || 4, s = i * 0.5, n = Math.PI * e * e * i, o = 4 / 3 * Math.PI * e * e * e, a = n / (n + o);
169
+ if (Math.random() < a) {
170
+ const c = Math.random() * Math.PI * 2, l = e * Math.sqrt(Math.random());
171
+ t[0] = Math.cos(c) * l, t[1] = (Math.random() - 0.5) * i, t[2] = Math.sin(c) * l;
172
172
  } else {
173
- const s = Math.random() * Math.PI * 2, l = Math.acos(2 * Math.random() - 1), u = e * Math.cbrt(Math.random());
174
- t[0] = u * Math.sin(l) * Math.cos(s), t[1] = u * Math.cos(l), t[2] = u * Math.sin(l) * Math.sin(s), t[1] += t[1] >= 0 ? a : -a;
173
+ const c = Math.random() * Math.PI * 2, l = Math.acos(2 * Math.random() - 1), u = e * Math.cbrt(Math.random());
174
+ t[0] = u * Math.sin(l) * Math.cos(c), t[1] = u * Math.cos(l), t[2] = u * Math.sin(l) * Math.sin(c), t[1] += t[1] >= 0 ? s : -s;
175
175
  }
176
176
  }
177
177
  _emitFromArc(t) {
178
- const e = this.config.arcStartAngle || 0, i = this.config.arcEndAngle || 180, a = this.config.arcInnerRadius || 0, r = this.config.arcOuterRadius || 2, n = e * Math.PI / 180, o = i * Math.PI / 180, s = n + Math.random() * (o - n);
178
+ const e = this.config.arcStartAngle || 0, i = this.config.arcEndAngle || 180, s = this.config.arcInnerRadius || 0, n = this.config.arcOuterRadius || 2, o = e * Math.PI / 180, a = i * Math.PI / 180, c = o + Math.random() * (a - o);
179
179
  let l;
180
- a > 0 ? l = a + (r - a) * Math.random() : l = r * Math.sqrt(Math.random()), t[0] = Math.cos(s) * l, t[1] = Math.sin(s) * l, t[2] = 0;
180
+ s > 0 ? l = s + (n - s) * Math.random() : l = n * Math.sqrt(Math.random()), t[0] = Math.cos(c) * l, t[1] = Math.sin(c) * l, t[2] = 0;
181
181
  }
182
182
  _emitFromSpiral(t) {
183
- const e = this.config.spiralTurns || 3, i = this.config.spiralRadiusStart || 0.5, a = this.config.spiralRadiusEnd || 2, r = this.config.spiralHeight || 4, n = Math.random(), o = n * e * Math.PI * 2, s = i + (a - i) * n;
184
- t[0] = Math.cos(o) * s, t[1] = (n - 0.5) * r, t[2] = Math.sin(o) * s;
183
+ const e = this.config.spiralTurns || 3, i = this.config.spiralRadiusStart || 0.5, s = this.config.spiralRadiusEnd || 2, n = this.config.spiralHeight || 4, o = Math.random(), a = o * e * Math.PI * 2, c = i + (s - i) * o;
184
+ t[0] = Math.cos(a) * c, t[1] = (o - 0.5) * n, t[2] = Math.sin(a) * c;
185
185
  }
186
186
  _emitFromFrustum(t) {
187
- const e = this.config.frustumRadiusNear || 0.5, i = this.config.frustumRadiusFar || 2, a = this.config.frustumHeight || 4, r = Math.random() * Math.PI * 2, n = Math.random(), o = n * a, l = (e + (i - e) * n) * Math.sqrt(Math.random());
188
- t[0] = Math.cos(r) * l, t[1] = o, t[2] = Math.sin(r) * l;
187
+ const e = this.config.frustumRadiusNear || 0.5, i = this.config.frustumRadiusFar || 2, s = this.config.frustumHeight || 4, n = Math.random() * Math.PI * 2, o = Math.random(), a = o * s, l = (e + (i - e) * o) * Math.sqrt(Math.random());
188
+ t[0] = Math.cos(n) * l, t[1] = a, t[2] = Math.sin(n) * l;
189
189
  }
190
190
  _emitFromCubeSurface(t) {
191
- const e = this.config.cubeSurfaceSize || 2, i = e * 0.5, a = Math.floor(Math.random() * 6), r = (Math.random() - 0.5) * e, n = (Math.random() - 0.5) * e;
192
- switch (a) {
191
+ const e = this.config.cubeSurfaceSize || 2, i = e * 0.5, s = Math.floor(Math.random() * 6), n = (Math.random() - 0.5) * e, o = (Math.random() - 0.5) * e;
192
+ switch (s) {
193
193
  case 0:
194
- t[0] = r, t[1] = n, t[2] = i;
194
+ t[0] = n, t[1] = o, t[2] = i;
195
195
  break;
196
196
  case 1:
197
- t[0] = r, t[1] = n, t[2] = -i;
197
+ t[0] = n, t[1] = o, t[2] = -i;
198
198
  break;
199
199
  case 2:
200
- t[0] = i, t[1] = r, t[2] = n;
200
+ t[0] = i, t[1] = n, t[2] = o;
201
201
  break;
202
202
  case 3:
203
- t[0] = -i, t[1] = r, t[2] = n;
203
+ t[0] = -i, t[1] = n, t[2] = o;
204
204
  break;
205
205
  case 4:
206
- t[0] = r, t[1] = i, t[2] = n;
206
+ t[0] = n, t[1] = i, t[2] = o;
207
207
  break;
208
208
  case 5:
209
- t[0] = r, t[1] = -i, t[2] = n;
209
+ t[0] = n, t[1] = -i, t[2] = o;
210
210
  break;
211
211
  }
212
212
  }
213
213
  _emitFromSphereSurface(t) {
214
- const e = this.config.sphereSurfaceRadius || 2, i = Math.random() * Math.PI * 2, a = Math.acos(2 * Math.random() - 1);
215
- t[0] = e * Math.sin(a) * Math.cos(i), t[1] = e * Math.sin(a) * Math.sin(i), t[2] = e * Math.cos(a);
214
+ const e = this.config.sphereSurfaceRadius || 2, i = Math.random() * Math.PI * 2, s = Math.acos(2 * Math.random() - 1);
215
+ t[0] = e * Math.sin(s) * Math.cos(i), t[1] = e * Math.sin(s) * Math.sin(i), t[2] = e * Math.cos(s);
216
216
  }
217
217
  _emitFromBoxFrame(t) {
218
- const e = this.config.boxFrameSize || 2, i = e * 0.5, a = Math.floor(Math.random() * 12), n = (Math.random() - 0.5) * e, o = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
219
- if (a < 4) {
220
- const [s, l] = o[a];
221
- t[0] = n, t[1] = s * i, t[2] = l * i;
222
- } else if (a < 8) {
223
- const [s, l] = o[a - 4];
224
- t[0] = s * i, t[1] = n, t[2] = l * i;
218
+ const e = this.config.boxFrameSize || 2, i = e * 0.5, s = Math.floor(Math.random() * 12), o = (Math.random() - 0.5) * e, a = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
219
+ if (s < 4) {
220
+ const [c, l] = a[s];
221
+ t[0] = o, t[1] = c * i, t[2] = l * i;
222
+ } else if (s < 8) {
223
+ const [c, l] = a[s - 4];
224
+ t[0] = c * i, t[1] = o, t[2] = l * i;
225
225
  } else {
226
- const [s, l] = o[a - 8];
227
- t[0] = s * i, t[1] = l * i, t[2] = n;
226
+ const [c, l] = a[s - 8];
227
+ t[0] = c * i, t[1] = l * i, t[2] = o;
228
228
  }
229
229
  }
230
230
  _emitFromPolygon(t) {
231
- const e = Math.max(3, Math.floor(this.config.polygonSides || 6)), i = this.config.polygonRadius || 2, a = Math.floor(Math.random() * e), r = a / e * Math.PI * 2, n = (a + 1) / e * Math.PI * 2;
232
- let o = Math.random(), s = Math.random();
233
- o + s > 1 && (o = 1 - o, s = 1 - s);
234
- const l = o * Math.cos(r) + s * Math.cos(n), u = o * Math.sin(r) + s * Math.sin(n);
231
+ const e = Math.max(3, Math.floor(this.config.polygonSides || 6)), i = this.config.polygonRadius || 2, s = Math.floor(Math.random() * e), n = s / e * Math.PI * 2, o = (s + 1) / e * Math.PI * 2;
232
+ let a = Math.random(), c = Math.random();
233
+ a + c > 1 && (a = 1 - a, c = 1 - c);
234
+ const l = a * Math.cos(n) + c * Math.cos(o), u = a * Math.sin(n) + c * Math.sin(o);
235
235
  t[0] = l * i, t[1] = u * i, t[2] = 0;
236
236
  }
237
+ _emitFromRectangle(t) {
238
+ const e = this.config.rectangleWidth || 2, i = this.config.rectangleHeight || 2;
239
+ t[0] = (Math.random() - 0.5) * e, t[1] = (Math.random() - 0.5) * i, t[2] = 0;
240
+ }
237
241
  _emitFromCylinder(t) {
238
- const e = this.config.cylinderInnerRadius || 0, i = this.config.cylinderOuterRadius || 2, a = this.config.cylinderHeight || 4, r = Math.random() * Math.PI * 2;
239
- let n;
240
- e > 0 ? n = e + (i - e) * Math.random() : n = i * Math.sqrt(Math.random()), t[0] = Math.cos(r) * n, t[1] = (Math.random() - 0.5) * a, t[2] = Math.sin(r) * n;
242
+ const e = this.config.cylinderInnerRadius || 0, i = this.config.cylinderOuterRadius || 2, s = this.config.cylinderHeight || 4, n = Math.random() * Math.PI * 2;
243
+ let o;
244
+ e > 0 ? o = e + (i - e) * Math.random() : o = i * Math.sqrt(Math.random()), t[0] = Math.cos(n) * o, t[1] = (Math.random() - 0.5) * s, t[2] = Math.sin(n) * o;
241
245
  }
242
- calculateVelocity(t, e, i, a, r) {
243
- const n = this.config.shapeTranslationX || 0, o = this.config.shapeTranslationY || 0, s = this.config.shapeTranslationZ || 0, l = t - n, u = e - o, d = i - s, f = Math.sqrt(l * l + u * u + d * d);
244
- let h, p, m;
245
- if (f > 1e-4) {
246
- let S = !1;
246
+ calculateVelocity(t, e, i, s, n) {
247
+ const o = this.config.emissionPositionX || 0, a = this.config.emissionPositionY || 0, c = this.config.emissionPositionZ || 0, l = t - o, u = e - a, f = i - c, h = Math.sqrt(l * l + u * u + f * f);
248
+ let m, S, R;
249
+ if (h > 1e-4) {
250
+ let C = !1;
247
251
  if (this.config.emissionShape === "circle" && this.config.circleVelocityDirection === "tangential") {
248
- const y = this.inverseRotation(l, u, d), P = Math.sqrt(y[0] * y[0] + y[1] * y[1]);
249
- if (P > 1e-4) {
250
- const g = -y[1] / P, x = y[0] / P, M = this.applyRotation(g, x, 0);
251
- h = M[0], p = M[1], m = M[2], S = !0;
252
+ const B = this.inverseRotation(l, u, f), A = Math.sqrt(B[0] * B[0] + B[1] * B[1]);
253
+ if (A > 1e-4) {
254
+ const P = -B[1] / A, _ = B[0] / A, T = this.applyRotation(P, _, 0);
255
+ m = T[0], S = T[1], R = T[2], C = !0;
252
256
  }
253
257
  } else if (this.config.emissionShape === "cylinder" && this.config.cylinderVelocityDirection === "tangential") {
254
- const y = this.inverseRotation(l, u, d), P = Math.sqrt(y[0] * y[0] + y[2] * y[2]);
255
- if (P > 1e-4) {
256
- const g = -y[2] / P, x = y[0] / P, M = this.applyRotation(g, 0, x);
257
- h = M[0], p = M[1], m = M[2], S = !0;
258
+ const B = this.inverseRotation(l, u, f), A = Math.sqrt(B[0] * B[0] + B[2] * B[2]);
259
+ if (A > 1e-4) {
260
+ const P = -B[2] / A, _ = B[0] / A, T = this.applyRotation(P, 0, _);
261
+ m = T[0], S = T[1], R = T[2], C = !0;
258
262
  } else {
259
- const g = Math.random() * Math.PI * 2, x = this.applyRotation(Math.cos(g), 0, Math.sin(g));
260
- h = x[0], p = x[1], m = x[2], S = !0;
263
+ const P = Math.random() * Math.PI * 2, _ = this.applyRotation(Math.cos(P), 0, Math.sin(P));
264
+ m = _[0], S = _[1], R = _[2], C = !0;
261
265
  }
262
266
  }
263
- S || (h = l / f, p = u / f, m = d / f);
267
+ C || (m = l / h, S = u / h, R = f / h);
264
268
  } else {
265
- const S = Math.random() * Math.PI * 2, y = Math.acos(2 * Math.random() - 1);
266
- h = Math.sin(y) * Math.cos(S), p = Math.sin(y) * Math.sin(S), m = Math.cos(y);
269
+ const C = Math.random() * Math.PI * 2, B = Math.acos(2 * Math.random() - 1);
270
+ m = Math.sin(B) * Math.cos(C), S = Math.sin(B) * Math.sin(C), R = Math.cos(B);
267
271
  }
268
- let b;
269
- this.config.randomSpeed ? b = (this.config.minSpeed || 0) + Math.random() * ((this.config.maxSpeed || 1) - (this.config.minSpeed || 0)) : b = this.config.particleSpeed, a[r] = this.config.overrideXVelocity ? this.config.xVelocity : h * b, a[r + 1] = this.config.overrideYVelocity ? this.config.yVelocity : p * b, a[r + 2] = this.config.overrideZVelocity ? this.config.zVelocity : m * b, a[r + 3] = 0;
272
+ let D;
273
+ this.config.randomSpeed ? D = (this.config.minSpeed || 0) + Math.random() * ((this.config.maxSpeed || 1) - (this.config.minSpeed || 0)) : D = this.config.particleSpeed, s[n] = this.config.overrideXVelocity ? this.config.xVelocity : m * D, s[n + 1] = this.config.overrideYVelocity ? this.config.yVelocity : S * D, s[n + 2] = this.config.overrideZVelocity ? this.config.zVelocity : R * D, s[n + 3] = 0;
270
274
  }
271
275
  setParticleColor(t, e) {
272
276
  if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
273
- const i = this.config.randomColors, a = i[Math.floor(Math.random() * i.length)];
274
- t[e + 3] = a[0], t[e + 4] = a[1], t[e + 5] = a[2];
277
+ const i = this.config.randomColors, s = i[Math.floor(Math.random() * i.length)];
278
+ t[e + 3] = s[0], t[e + 4] = s[1], t[e + 5] = s[2];
275
279
  } else this.config.colorTransitionEnabled ? (t[e + 3] = this.config.startColor[0], t[e + 4] = this.config.startColor[1], t[e + 5] = this.config.startColor[2]) : (t[e + 3] = this.config.particleColor[0], t[e + 4] = this.config.particleColor[1], t[e + 5] = this.config.particleColor[2]);
276
280
  }
277
281
  setParticleLifetime(t, e) {
@@ -279,7 +283,7 @@ class Z {
279
283
  t[e + 6] = 0, t[e + 7] = i + (Math.random() * 0.4 - 0.2) * i;
280
284
  }
281
285
  }
282
- class q {
286
+ class us {
283
287
  constructor(t, e = 1e4) {
284
288
  this.device = t, this.physicsSettings = {
285
289
  deltaTime: 0.016,
@@ -321,17 +325,25 @@ class q {
321
325
  size: e * 4 * 4,
322
326
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
323
327
  label: "RenderReadback_Velocity"
324
- }), this._renderStagingInUse = !1;
328
+ }), this._renderStagingInUse = !1, this._scriptStagingParticleBuffer = t.createBuffer({
329
+ size: e * 8 * 4,
330
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
331
+ label: "ScriptReadback_ParticleData"
332
+ }), this._scriptStagingVelocityBuffer = t.createBuffer({
333
+ size: e * 4 * 4,
334
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
335
+ label: "ScriptReadback_Velocity"
336
+ }), this._scriptStagingInUse = !1;
325
337
  }
326
338
  async initComputePipeline(t, e, i) {
327
339
  try {
328
340
  return await this.createComputePipeline(t, e, i), this.computeReady = !0, !0;
329
- } catch (a) {
330
- return console.error("Error initializing compute pipeline:", a), !1;
341
+ } catch (s) {
342
+ return console.error("Error initializing compute pipeline:", s), !1;
331
343
  }
332
344
  }
333
345
  async createComputePipeline(t, e, i) {
334
- const { particlePhysicsShader: a } = await Promise.resolve().then(() => Y);
346
+ const { particlePhysicsShader: s } = await Promise.resolve().then(() => _i);
335
347
  this.computeBindGroupLayout = this.device.createBindGroupLayout({
336
348
  entries: [
337
349
  {
@@ -361,7 +373,7 @@ class q {
361
373
  }),
362
374
  compute: {
363
375
  module: this.device.createShaderModule({
364
- code: a
376
+ code: s
365
377
  }),
366
378
  entryPoint: "main"
367
379
  }
@@ -387,49 +399,49 @@ class q {
387
399
  ]
388
400
  });
389
401
  }
390
- updatePhysics(t, e, i, a, r, n) {
402
+ updatePhysics(t, e, i, s, n, o) {
391
403
  if (e <= 0 || !this.computeReady)
392
404
  return;
393
- const o = this._physicsData, s = this.physicsSettings;
394
- o[0] = t, o[1] = i.particleSpeed, o[2] = s.gravity, o[3] = s.turbulence, o[4] = s.attractorStrength, o[5] = s.damping, o[6] = s.attractorPosition[0], o[7] = s.attractorPosition[1], o[8] = s.attractorPosition[2], this._physicsDataU32View[9] = e, o[10] = s.confinementEnabled ? 1 : 0, o[11] = s.confinementShape === "sphere" ? 1 : 0, o[12] = s.confinementMode === "kill" ? 1 : 0, o[13] = s.confinementSpace === "local" ? 1 : 0, o[14] = s.confinementBoxHalfSize[0], o[15] = s.confinementBoxHalfSize[1], o[16] = s.confinementBoxHalfSize[2], o[17] = s.confinementSphereRadius, o[18] = s.confinementRestitution, o[19] = s.confinementFriction, o[20] = s.confinementCenter[0], o[21] = s.confinementCenter[1], o[22] = s.confinementCenter[2], o[23] = s.softBoundaryEnabled ? 1 : 0, o[24] = s.softBoundaryStrength, o[25] = s.softBoundaryFalloff, o[26] = i.velocityStretchEnabled ? 1 : 0, o[27] = i.velocityStretchFactor ?? 1, o[28] = 0, o[29] = 0, o[30] = 0, o[31] = 0, this.device.queue.writeBuffer(this.physicsUniformBuffer, 0, o);
395
- const l = n || this.device.createCommandEncoder({ label: "ParticlePhysicsEncoder" }), u = l.beginComputePass({ label: "ParticlePhysicsPass" });
405
+ const a = this._physicsData, c = this.physicsSettings;
406
+ a[0] = t, a[1] = i.particleSpeed, a[2] = c.gravity, a[3] = c.turbulence, a[4] = c.attractorStrength, a[5] = c.damping, a[6] = c.attractorPosition[0], a[7] = c.attractorPosition[1], a[8] = c.attractorPosition[2], this._physicsDataU32View[9] = e, a[10] = c.confinementEnabled ? 1 : 0, a[11] = c.confinementShape === "sphere" ? 1 : 0, a[12] = c.confinementMode === "kill" ? 1 : 0, a[13] = c.confinementSpace === "local" ? 1 : 0, a[14] = c.confinementBoxHalfSize[0], a[15] = c.confinementBoxHalfSize[1], a[16] = c.confinementBoxHalfSize[2], a[17] = c.confinementSphereRadius, a[18] = c.confinementRestitution, a[19] = c.confinementFriction, a[20] = c.confinementCenter[0], a[21] = c.confinementCenter[1], a[22] = c.confinementCenter[2], a[23] = c.softBoundaryEnabled ? 1 : 0, a[24] = c.softBoundaryStrength, a[25] = c.softBoundaryFalloff, a[26] = i.velocityStretchEnabled ? 1 : 0, a[27] = i.velocityStretchFactor ?? 1, a[28] = 0, a[29] = 0, a[30] = 0, a[31] = 0, this.device.queue.writeBuffer(this.physicsUniformBuffer, 0, a);
407
+ const l = o || this.device.createCommandEncoder({ label: "ParticlePhysicsEncoder" }), u = l.beginComputePass({ label: "ParticlePhysicsPass" });
396
408
  u.setPipeline(this.computePipeline), u.setBindGroup(0, this.computeBindGroup);
397
- const d = Math.max(1, Math.ceil(e / 64));
398
- u.dispatchWorkgroups(d, 1, 1), u.end(), n || this.device.queue.submit([l.finish()]), this.lastUpdateTime = performance.now() / 1e3;
409
+ const f = Math.max(1, Math.ceil(e / 64));
410
+ u.dispatchWorkgroups(f, 1, 1), u.end(), o || this.device.queue.submit([l.finish()]), this.lastUpdateTime = performance.now() / 1e3;
399
411
  }
400
- async readbackAndProcessParticles(t, e, i, a, r) {
412
+ async readbackAndProcessParticles(t, e, i, s, n) {
401
413
  if (t <= 0)
402
414
  return { activeCount: 0, shouldUpdate: !1 };
403
415
  if (this._stagingInUse)
404
416
  return { activeCount: t, shouldUpdate: !1 };
405
417
  try {
406
418
  this._stagingInUse = !0;
407
- const n = this.device.createCommandEncoder({
419
+ const o = this.device.createCommandEncoder({
408
420
  label: "ParticleReadbackEncoder"
409
- }), o = t * 8 * 4;
410
- n.copyBufferToBuffer(
411
- a,
421
+ }), a = t * 8 * 4;
422
+ o.copyBufferToBuffer(
423
+ s,
412
424
  0,
413
425
  this._particleDataStagingBuffer,
414
426
  0,
415
- o
427
+ a
416
428
  );
417
- const s = t * 4 * 4;
418
- return n.copyBufferToBuffer(
419
- r,
429
+ const c = t * 4 * 4;
430
+ return o.copyBufferToBuffer(
431
+ n,
420
432
  0,
421
433
  this._velocityStagingBuffer,
422
434
  0,
423
- s
424
- ), this.device.queue.submit([n.finish()]), await Promise.all([
435
+ c
436
+ ), this.device.queue.submit([o.finish()]), await Promise.all([
425
437
  (async () => {
426
- await this._particleDataStagingBuffer.mapAsync(GPUMapMode.READ, 0, o);
427
- const l = new Float32Array(this._particleDataStagingBuffer.getMappedRange(0, o));
438
+ await this._particleDataStagingBuffer.mapAsync(GPUMapMode.READ, 0, a);
439
+ const l = new Float32Array(this._particleDataStagingBuffer.getMappedRange(0, a));
428
440
  e.set(l), this._particleDataStagingBuffer.unmap();
429
441
  })(),
430
442
  (async () => {
431
- await this._velocityStagingBuffer.mapAsync(GPUMapMode.READ, 0, s);
432
- const l = new Float32Array(this._velocityStagingBuffer.getMappedRange(0, s));
443
+ await this._velocityStagingBuffer.mapAsync(GPUMapMode.READ, 0, c);
444
+ const l = new Float32Array(this._velocityStagingBuffer.getMappedRange(0, c));
433
445
  i.set(l), this._velocityStagingBuffer.unmap();
434
446
  })()
435
447
  ]), this._stagingInUse = !1, {
@@ -437,8 +449,8 @@ class q {
437
449
  particleVelocities: i,
438
450
  shouldUpdate: !0
439
451
  };
440
- } catch (n) {
441
- return this._stagingInUse = !1, console.error("Error reading back particle data:", n), { activeCount: t, shouldUpdate: !1 };
452
+ } catch (o) {
453
+ return this._stagingInUse = !1, o && o.name === "AbortError" || console.error("Error reading back particle data:", o), { activeCount: t, shouldUpdate: !1 };
442
454
  }
443
455
  }
444
456
  setDamping(t) {
@@ -465,37 +477,37 @@ class q {
465
477
  * @param {GPUBuffer} velocityBuffer
466
478
  * @returns {Promise<{particleData: Float32Array, particleVelocities: Float32Array, shouldUpdate: boolean}>}
467
479
  */
468
- async readbackForRendering(t, e, i, a, r) {
480
+ async readbackForRendering(t, e, i, s, n) {
469
481
  if (t <= 0)
470
482
  return { shouldUpdate: !1 };
471
483
  if (this._renderStagingInUse)
472
484
  return { shouldUpdate: !1 };
473
485
  try {
474
486
  this._renderStagingInUse = !0;
475
- const n = t * 8 * 4, o = t * 4 * 4, s = this.device.createCommandEncoder({
487
+ const o = t * 8 * 4, a = t * 4 * 4, c = this.device.createCommandEncoder({
476
488
  label: "RenderReadbackEncoder"
477
489
  });
478
- return s.copyBufferToBuffer(
479
- a,
490
+ return c.copyBufferToBuffer(
491
+ s,
480
492
  0,
481
493
  this._renderStagingParticleBuffer,
482
494
  0,
483
- n
484
- ), s.copyBufferToBuffer(
485
- r,
495
+ o
496
+ ), c.copyBufferToBuffer(
497
+ n,
486
498
  0,
487
499
  this._renderStagingVelocityBuffer,
488
500
  0,
489
- o
490
- ), this.device.queue.submit([s.finish()]), await Promise.all([
501
+ a
502
+ ), this.device.queue.submit([c.finish()]), await Promise.all([
491
503
  (async () => {
492
- await this._renderStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, n);
493
- const l = new Float32Array(this._renderStagingParticleBuffer.getMappedRange(0, n));
504
+ await this._renderStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, o);
505
+ const l = new Float32Array(this._renderStagingParticleBuffer.getMappedRange(0, o));
494
506
  e.set(l), this._renderStagingParticleBuffer.unmap();
495
507
  })(),
496
508
  (async () => {
497
- await this._renderStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, o);
498
- const l = new Float32Array(this._renderStagingVelocityBuffer.getMappedRange(0, o));
509
+ await this._renderStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, a);
510
+ const l = new Float32Array(this._renderStagingVelocityBuffer.getMappedRange(0, a));
499
511
  i.set(l), this._renderStagingVelocityBuffer.unmap();
500
512
  })()
501
513
  ]), this._renderStagingInUse = !1, {
@@ -503,22 +515,71 @@ class q {
503
515
  particleVelocities: i,
504
516
  shouldUpdate: !0
505
517
  };
506
- } catch (n) {
507
- return this._renderStagingInUse = !1, console.error("Error in rendering readback:", n), { shouldUpdate: !1 };
518
+ } catch (o) {
519
+ return this._renderStagingInUse = !1, console.error("Error in rendering readback:", o), { shouldUpdate: !1 };
520
+ }
521
+ }
522
+ /**
523
+ * Non-blocking readback for CPU-side particle scripting.
524
+ * Uses dedicated staging buffers that never contend with cleanup or rendering readback.
525
+ * Copies GPU data into caller-provided Float32Arrays.
526
+ * @param {number} activeParticles
527
+ * @param {Float32Array} outParticleData
528
+ * @param {Float32Array} outVelocities
529
+ * @param {GPUBuffer} instanceBuffer
530
+ * @param {GPUBuffer} velocityBuffer
531
+ * @returns {Promise<{shouldUpdate: boolean}>}
532
+ */
533
+ async readbackForScript(t, e, i, s, n) {
534
+ if (t <= 0)
535
+ return { shouldUpdate: !1 };
536
+ if (this._scriptStagingInUse)
537
+ return { shouldUpdate: !1 };
538
+ try {
539
+ this._scriptStagingInUse = !0;
540
+ const o = t * 8 * 4, a = t * 4 * 4, c = this.device.createCommandEncoder({
541
+ label: "ScriptReadbackEncoder"
542
+ });
543
+ return c.copyBufferToBuffer(
544
+ s,
545
+ 0,
546
+ this._scriptStagingParticleBuffer,
547
+ 0,
548
+ o
549
+ ), c.copyBufferToBuffer(
550
+ n,
551
+ 0,
552
+ this._scriptStagingVelocityBuffer,
553
+ 0,
554
+ a
555
+ ), this.device.queue.submit([c.finish()]), await Promise.all([
556
+ (async () => {
557
+ await this._scriptStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, o);
558
+ const l = new Float32Array(this._scriptStagingParticleBuffer.getMappedRange(0, o));
559
+ e.set(l), this._scriptStagingParticleBuffer.unmap();
560
+ })(),
561
+ (async () => {
562
+ await this._scriptStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, a);
563
+ const l = new Float32Array(this._scriptStagingVelocityBuffer.getMappedRange(0, a));
564
+ i.set(l), this._scriptStagingVelocityBuffer.unmap();
565
+ })()
566
+ ]), this._scriptStagingInUse = !1, { shouldUpdate: !0 };
567
+ } catch (o) {
568
+ return this._scriptStagingInUse = !1, console.error("Error in script readback:", o), { shouldUpdate: !1 };
508
569
  }
509
570
  }
510
571
  /**
511
572
  * Destroy all GPU buffers owned by this physics instance.
512
573
  */
513
574
  destroy() {
514
- this.physicsUniformBuffer.destroy(), this._particleDataStagingBuffer.destroy(), this._velocityStagingBuffer.destroy(), this._renderStagingParticleBuffer.destroy(), this._renderStagingVelocityBuffer.destroy();
575
+ this.physicsUniformBuffer.destroy(), this._particleDataStagingBuffer.destroy(), this._velocityStagingBuffer.destroy(), this._renderStagingParticleBuffer.destroy(), this._renderStagingVelocityBuffer.destroy(), this._scriptStagingParticleBuffer.destroy(), this._scriptStagingVelocityBuffer.destroy();
515
576
  }
516
577
  setSoftBoundary(t) {
517
578
  const e = this.physicsSettings;
518
579
  t.enabled !== void 0 && (e.softBoundaryEnabled = t.enabled), t.strength !== void 0 && (e.softBoundaryStrength = t.strength), t.falloff !== void 0 && (e.softBoundaryFalloff = t.falloff);
519
580
  }
520
581
  }
521
- class $ {
582
+ class ds {
522
583
  constructor(t) {
523
584
  this.device = t, this.defaultTexture = null, this.createDefaultTexture();
524
585
  }
@@ -557,315 +618,583 @@ class $ {
557
618
  t && t.label !== "defaultParticleTexture" && t.destroy();
558
619
  }
559
620
  }
560
- async function O(c) {
561
- const t = new DataView(c);
621
+ const yi = Object.freeze({
622
+ sin: Math.sin,
623
+ cos: Math.cos,
624
+ abs: Math.abs,
625
+ floor: Math.floor,
626
+ ceil: Math.ceil,
627
+ round: Math.round,
628
+ min: Math.min,
629
+ max: Math.max,
630
+ sqrt: Math.sqrt,
631
+ pow: Math.pow,
632
+ random: Math.random,
633
+ PI: Math.PI,
634
+ TAU: Math.PI * 2,
635
+ clamp(r, t, e) {
636
+ return r < t ? t : r > e ? e : r;
637
+ },
638
+ lerp(r, t, e) {
639
+ return r + (t - r) * e;
640
+ },
641
+ smoothstep(r, t, e) {
642
+ const i = yi.clamp((e - r) / (t - r), 0, 1);
643
+ return i * i * (3 - 2 * i);
644
+ }
645
+ }), Ze = /* @__PURE__ */ new Set([
646
+ "particleSize",
647
+ "particleSpeed",
648
+ "particleColor",
649
+ "startColor",
650
+ "endColor",
651
+ "opacity",
652
+ "emissionRate",
653
+ "gravityStrength",
654
+ "dampingStrength",
655
+ "attractorStrength",
656
+ "attractorPosition",
657
+ "pulseAmplitude",
658
+ "pulseFrequency",
659
+ "bloomIntensity"
660
+ ]);
661
+ class fs {
662
+ constructor(t) {
663
+ this._collection = t, this._pd = null, this._vd = null, this._pi = 0, this._vi = 0;
664
+ }
665
+ _bind(t, e, i) {
666
+ return this._pd = t, this._vd = e, this._pi = i * 8, this._vi = i * 4, this;
667
+ }
668
+ // Position
669
+ get x() {
670
+ return this._pd[this._pi];
671
+ }
672
+ set x(t) {
673
+ this._pd[this._pi] = t, this._collection._dirty = !0;
674
+ }
675
+ get y() {
676
+ return this._pd[this._pi + 1];
677
+ }
678
+ set y(t) {
679
+ this._pd[this._pi + 1] = t, this._collection._dirty = !0;
680
+ }
681
+ get z() {
682
+ return this._pd[this._pi + 2];
683
+ }
684
+ set z(t) {
685
+ this._pd[this._pi + 2] = t, this._collection._dirty = !0;
686
+ }
687
+ // Color
688
+ get r() {
689
+ return this._pd[this._pi + 3];
690
+ }
691
+ set r(t) {
692
+ this._pd[this._pi + 3] = t, this._collection._dirty = !0;
693
+ }
694
+ get g() {
695
+ return this._pd[this._pi + 4];
696
+ }
697
+ set g(t) {
698
+ this._pd[this._pi + 4] = t, this._collection._dirty = !0;
699
+ }
700
+ get b() {
701
+ return this._pd[this._pi + 5];
702
+ }
703
+ set b(t) {
704
+ this._pd[this._pi + 5] = t, this._collection._dirty = !0;
705
+ }
706
+ // Age / Lifetime
707
+ get age() {
708
+ return this._pd[this._pi + 6];
709
+ }
710
+ set age(t) {
711
+ this._pd[this._pi + 6] = t, this._collection._dirty = !0;
712
+ }
713
+ get lifetime() {
714
+ return this._pd[this._pi + 7];
715
+ }
716
+ set lifetime(t) {
717
+ this._pd[this._pi + 7] = t, this._collection._dirty = !0;
718
+ }
719
+ // Velocity
720
+ get vx() {
721
+ return this._vd[this._vi];
722
+ }
723
+ set vx(t) {
724
+ this._vd[this._vi] = t, this._collection._dirty = !0;
725
+ }
726
+ get vy() {
727
+ return this._vd[this._vi + 1];
728
+ }
729
+ set vy(t) {
730
+ this._vd[this._vi + 1] = t, this._collection._dirty = !0;
731
+ }
732
+ get vz() {
733
+ return this._vd[this._vi + 2];
734
+ }
735
+ set vz(t) {
736
+ this._vd[this._vi + 2] = t, this._collection._dirty = !0;
737
+ }
738
+ }
739
+ class ps {
740
+ constructor() {
741
+ this._proxy = new fs(this), this._pd = null, this._vd = null, this.count = 0, this._dirty = !1;
742
+ }
743
+ _bind(t, e, i) {
744
+ this._pd = t, this._vd = e, this.count = i, this._dirty = !1;
745
+ }
746
+ get(t) {
747
+ return t < 0 || t >= this.count ? null : this._proxy._bind(this._pd, this._vd, t);
748
+ }
749
+ }
750
+ const hs = 1e6;
751
+ function ms(r) {
752
+ let t = 0;
753
+ return r.replace(
754
+ /\b(for|while)\s*\([^)]*\)\s*\{/g,
755
+ (e) => {
756
+ const i = `__lc${t++}`;
757
+ return `${e} if(++${i}>${hs})throw new Error("Loop limit exceeded");`;
758
+ }
759
+ ).replace(
760
+ /\b(for|while)\s*\([^)]*\)\s*\{/g,
761
+ // already handled above
762
+ (e) => e
763
+ ).replace(
764
+ // Prepend counter declarations at the top
765
+ /^/,
766
+ () => {
767
+ let e = "";
768
+ for (let i = 0; i < t; i++)
769
+ e += `let __lc${i}=0;`;
770
+ return e;
771
+ }
772
+ );
773
+ }
774
+ const vt = /* @__PURE__ */ new Map();
775
+ for (const r of Ze)
776
+ vt.set(r.toLowerCase(), r);
777
+ function ys(r) {
778
+ const t = { value: !1 }, e = /* @__PURE__ */ new Set();
779
+ return new Proxy(r, {
780
+ get(s, n) {
781
+ if (n === "__dirty") return t.value;
782
+ if (n === "__resetDirty") return () => {
783
+ t.value = !1;
784
+ };
785
+ if (typeof n != "string") return;
786
+ if (Ze.has(n)) return s[n];
787
+ const o = vt.get(n.toLowerCase());
788
+ if (o)
789
+ return e.has(n) || (e.add(n), console.warn(`[ParticleScript] config.${n} → did you mean config.${o}?`)), s[o];
790
+ },
791
+ set(s, n, o) {
792
+ if (typeof n != "string") return !0;
793
+ let a = n;
794
+ if (!Ze.has(a)) {
795
+ const c = vt.get(a.toLowerCase());
796
+ if (c)
797
+ e.has(n) || (e.add(n), console.warn(`[ParticleScript] config.${n} → did you mean config.${c}?`)), a = c;
798
+ else
799
+ return !0;
800
+ }
801
+ return s[a] = o, t.value = !0, !0;
802
+ }
803
+ });
804
+ }
805
+ class si {
806
+ /**
807
+ * @param {string} source - User script source code
808
+ * @param {object} config - ParticleSystem config (will be proxied)
809
+ * @param {number} maxParticles - Max particle count for pre-allocation
810
+ */
811
+ constructor(t, e, i) {
812
+ this._particles = new ps(), this._configProxy = ys(e), this._configSnapshot = null, this._fn = null, this._error = !1, this.compile(t);
813
+ }
814
+ /**
815
+ * Compile script source into a sandboxed function.
816
+ */
817
+ compile(t) {
818
+ if (this._fn = null, this._error = !1, !(!t || typeof t != "string"))
819
+ try {
820
+ const i = `
821
+ return function(__deltaTime, __time, __currentFrame, __totalFrames, __particles, __config, __math) {
822
+ var window = void 0, document = void 0, globalThis = void 0;
823
+ var Function = void 0, eval = void 0, fetch = void 0;
824
+ var importScripts = void 0, XMLHttpRequest = void 0, WebSocket = void 0;
825
+ var deltaTime = __deltaTime, time = __time;
826
+ var currentFrame = __currentFrame, totalFrames = __totalFrames;
827
+ var particles = __particles, config = __config, math = __math;
828
+ ${ms(t)}
829
+ };`, s = new Function(i);
830
+ this._fn = s();
831
+ } catch (e) {
832
+ console.warn("[ParticleScript] Compilation error:", e.message), this._fn = null, this._error = !0;
833
+ }
834
+ }
835
+ /**
836
+ * Execute the script for one frame.
837
+ * @param {number} deltaTime
838
+ * @param {number} time - seconds since system start
839
+ * @param {number} frame - frame counter
840
+ * @param {number} totalFrames - estimated total frames
841
+ * @param {Float32Array} particleData - read/write
842
+ * @param {Float32Array} velocityData - read/write
843
+ * @param {number} count - active particle count
844
+ * @returns {boolean} true if config was modified
845
+ */
846
+ execute(t, e, i, s, n, o, a) {
847
+ if (!this._fn || this._error) return { configDirty: !1, particlesDirty: !1 };
848
+ this._particles._bind(n, o, a), this._configProxy.__resetDirty();
849
+ try {
850
+ this._fn(t, e, i, s, this._particles, this._configProxy, yi);
851
+ } catch (c) {
852
+ console.warn("[ParticleScript] Runtime error:", c.message);
853
+ }
854
+ return {
855
+ configDirty: this._configProxy.__dirty,
856
+ particlesDirty: this._particles._dirty
857
+ };
858
+ }
859
+ /**
860
+ * Deep-clone the scriptable config properties for later restoration.
861
+ */
862
+ snapshotConfig(t) {
863
+ const e = {};
864
+ for (const i of Ze) {
865
+ const s = t[i];
866
+ s !== void 0 && (e[i] = Array.isArray(s) ? [...s] : s);
867
+ }
868
+ this._configSnapshot = e;
869
+ }
870
+ /**
871
+ * Restore config properties from the snapshot.
872
+ */
873
+ restoreConfig(t) {
874
+ if (this._configSnapshot) {
875
+ for (const e of Ze)
876
+ if (e in this._configSnapshot) {
877
+ const i = this._configSnapshot[e];
878
+ t[e] = Array.isArray(i) ? [...i] : i;
879
+ }
880
+ }
881
+ }
882
+ /**
883
+ * Cleanup.
884
+ */
885
+ destroy() {
886
+ this._fn = null, this._particles = null, this._configProxy = null, this._configSnapshot = null;
887
+ }
888
+ }
889
+ async function gi(r) {
890
+ const t = new DataView(r);
562
891
  if (t.getUint32(0, !0) !== 1179937895)
563
892
  throw new Error("Invalid GLB file: incorrect magic number");
564
893
  const i = t.getUint32(4, !0);
565
894
  if (i !== 2)
566
895
  throw new Error(`Unsupported GLB version: ${i} (only version 2 is supported)`);
567
- const a = t.getUint32(8, !0);
568
- let r = 12, n = null, o = null;
569
- for (; r < a; ) {
570
- const g = t.getUint32(r, !0), x = t.getUint32(r + 4, !0), M = c.slice(r + 8, r + 8 + g);
571
- if (x === 1313821514) {
572
- const B = new TextDecoder("utf-8").decode(M);
573
- n = JSON.parse(B);
574
- } else x === 5130562 && (o = M);
575
- r += 8 + g;
896
+ const s = t.getUint32(8, !0);
897
+ let n = 12, o = null, a = null;
898
+ for (; n < s; ) {
899
+ const P = t.getUint32(n, !0), _ = t.getUint32(n + 4, !0), T = r.slice(n + 8, n + 8 + P);
900
+ if (_ === 1313821514) {
901
+ const N = new TextDecoder("utf-8").decode(T);
902
+ o = JSON.parse(N);
903
+ } else _ === 5130562 && (a = T);
904
+ n += 8 + P;
576
905
  }
577
- if (!n)
906
+ if (!o)
578
907
  throw new Error("GLB file missing JSON chunk");
579
- if (!n.meshes || n.meshes.length === 0)
908
+ if (!o.meshes || o.meshes.length === 0)
580
909
  throw new Error("GLB file contains no meshes");
581
- const l = n.meshes[0].primitives[0];
910
+ const l = o.meshes[0].primitives[0];
582
911
  if (!l)
583
912
  throw new Error("First mesh has no primitives");
584
913
  const u = l.attributes.POSITION;
585
914
  if (u === void 0)
586
915
  throw new Error("Mesh primitive missing POSITION attribute");
587
- const d = _(n, o, u, 3, 5126);
588
- let f;
916
+ const f = gt(o, a, u, 3, 5126);
917
+ let h;
589
918
  if (l.attributes.NORMAL !== void 0)
590
- f = _(n, o, l.attributes.NORMAL, 3, 5126);
919
+ h = gt(o, a, l.attributes.NORMAL, 3, 5126);
591
920
  else {
592
- const g = l.indices;
593
- if (g === void 0)
921
+ const P = l.indices;
922
+ if (P === void 0)
594
923
  throw new Error("Cannot generate normals without indices");
595
- const x = I(n, o, g);
596
- f = H(d, x);
924
+ const _ = ri(o, a, P);
925
+ h = gs(f, _);
597
926
  }
598
- const h = l.indices;
599
- if (h === void 0)
927
+ const m = l.indices;
928
+ if (m === void 0)
600
929
  throw new Error("Mesh primitive missing indices");
601
- const p = I(n, o, h), m = d.length / 3, b = p.length;
602
- let S = null;
603
- l.attributes.TEXCOORD_0 !== void 0 && (S = _(n, o, l.attributes.TEXCOORD_0, 2, 5126));
604
- let y = !1;
605
- if (n.materials && n.materials.length > 0) {
606
- const g = n.materials[0];
607
- g.pbrMetallicRoughness && g.pbrMetallicRoughness.baseColorTexture !== void 0 && (y = !0);
608
- }
609
- let P = null;
610
- if (n.skins && n.skins.length > 0)
930
+ const S = ri(o, a, m), R = f.length / 3, D = S.length;
931
+ let C = null;
932
+ l.attributes.TEXCOORD_0 !== void 0 && (C = gt(o, a, l.attributes.TEXCOORD_0, 2, 5126));
933
+ let B = !1;
934
+ if (o.materials && o.materials.length > 0) {
935
+ const P = o.materials[0];
936
+ P.pbrMetallicRoughness && P.pbrMetallicRoughness.baseColorTexture !== void 0 && (B = !0);
937
+ }
938
+ let A = null;
939
+ if (o.skins && o.skins.length > 0)
611
940
  try {
612
- P = te(n, o, l), console.log("Animation data extracted:", P);
613
- } catch (g) {
614
- console.warn("Failed to extract animation data:", g);
941
+ A = _s(o, a, l), console.log("Animation data extracted:", A);
942
+ } catch (P) {
943
+ console.warn("Failed to extract animation data:", P);
615
944
  }
616
945
  return {
617
- positions: d,
618
- normals: f,
619
- indices: p,
620
- texCoords: S,
621
- vertexCount: m,
622
- indexCount: b,
623
- animationData: P,
624
- hasBaseColorTexture: y
946
+ positions: f,
947
+ normals: h,
948
+ indices: S,
949
+ texCoords: C,
950
+ vertexCount: R,
951
+ indexCount: D,
952
+ animationData: A,
953
+ hasBaseColorTexture: B
625
954
  };
626
955
  }
627
- function _(c, t, e, i, a) {
628
- const r = c.accessors[e], o = {
956
+ function gt(r, t, e, i, s) {
957
+ const n = r.accessors[e], a = {
629
958
  SCALAR: 1,
630
959
  VEC2: 2,
631
960
  VEC3: 3,
632
961
  VEC4: 4
633
- }[r.type];
634
- if (o !== i)
635
- throw new Error(`Attribute accessor type mismatch: expected ${i} components, got ${o}`);
636
- if (r.componentType !== a)
637
- throw new Error(`Attribute component type mismatch: expected ${a}, got ${r.componentType}`);
638
- const l = (c.bufferViews[r.bufferView].byteOffset || 0) + (r.byteOffset || 0), u = r.count, d = new DataView(t, l, u * i * 4), f = new Float32Array(u * i);
639
- for (let h = 0; h < u * i; h++)
640
- f[h] = d.getFloat32(h * 4, !0);
641
- return f;
962
+ }[n.type];
963
+ if (a !== i)
964
+ throw new Error(`Attribute accessor type mismatch: expected ${i} components, got ${a}`);
965
+ if (n.componentType !== s)
966
+ throw new Error(`Attribute component type mismatch: expected ${s}, got ${n.componentType}`);
967
+ const l = (r.bufferViews[n.bufferView].byteOffset || 0) + (n.byteOffset || 0), u = n.count, f = new DataView(t, l, u * i * 4), h = new Float32Array(u * i);
968
+ for (let m = 0; m < u * i; m++)
969
+ h[m] = f.getFloat32(m * 4, !0);
970
+ return h;
642
971
  }
643
- function I(c, t, e) {
644
- const i = c.accessors[e];
972
+ function ri(r, t, e) {
973
+ const i = r.accessors[e];
645
974
  if (i.type !== "SCALAR")
646
975
  throw new Error(`Indices accessor must be SCALAR, got ${i.type}`);
647
- const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
976
+ const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
648
977
  if (i.componentType === 5123) {
649
- const o = new DataView(t, r, n * 2), s = new Uint16Array(n);
650
- for (let l = 0; l < n; l++)
651
- s[l] = o.getUint16(l * 2, !0);
652
- return s;
978
+ const a = new DataView(t, n, o * 2), c = new Uint16Array(o);
979
+ for (let l = 0; l < o; l++)
980
+ c[l] = a.getUint16(l * 2, !0);
981
+ return c;
653
982
  } else if (i.componentType === 5125) {
654
- const o = new DataView(t, r, n * 4), s = new Uint32Array(n);
655
- for (let l = 0; l < n; l++)
656
- s[l] = o.getUint32(l * 4, !0);
657
- return s;
983
+ const a = new DataView(t, n, o * 4), c = new Uint32Array(o);
984
+ for (let l = 0; l < o; l++)
985
+ c[l] = a.getUint32(l * 4, !0);
986
+ return c;
658
987
  } else
659
988
  throw new Error(`Unsupported index component type: ${i.componentType}`);
660
989
  }
661
- function H(c, t) {
662
- const e = new Float32Array(c.length);
990
+ function gs(r, t) {
991
+ const e = new Float32Array(r.length);
663
992
  for (let i = 0; i < t.length; i += 3) {
664
- const a = t[i] * 3, r = t[i + 1] * 3, n = t[i + 2] * 3, o = [c[a], c[a + 1], c[a + 2]], s = [c[r], c[r + 1], c[r + 2]], l = [c[n], c[n + 1], c[n + 2]], u = [s[0] - o[0], s[1] - o[1], s[2] - o[2]], d = [l[0] - o[0], l[1] - o[1], l[2] - o[2]], f = [
665
- u[1] * d[2] - u[2] * d[1],
666
- u[2] * d[0] - u[0] * d[2],
667
- u[0] * d[1] - u[1] * d[0]
668
- ], h = Math.sqrt(f[0] * f[0] + f[1] * f[1] + f[2] * f[2]);
669
- h > 0 && (f[0] /= h, f[1] /= h, f[2] /= h), e[a] = e[r] = e[n] = f[0], e[a + 1] = e[r + 1] = e[n + 1] = f[1], e[a + 2] = e[r + 2] = e[n + 2] = f[2];
993
+ const s = t[i] * 3, n = t[i + 1] * 3, o = t[i + 2] * 3, a = [r[s], r[s + 1], r[s + 2]], c = [r[n], r[n + 1], r[n + 2]], l = [r[o], r[o + 1], r[o + 2]], u = [c[0] - a[0], c[1] - a[1], c[2] - a[2]], f = [l[0] - a[0], l[1] - a[1], l[2] - a[2]], h = [
994
+ u[1] * f[2] - u[2] * f[1],
995
+ u[2] * f[0] - u[0] * f[2],
996
+ u[0] * f[1] - u[1] * f[0]
997
+ ], m = Math.sqrt(h[0] * h[0] + h[1] * h[1] + h[2] * h[2]);
998
+ m > 0 && (h[0] /= m, h[1] /= m, h[2] /= m), e[s] = e[n] = e[o] = h[0], e[s + 1] = e[n + 1] = e[o + 1] = h[1], e[s + 2] = e[n + 2] = e[o + 2] = h[2];
670
999
  }
671
1000
  return e;
672
1001
  }
673
- function W(c, t, e) {
674
- const i = c.accessors[e];
1002
+ function bs(r, t, e) {
1003
+ const i = r.accessors[e];
675
1004
  if (i.type !== "VEC4")
676
1005
  throw new Error(`JOINTS_0 must be VEC4, got ${i.type}`);
677
- const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
1006
+ const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
678
1007
  if (i.componentType === 5121) {
679
- const o = new DataView(t, r, n * 4), s = new Uint8Array(n * 4);
680
- for (let l = 0; l < n * 4; l++)
681
- s[l] = o.getUint8(l);
682
- return s;
1008
+ const a = new DataView(t, n, o * 4), c = new Uint8Array(o * 4);
1009
+ for (let l = 0; l < o * 4; l++)
1010
+ c[l] = a.getUint8(l);
1011
+ return c;
683
1012
  } else if (i.componentType === 5123) {
684
- const o = new DataView(t, r, n * 8), s = new Uint8Array(n * 4);
685
- for (let l = 0; l < n * 4; l++)
686
- s[l] = o.getUint16(l * 2, !0);
687
- return s;
1013
+ const a = new DataView(t, n, o * 8), c = new Uint8Array(o * 4);
1014
+ for (let l = 0; l < o * 4; l++)
1015
+ c[l] = a.getUint16(l * 2, !0);
1016
+ return c;
688
1017
  } else
689
1018
  throw new Error(`Unsupported JOINTS_0 component type: ${i.componentType}`);
690
1019
  }
691
- function J(c, t, e) {
692
- const i = c.accessors[e];
1020
+ function Ss(r, t, e) {
1021
+ const i = r.accessors[e];
693
1022
  if (i.type !== "VEC4")
694
1023
  throw new Error(`WEIGHTS_0 must be VEC4, got ${i.type}`);
695
- const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
1024
+ const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count;
696
1025
  if (i.componentType === 5126) {
697
- const o = new DataView(t, r, n * 16), s = new Float32Array(n * 4);
698
- for (let l = 0; l < n * 4; l++)
699
- s[l] = o.getFloat32(l * 4, !0);
700
- return s;
1026
+ const a = new DataView(t, n, o * 16), c = new Float32Array(o * 4);
1027
+ for (let l = 0; l < o * 4; l++)
1028
+ c[l] = a.getFloat32(l * 4, !0);
1029
+ return c;
701
1030
  } else if (i.componentType === 5121) {
702
- const o = new DataView(t, r, n * 4), s = new Float32Array(n * 4);
703
- for (let l = 0; l < n * 4; l++)
704
- s[l] = o.getUint8(l) / 255;
705
- return s;
1031
+ const a = new DataView(t, n, o * 4), c = new Float32Array(o * 4);
1032
+ for (let l = 0; l < o * 4; l++)
1033
+ c[l] = a.getUint8(l) / 255;
1034
+ return c;
706
1035
  } else
707
1036
  throw new Error(`Unsupported WEIGHTS_0 component type: ${i.componentType}`);
708
1037
  }
709
- function K(c, t, e) {
710
- const i = c.accessors[e];
1038
+ function xs(r, t, e) {
1039
+ const i = r.accessors[e];
711
1040
  if (i.type !== "MAT4")
712
1041
  throw new Error(`Expected MAT4, got ${i.type}`);
713
1042
  if (i.componentType !== 5126)
714
1043
  throw new Error(`Expected FLOAT component type for MAT4, got ${i.componentType}`);
715
- const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count, o = new DataView(t, r, n * 64), s = new Float32Array(n * 16);
716
- for (let l = 0; l < n * 16; l++)
717
- s[l] = o.getFloat32(l * 4, !0);
718
- return s;
1044
+ const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count, a = new DataView(t, n, o * 64), c = new Float32Array(o * 16);
1045
+ for (let l = 0; l < o * 16; l++)
1046
+ c[l] = a.getFloat32(l * 4, !0);
1047
+ return c;
719
1048
  }
720
- function Q(c, t, e) {
721
- const i = c.accessors[e];
1049
+ function vs(r, t, e) {
1050
+ const i = r.accessors[e];
722
1051
  if (i.type !== "SCALAR")
723
1052
  throw new Error(`Expected SCALAR, got ${i.type}`);
724
1053
  if (i.componentType !== 5126)
725
1054
  throw new Error(`Expected FLOAT component type for SCALAR, got ${i.componentType}`);
726
- const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count, o = new DataView(t, r, n * 4), s = new Float32Array(n);
727
- for (let l = 0; l < n; l++)
728
- s[l] = o.getFloat32(l * 4, !0);
729
- return s;
1055
+ const n = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), o = i.count, a = new DataView(t, n, o * 4), c = new Float32Array(o);
1056
+ for (let l = 0; l < o; l++)
1057
+ c[l] = a.getFloat32(l * 4, !0);
1058
+ return c;
730
1059
  }
731
- function ee(c, t, e) {
732
- const i = c.accessors[e], r = { VEC3: 3, VEC4: 4 }[i.type];
733
- if (!r)
1060
+ function Ps(r, t, e) {
1061
+ const i = r.accessors[e], n = { VEC3: 3, VEC4: 4 }[i.type];
1062
+ if (!n)
734
1063
  throw new Error(`Expected VEC3 or VEC4, got ${i.type}`);
735
1064
  if (i.componentType !== 5126)
736
1065
  throw new Error(`Expected FLOAT component type, got ${i.componentType}`);
737
- const o = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), s = i.count, l = new DataView(t, o, s * r * 4), u = new Float32Array(s * r);
738
- for (let d = 0; d < s * r; d++)
739
- u[d] = l.getFloat32(d * 4, !0);
1066
+ const a = (r.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), c = i.count, l = new DataView(t, a, c * n * 4), u = new Float32Array(c * n);
1067
+ for (let f = 0; f < c * n; f++)
1068
+ u[f] = l.getFloat32(f * 4, !0);
740
1069
  return u;
741
1070
  }
742
- function te(c, t, e) {
743
- const i = c.skins[0], a = i.joints, r = K(c, t, i.inverseBindMatrices), n = e.attributes.JOINTS_0 !== void 0 ? W(c, t, e.attributes.JOINTS_0) : null, o = e.attributes.WEIGHTS_0 !== void 0 ? J(c, t, e.attributes.WEIGHTS_0) : null;
744
- if (!n || !o)
1071
+ function _s(r, t, e) {
1072
+ const i = r.skins[0], s = i.joints, n = xs(r, t, i.inverseBindMatrices), o = e.attributes.JOINTS_0 !== void 0 ? bs(r, t, e.attributes.JOINTS_0) : null, a = e.attributes.WEIGHTS_0 !== void 0 ? Ss(r, t, e.attributes.WEIGHTS_0) : null;
1073
+ if (!o || !a)
745
1074
  throw new Error("Mesh missing JOINTS_0 or WEIGHTS_0 attributes");
746
- const s = c.nodes.map((u) => ({
1075
+ const c = r.nodes.map((u) => ({
747
1076
  translation: u.translation || [0, 0, 0],
748
1077
  rotation: u.rotation || [0, 0, 0, 1],
749
1078
  scale: u.scale || [1, 1, 1],
750
1079
  children: u.children || [],
751
1080
  name: u.name || ""
752
1081
  })), l = [];
753
- if (c.animations && c.animations.length > 0)
754
- for (const u of c.animations) {
755
- const d = [];
756
- let f = 0;
757
- for (const h of u.channels) {
758
- const p = u.samplers[h.sampler], m = Q(c, t, p.input), b = ee(c, t, p.output), S = m[m.length - 1];
759
- S > f && (f = S), d.push({
760
- targetNode: h.target.node,
761
- targetPath: h.target.path,
762
- interpolation: p.interpolation || "LINEAR",
763
- timestamps: m,
764
- values: b
1082
+ if (r.animations && r.animations.length > 0)
1083
+ for (const u of r.animations) {
1084
+ const f = [];
1085
+ let h = 0;
1086
+ for (const m of u.channels) {
1087
+ const S = u.samplers[m.sampler], R = vs(r, t, S.input), D = Ps(r, t, S.output), C = R[R.length - 1];
1088
+ C > h && (h = C), f.push({
1089
+ targetNode: m.target.node,
1090
+ targetPath: m.target.path,
1091
+ interpolation: S.interpolation || "LINEAR",
1092
+ timestamps: R,
1093
+ values: D
765
1094
  });
766
1095
  }
767
1096
  l.push({
768
1097
  name: u.name || `Animation ${l.length}`,
769
- duration: f,
770
- channels: d
1098
+ duration: h,
1099
+ channels: f
771
1100
  });
772
1101
  }
773
1102
  return {
774
- joints: a,
775
- inverseBindMatrices: r,
776
- jointIndices: n,
777
- jointWeights: o,
778
- nodes: s,
1103
+ joints: s,
1104
+ inverseBindMatrices: n,
1105
+ jointIndices: o,
1106
+ jointWeights: a,
1107
+ nodes: c,
779
1108
  animations: l
780
1109
  };
781
1110
  }
782
- async function ie(c) {
783
- const t = new DataView(c);
1111
+ async function ws(r) {
1112
+ const t = new DataView(r);
784
1113
  if (t.getUint32(0, !0) !== 1179937895)
785
1114
  throw new Error("Invalid GLB file: incorrect magic number");
786
1115
  const i = t.getUint32(4, !0);
787
1116
  if (i !== 2)
788
1117
  throw new Error(`Unsupported GLB version: ${i}`);
789
- const a = t.getUint32(8, !0);
790
- let r = 12, n = null, o = null;
791
- for (; r < a; ) {
792
- const P = t.getUint32(r, !0), g = t.getUint32(r + 4, !0), x = c.slice(r + 8, r + 8 + P);
793
- if (g === 1313821514) {
794
- const R = new TextDecoder("utf-8").decode(x);
795
- n = JSON.parse(R);
796
- } else g === 5130562 && (o = x);
797
- r += 8 + P;
1118
+ const s = t.getUint32(8, !0);
1119
+ let n = 12, o = null, a = null;
1120
+ for (; n < s; ) {
1121
+ const A = t.getUint32(n, !0), P = t.getUint32(n + 4, !0), _ = r.slice(n + 8, n + 8 + A);
1122
+ if (P === 1313821514) {
1123
+ const L = new TextDecoder("utf-8").decode(_);
1124
+ o = JSON.parse(L);
1125
+ } else P === 5130562 && (a = _);
1126
+ n += 8 + A;
798
1127
  }
799
- if (!n)
1128
+ if (!o)
800
1129
  throw new Error("GLB file missing JSON chunk");
801
- if (!n.materials || n.materials.length === 0)
1130
+ if (!o.materials || o.materials.length === 0)
802
1131
  return null;
803
- const s = n.materials[0];
804
- if (!s.pbrMetallicRoughness || s.pbrMetallicRoughness.baseColorTexture === void 0)
1132
+ const c = o.materials[0];
1133
+ if (!c.pbrMetallicRoughness || c.pbrMetallicRoughness.baseColorTexture === void 0)
805
1134
  return null;
806
- const l = s.pbrMetallicRoughness.baseColorTexture.index;
807
- if (!n.textures || !n.textures[l])
1135
+ const l = c.pbrMetallicRoughness.baseColorTexture.index;
1136
+ if (!o.textures || !o.textures[l])
808
1137
  return null;
809
- const d = n.textures[l].source;
810
- if (d === void 0 || !n.images || !n.images[d])
1138
+ const f = o.textures[l].source;
1139
+ if (f === void 0 || !o.images || !o.images[f])
811
1140
  return null;
812
- const f = n.images[d], h = f.mimeType || "image/png";
813
- if (f.bufferView === void 0)
1141
+ const h = o.images[f], m = h.mimeType || "image/png";
1142
+ if (h.bufferView === void 0)
814
1143
  return null;
815
- if (!o)
1144
+ if (!a)
816
1145
  throw new Error("GLB file missing BIN chunk (required for embedded textures)");
817
- const p = n.bufferViews[f.bufferView], m = p.byteOffset || 0, b = p.byteLength, S = o.slice(m, m + b);
818
- return { imageBlob: new Blob([S], { type: h }), mimeType: h };
1146
+ const S = o.bufferViews[h.bufferView], R = S.byteOffset || 0, D = S.byteLength, C = a.slice(R, R + D);
1147
+ return { imageBlob: new Blob([C], { type: m }), mimeType: m };
819
1148
  }
820
- const U = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1149
+ const ni = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
821
1150
  __proto__: null,
822
- extractGLBTexture: ie,
823
- parseGLB: O
1151
+ extractGLBTexture: ws,
1152
+ parseGLB: gi
824
1153
  }, Symbol.toStringTag, { value: "Module" }));
825
- function z(c, t, e) {
1154
+ function ai(r, t, e) {
826
1155
  return [
827
- c[0] + (t[0] - c[0]) * e,
828
- c[1] + (t[1] - c[1]) * e,
829
- c[2] + (t[2] - c[2]) * e
1156
+ r[0] + (t[0] - r[0]) * e,
1157
+ r[1] + (t[1] - r[1]) * e,
1158
+ r[2] + (t[2] - r[2]) * e
830
1159
  ];
831
1160
  }
832
- function F(c, t, e) {
833
- let i = c[0] * t[0] + c[1] * t[1] + c[2] * t[2] + c[3] * t[3], a = t;
834
- if (i < 0 && (i = -i, a = [-t[0], -t[1], -t[2], -t[3]]), i > 0.9995) {
1161
+ function oi(r, t, e) {
1162
+ let i = r[0] * t[0] + r[1] * t[1] + r[2] * t[2] + r[3] * t[3], s = t;
1163
+ if (i < 0 && (i = -i, s = [-t[0], -t[1], -t[2], -t[3]]), i > 0.9995) {
835
1164
  const l = [
836
- c[0] + (a[0] - c[0]) * e,
837
- c[1] + (a[1] - c[1]) * e,
838
- c[2] + (a[2] - c[2]) * e,
839
- c[3] + (a[3] - c[3]) * e
1165
+ r[0] + (s[0] - r[0]) * e,
1166
+ r[1] + (s[1] - r[1]) * e,
1167
+ r[2] + (s[2] - r[2]) * e,
1168
+ r[3] + (s[3] - r[3]) * e
840
1169
  ];
841
- return ae(l);
1170
+ return Bs(l);
842
1171
  }
843
- const r = Math.acos(i), n = Math.sin(r), o = Math.sin((1 - e) * r) / n, s = Math.sin(e * r) / n;
1172
+ const n = Math.acos(i), o = Math.sin(n), a = Math.sin((1 - e) * n) / o, c = Math.sin(e * n) / o;
844
1173
  return [
845
- c[0] * o + a[0] * s,
846
- c[1] * o + a[1] * s,
847
- c[2] * o + a[2] * s,
848
- c[3] * o + a[3] * s
1174
+ r[0] * a + s[0] * c,
1175
+ r[1] * a + s[1] * c,
1176
+ r[2] * a + s[2] * c,
1177
+ r[3] * a + s[3] * c
849
1178
  ];
850
1179
  }
851
- function ae(c) {
852
- const t = Math.sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
853
- return t > 1e-4 ? [c[0] / t, c[1] / t, c[2] / t, c[3] / t] : [0, 0, 0, 1];
1180
+ function Bs(r) {
1181
+ const t = Math.sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2] + r[3] * r[3]);
1182
+ return t > 1e-4 ? [r[0] / t, r[1] / t, r[2] / t, r[3] / t] : [0, 0, 0, 1];
854
1183
  }
855
- function se(c) {
856
- const t = c[0], e = c[1], i = c[2], a = c[3], r = t + t, n = e + e, o = i + i, s = t * r, l = t * n, u = t * o, d = e * n, f = e * o, h = i * o, p = a * r, m = a * n, b = a * o;
1184
+ function Rs(r) {
1185
+ const t = r[0], e = r[1], i = r[2], s = r[3], n = t + t, o = e + e, a = i + i, c = t * n, l = t * o, u = t * a, f = e * o, h = e * a, m = i * a, S = s * n, R = s * o, D = s * a;
857
1186
  return new Float32Array([
858
- 1 - (d + h),
859
- l + b,
860
- u - m,
1187
+ 1 - (f + m),
1188
+ l + D,
1189
+ u - R,
861
1190
  0,
862
- l - b,
863
- 1 - (s + h),
864
- f + p,
1191
+ l - D,
1192
+ 1 - (c + m),
1193
+ h + S,
865
1194
  0,
866
- u + m,
867
- f - p,
868
- 1 - (s + d),
1195
+ u + R,
1196
+ h - S,
1197
+ 1 - (c + f),
869
1198
  0,
870
1199
  0,
871
1200
  0,
@@ -873,8 +1202,8 @@ function se(c) {
873
1202
  1
874
1203
  ]);
875
1204
  }
876
- function re(c, t, e) {
877
- const i = se(t);
1205
+ function Ms(r, t, e) {
1206
+ const i = Rs(t);
878
1207
  return new Float32Array([
879
1208
  i[0] * e[0],
880
1209
  i[1] * e[0],
@@ -888,20 +1217,20 @@ function re(c, t, e) {
888
1217
  i[9] * e[2],
889
1218
  i[10] * e[2],
890
1219
  0,
891
- c[0],
892
- c[1],
893
- c[2],
1220
+ r[0],
1221
+ r[1],
1222
+ r[2],
894
1223
  1
895
1224
  ]);
896
1225
  }
897
- function G(c, t) {
1226
+ function li(r, t) {
898
1227
  const e = new Float32Array(16);
899
1228
  for (let i = 0; i < 4; i++)
900
- for (let a = 0; a < 4; a++)
901
- e[i * 4 + a] = c[0 + a] * t[i * 4 + 0] + c[4 + a] * t[i * 4 + 1] + c[8 + a] * t[i * 4 + 2] + c[12 + a] * t[i * 4 + 3];
1229
+ for (let s = 0; s < 4; s++)
1230
+ e[i * 4 + s] = r[0 + s] * t[i * 4 + 0] + r[4 + s] * t[i * 4 + 1] + r[8 + s] * t[i * 4 + 2] + r[12 + s] * t[i * 4 + 3];
902
1231
  return e;
903
1232
  }
904
- class ne {
1233
+ class Ts {
905
1234
  constructor(t) {
906
1235
  this.joints = t.joints, this.inverseBindMatrices = t.inverseBindMatrices, this.jointWeights = t.jointWeights, this.jointIndices = t.jointIndices, this.nodes = t.nodes, this.animations = t.animations, this.restPositions = null, this.restNormals = null, this.currentAnimIndex = 0, this.currentTime = 0, this.playing = !0, this.speed = 1, this.loop = !0, this.jointLocalTransforms = new Array(this.nodes.length), this.jointGlobalTransforms = new Array(this.nodes.length), this.jointFinalMatrices = new Array(this.joints.length);
907
1236
  for (let e = 0; e < this.nodes.length; e++)
@@ -925,33 +1254,33 @@ class ne {
925
1254
  async initGPUSkinning(t, e, i) {
926
1255
  try {
927
1256
  this._gpuDevice = t, this._gpuOutputBuffer = e;
928
- const a = this.restPositions.length / 3, r = new Float32Array(a * 8);
929
- for (let l = 0; l < a; l++) {
930
- const u = l * 8, d = l * 3, f = l * 2;
931
- r[u] = this.restPositions[d], r[u + 1] = this.restPositions[d + 1], r[u + 2] = this.restPositions[d + 2], r[u + 3] = this.restNormals[d], r[u + 4] = this.restNormals[d + 1], r[u + 5] = this.restNormals[d + 2], r[u + 6] = i ? i[f] : 0, r[u + 7] = i ? i[f + 1] : 0;
1257
+ const s = this.restPositions.length / 3, n = new Float32Array(s * 8);
1258
+ for (let l = 0; l < s; l++) {
1259
+ const u = l * 8, f = l * 3, h = l * 2;
1260
+ n[u] = this.restPositions[f], n[u + 1] = this.restPositions[f + 1], n[u + 2] = this.restPositions[f + 2], n[u + 3] = this.restNormals[f], n[u + 4] = this.restNormals[f + 1], n[u + 5] = this.restNormals[f + 2], n[u + 6] = i ? i[h] : 0, n[u + 7] = i ? i[h + 1] : 0;
932
1261
  }
933
1262
  this._gpuRestDataBuffer = t.createBuffer({
934
- size: r.byteLength,
1263
+ size: n.byteLength,
935
1264
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
936
1265
  label: "skinning_restData"
937
- }), t.queue.writeBuffer(this._gpuRestDataBuffer, 0, r), this._gpuJointWeightsBuffer = t.createBuffer({
1266
+ }), t.queue.writeBuffer(this._gpuRestDataBuffer, 0, n), this._gpuJointWeightsBuffer = t.createBuffer({
938
1267
  size: this.jointWeights.byteLength,
939
1268
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
940
1269
  label: "skinning_jointWeights"
941
1270
  }), t.queue.writeBuffer(this._gpuJointWeightsBuffer, 0, this.jointWeights);
942
- const n = new Uint32Array(this.jointIndices.length);
1271
+ const o = new Uint32Array(this.jointIndices.length);
943
1272
  for (let l = 0; l < this.jointIndices.length; l++)
944
- n[l] = this.jointIndices[l];
1273
+ o[l] = this.jointIndices[l];
945
1274
  this._gpuJointIndicesBuffer = t.createBuffer({
946
- size: n.byteLength,
1275
+ size: o.byteLength,
947
1276
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
948
1277
  label: "skinning_jointIndices"
949
- }), t.queue.writeBuffer(this._gpuJointIndicesBuffer, 0, n), this._gpuJointMatricesBuffer = t.createBuffer({
1278
+ }), t.queue.writeBuffer(this._gpuJointIndicesBuffer, 0, o), this._gpuJointMatricesBuffer = t.createBuffer({
950
1279
  size: this.joints.length * 16 * 4,
951
1280
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
952
1281
  label: "skinning_jointMatrices"
953
1282
  }), this._gpuJointMatricesData = new Float32Array(this.joints.length * 16);
954
- const { skinningComputeShader: o } = await Promise.resolve().then(() => Y), s = t.createBindGroupLayout({
1283
+ const { skinningComputeShader: a } = await Promise.resolve().then(() => _i), c = t.createBindGroupLayout({
955
1284
  entries: [
956
1285
  { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
957
1286
  { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
@@ -961,13 +1290,13 @@ class ne {
961
1290
  ]
962
1291
  });
963
1292
  this._gpuSkinningPipeline = t.createComputePipeline({
964
- layout: t.createPipelineLayout({ bindGroupLayouts: [s] }),
1293
+ layout: t.createPipelineLayout({ bindGroupLayouts: [c] }),
965
1294
  compute: {
966
- module: t.createShaderModule({ code: o }),
1295
+ module: t.createShaderModule({ code: a }),
967
1296
  entryPoint: "main"
968
1297
  }
969
1298
  }), this._gpuSkinningBindGroup = t.createBindGroup({
970
- layout: s,
1299
+ layout: c,
971
1300
  entries: [
972
1301
  { binding: 0, resource: { buffer: this._gpuRestDataBuffer } },
973
1302
  { binding: 1, resource: { buffer: this._gpuJointWeightsBuffer } },
@@ -975,9 +1304,9 @@ class ne {
975
1304
  { binding: 3, resource: { buffer: this._gpuJointMatricesBuffer } },
976
1305
  { binding: 4, resource: { buffer: this._gpuOutputBuffer } }
977
1306
  ]
978
- }), this._gpuVertexCount = a, this._gpuSkinningReady = !0, console.log(`GPU skinning initialized: ${a} vertices, ${this.joints.length} joints`);
979
- } catch (a) {
980
- console.warn("GPU skinning init failed, using CPU fallback:", a), this._gpuSkinningReady = !1;
1307
+ }), this._gpuVertexCount = s, this._gpuSkinningReady = !0, console.log(`GPU skinning initialized: ${s} vertices, ${this.joints.length} joints`);
1308
+ } catch (s) {
1309
+ console.warn("GPU skinning init failed, using CPU fallback:", s), this._gpuSkinningReady = !1;
981
1310
  }
982
1311
  }
983
1312
  /**
@@ -1027,48 +1356,48 @@ class ne {
1027
1356
  * Build topological order for node traversal (parent before child).
1028
1357
  */
1029
1358
  _buildTopologicalOrder() {
1030
- const t = /* @__PURE__ */ new Set(), e = [], i = (r) => {
1031
- if (t.has(r)) return;
1032
- t.add(r);
1033
- const n = this.nodes[r];
1359
+ const t = /* @__PURE__ */ new Set(), e = [], i = (n) => {
1360
+ if (t.has(n)) return;
1361
+ t.add(n);
1362
+ const o = this.nodes[n];
1363
+ for (const a of o.children)
1364
+ i(a);
1365
+ e.push(n);
1366
+ }, s = /* @__PURE__ */ new Set();
1367
+ for (const n of this.nodes)
1034
1368
  for (const o of n.children)
1035
- i(o);
1036
- e.push(r);
1037
- }, a = /* @__PURE__ */ new Set();
1038
- for (const r of this.nodes)
1039
- for (const n of r.children)
1040
- a.add(n);
1041
- for (let r = 0; r < this.nodes.length; r++)
1042
- a.has(r) || i(r);
1369
+ s.add(o);
1370
+ for (let n = 0; n < this.nodes.length; n++)
1371
+ s.has(n) || i(n);
1043
1372
  this.topologicalOrder = e.reverse();
1044
1373
  }
1045
1374
  /**
1046
1375
  * Sample a single channel at the given time.
1047
1376
  */
1048
1377
  _sampleChannel(t, e) {
1049
- const { timestamps: i, values: a, interpolation: r, targetPath: n } = t;
1378
+ const { timestamps: i, values: s, interpolation: n, targetPath: o } = t;
1050
1379
  if (e <= i[0])
1051
- return this._extractValue(a, 0, n);
1380
+ return this._extractValue(s, 0, o);
1052
1381
  if (e >= i[i.length - 1])
1053
- return this._extractValue(a, i.length - 1, n);
1054
- let o = 0, s = i.length - 1;
1055
- for (; s - o > 1; ) {
1056
- const p = Math.floor((o + s) / 2);
1057
- i[p] <= e ? o = p : s = p;
1382
+ return this._extractValue(s, i.length - 1, o);
1383
+ let a = 0, c = i.length - 1;
1384
+ for (; c - a > 1; ) {
1385
+ const S = Math.floor((a + c) / 2);
1386
+ i[S] <= e ? a = S : c = S;
1058
1387
  }
1059
- const l = i[o], u = i[s], d = (e - l) / (u - l), f = this._extractValue(a, o, n), h = this._extractValue(a, s, n);
1060
- return r === "STEP" ? f : n === "rotation" ? F(f, h, d) : z(f, h, d);
1388
+ const l = i[a], u = i[c], f = (e - l) / (u - l), h = this._extractValue(s, a, o), m = this._extractValue(s, c, o);
1389
+ return n === "STEP" ? h : o === "rotation" ? oi(h, m, f) : ai(h, m, f);
1061
1390
  }
1062
1391
  /**
1063
1392
  * Extract value from values array at the given index.
1064
1393
  */
1065
1394
  _extractValue(t, e, i) {
1066
1395
  if (i === "rotation") {
1067
- const a = e * 4;
1068
- return [t[a], t[a + 1], t[a + 2], t[a + 3]];
1396
+ const s = e * 4;
1397
+ return [t[s], t[s + 1], t[s + 2], t[s + 3]];
1069
1398
  } else {
1070
- const a = e * 3;
1071
- return [t[a], t[a + 1], t[a + 2]];
1399
+ const s = e * 3;
1400
+ return [t[s], t[s + 1], t[s + 2]];
1072
1401
  }
1073
1402
  }
1074
1403
  /**
@@ -1077,14 +1406,14 @@ class ne {
1077
1406
  _computeLocalTransforms(t) {
1078
1407
  const e = this.animations[this.currentAnimIndex];
1079
1408
  for (let i = 0; i < this.nodes.length; i++) {
1080
- const a = this.nodes[i];
1081
- let r = a.translation, n = a.rotation, o = a.scale;
1082
- for (const s of e.channels)
1083
- if (s.targetNode === i) {
1084
- const l = this._sampleChannel(s, t);
1085
- s.targetPath === "translation" ? r = l : s.targetPath === "rotation" ? n = l : s.targetPath === "scale" && (o = l);
1409
+ const s = this.nodes[i];
1410
+ let n = s.translation, o = s.rotation, a = s.scale;
1411
+ for (const c of e.channels)
1412
+ if (c.targetNode === i) {
1413
+ const l = this._sampleChannel(c, t);
1414
+ c.targetPath === "translation" ? n = l : c.targetPath === "rotation" ? o = l : c.targetPath === "scale" && (a = l);
1086
1415
  }
1087
- this.jointLocalTransforms[i] = re(r, n, o);
1416
+ this.jointLocalTransforms[i] = Ms(n, o, a);
1088
1417
  }
1089
1418
  }
1090
1419
  /**
@@ -1094,12 +1423,12 @@ class ne {
1094
1423
  const t = new Array(this.nodes.length).fill(-1);
1095
1424
  for (let e = 0; e < this.nodes.length; e++) {
1096
1425
  const i = this.nodes[e];
1097
- for (const a of i.children)
1098
- t[a] = e;
1426
+ for (const s of i.children)
1427
+ t[s] = e;
1099
1428
  }
1100
1429
  for (const e of this.topologicalOrder) {
1101
1430
  const i = t[e];
1102
- i === -1 ? this.jointGlobalTransforms[e] = this.jointLocalTransforms[e] : this.jointGlobalTransforms[e] = G(
1431
+ i === -1 ? this.jointGlobalTransforms[e] = this.jointLocalTransforms[e] : this.jointGlobalTransforms[e] = li(
1103
1432
  this.jointGlobalTransforms[i],
1104
1433
  this.jointLocalTransforms[e]
1105
1434
  );
@@ -1110,8 +1439,8 @@ class ne {
1110
1439
  */
1111
1440
  _computeFinalMatrices() {
1112
1441
  for (let t = 0; t < this.joints.length; t++) {
1113
- const e = this.joints[t], i = this.jointGlobalTransforms[e], a = t * 16, r = this.inverseBindMatrices.slice(a, a + 16);
1114
- this.jointFinalMatrices[t] = G(i, r);
1442
+ const e = this.joints[t], i = this.jointGlobalTransforms[e], s = t * 16, n = this.inverseBindMatrices.slice(s, s + 16);
1443
+ this.jointFinalMatrices[t] = li(i, n);
1115
1444
  }
1116
1445
  }
1117
1446
  /**
@@ -1119,30 +1448,30 @@ class ne {
1119
1448
  * Inlined math, no temporary array allocations.
1120
1449
  */
1121
1450
  _applySkinning() {
1122
- const t = this.restPositions.length / 3, e = this.restPositions, i = this.restNormals, a = this.skinnedPositions, r = this.skinnedNormals, n = this.jointWeights, o = this.jointIndices, s = this.jointFinalMatrices;
1451
+ const t = this.restPositions.length / 3, e = this.restPositions, i = this.restNormals, s = this.skinnedPositions, n = this.skinnedNormals, o = this.jointWeights, a = this.jointIndices, c = this.jointFinalMatrices;
1123
1452
  for (let l = 0; l < t; l++) {
1124
- const u = l * 3, d = l * 4, f = e[u], h = e[u + 1], p = e[u + 2], m = i[u], b = i[u + 1], S = i[u + 2];
1125
- let y = 0, P = 0, g = 0, x = 0, M = 0, R = 0;
1126
- for (let T = 0; T < 4; T++) {
1127
- const w = n[d + T];
1128
- if (w === 0) continue;
1129
- const v = s[o[d + T]];
1130
- y += (v[0] * f + v[4] * h + v[8] * p + v[12]) * w, P += (v[1] * f + v[5] * h + v[9] * p + v[13]) * w, g += (v[2] * f + v[6] * h + v[10] * p + v[14]) * w, x += (v[0] * m + v[4] * b + v[8] * S) * w, M += (v[1] * m + v[5] * b + v[9] * S) * w, R += (v[2] * m + v[6] * b + v[10] * S) * w;
1453
+ const u = l * 3, f = l * 4, h = e[u], m = e[u + 1], S = e[u + 2], R = i[u], D = i[u + 1], C = i[u + 2];
1454
+ let B = 0, A = 0, P = 0, _ = 0, T = 0, L = 0;
1455
+ for (let k = 0; k < 4; k++) {
1456
+ const X = o[f + k];
1457
+ if (X === 0) continue;
1458
+ const z = c[a[f + k]];
1459
+ B += (z[0] * h + z[4] * m + z[8] * S + z[12]) * X, A += (z[1] * h + z[5] * m + z[9] * S + z[13]) * X, P += (z[2] * h + z[6] * m + z[10] * S + z[14]) * X, _ += (z[0] * R + z[4] * D + z[8] * C) * X, T += (z[1] * R + z[5] * D + z[9] * C) * X, L += (z[2] * R + z[6] * D + z[10] * C) * X;
1131
1460
  }
1132
- const B = Math.sqrt(x * x + M * M + R * R);
1133
- B > 1e-4 && (r[u] = x / B, r[u + 1] = M / B, r[u + 2] = R / B), a[u] = y, a[u + 1] = P, a[u + 2] = g;
1461
+ const N = Math.sqrt(_ * _ + T * T + L * L);
1462
+ N > 1e-4 && (n[u] = _ / N, n[u + 1] = T / N, n[u + 2] = L / N), s[u] = B, s[u + 1] = A, s[u + 2] = P;
1134
1463
  }
1135
1464
  }
1136
1465
  }
1137
- function D(c) {
1138
- const t = atob(c), e = new Uint8Array(t.length);
1466
+ function ci(r) {
1467
+ const t = atob(r), e = new Uint8Array(t.length);
1139
1468
  for (let i = 0; i < t.length; i++)
1140
1469
  e[i] = t.charCodeAt(i);
1141
1470
  return e.buffer;
1142
1471
  }
1143
- class C {
1472
+ class bt {
1144
1473
  constructor(t, e) {
1145
- this.device = t, this.config = e, this.MAX_PARTICLES = e.maxParticles || 1e4, this.particleCount = e.particleCount || 100, this.activeParticles = 0, this.emitting = !1, this.currentEmissionTime = 0, this.particleData = new Float32Array(this.MAX_PARTICLES * 8), this.particleVelocities = new Float32Array(this.MAX_PARTICLES * 4), this.instanceBuffer = t.createBuffer({
1474
+ this.device = t, this.config = e, this.MAX_PARTICLES = e.maxParticles || 1e4, this.particleCount = e.particleCount || 100, this.activeParticles = 0, this.emitting = !1, this.currentEmissionTime = 0, this.destroyed = !1, this.particleData = new Float32Array(this.MAX_PARTICLES * 8), this.particleVelocities = new Float32Array(this.MAX_PARTICLES * 4), this.instanceBuffer = t.createBuffer({
1146
1475
  size: this.MAX_PARTICLES * 8 * 4,
1147
1476
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
1148
1477
  label: "particleInstanceBuffer"
@@ -1157,8 +1486,8 @@ class C {
1157
1486
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
1158
1487
  label: "particleTrailBuffer"
1159
1488
  }), this._trailResetData = new Float32Array(this.MAX_PARTICLES * 4), this.appearanceUniformBuffer = t.createBuffer({
1160
- size: 176,
1161
- // appearance uniforms + pulse + GLB rotation + system offset + sim rotation
1489
+ size: 208,
1490
+ // appearance uniforms + pulse + GLB rotation + system offset + sim rotation + noise distortion
1162
1491
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
1163
1492
  label: "appearanceUniformBuffer"
1164
1493
  }), this.bloomIntensityBuffer = t.createBuffer({
@@ -1166,7 +1495,7 @@ class C {
1166
1495
  // intensity (f32) + padding
1167
1496
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
1168
1497
  label: "systemBloomIntensityBuffer"
1169
- }), e.overrideXVelocity === void 0 && (e.overrideXVelocity = !1), e.overrideYVelocity === void 0 && (e.overrideYVelocity = !1), e.overrideZVelocity === void 0 && (e.overrideZVelocity = !1), e.xVelocity === void 0 && (e.xVelocity = 0), e.yVelocity === void 0 && (e.yVelocity = 0), e.zVelocity === void 0 && (e.zVelocity = 0), e.textureEnabled === void 0 && (e.textureEnabled = !1), e.glbModelEnabled === void 0 && (e.glbModelEnabled = !1), e.textureType === void 0 && (e.textureType = "image"), e.glbFileName === void 0 && (e.glbFileName = null), e.animationIndex === void 0 && (e.animationIndex = 0), e.animationSpeed === void 0 && (e.animationSpeed = 1), e.animationLoop === void 0 && (e.animationLoop = !0), e.useGlbTexture === void 0 && (e.useGlbTexture = !1), e.glbHasTexture === void 0 && (e.glbHasTexture = !1), e.particleShape === void 0 && (e.particleShape = "square"), e.particleShapeRotation === void 0 && (e.particleShapeRotation = 0), e.particleShapeRotationX === void 0 && (e.particleShapeRotationX = 0), e.particleShapeRotationY === void 0 && (e.particleShapeRotationY = 0), e.particleShapeRotationZ === void 0 && (e.particleShapeRotationZ = 0), e.particleColor === void 0 && (e.particleColor = [1, 1, 1]), e.startColor === void 0 && (e.startColor = [1, 0, 0]), e.endColor === void 0 && (e.endColor = [0, 0, 1]), e.fadeEnabled === void 0 && (e.fadeEnabled = !0), e.colorTransitionEnabled === void 0 && (e.colorTransitionEnabled = !1), e.randomColorEnabled === void 0 && (e.randomColorEnabled = !1), e.randomColors === void 0 && (e.randomColors = []), e.particleSize === void 0 && (e.particleSize = 0.5), e.particleSpeed === void 0 && (e.particleSpeed = 1), e.opacity === void 0 && (e.opacity = 1), e.aspectRatio === void 0 && (e.aspectRatio = 1), e.rotation === void 0 && (e.rotation = 0), e.rotationMode === void 0 && (e.rotationMode = "fixed"), e.minRotation === void 0 && (e.minRotation = 0), e.maxRotation === void 0 && (e.maxRotation = 90), e.randomSize === void 0 && (e.randomSize = !1), e.minSize === void 0 && (e.minSize = 0.1), e.maxSize === void 0 && (e.maxSize = 0.5), e.randomSpeed === void 0 && (e.randomSpeed = !1), e.minSpeed === void 0 && (e.minSpeed = 0.1), e.maxSpeed === void 0 && (e.maxSpeed = 1), e.fadeSizeEnabled === void 0 && (e.fadeSizeEnabled = !1), e.increaseSizeEnabled === void 0 && (e.increaseSizeEnabled = !1), e.sizeLifetimeSpeed === void 0 && (e.sizeLifetimeSpeed = 1), e.bloomEnabled === void 0 && (e.bloomEnabled = !0), e.bloomIntensity === void 0 && (e.bloomIntensity = 1), e.bloomColor === void 0 && (e.bloomColor = [1, 1, 1]), e.gravityEnabled === void 0 && (e.gravityEnabled = !1), e.gravityStrength === void 0 && (e.gravityStrength = 2), e.dampingEnabled === void 0 && (e.dampingEnabled = !1), e.dampingStrength === void 0 && (e.dampingStrength = 1), e.attractorEnabled === void 0 && (e.attractorEnabled = !1), e.attractorStrength === void 0 && (e.attractorStrength = 1), e.attractorPosition === void 0 && (e.attractorPosition = [0, 0, 0]), e.burstMode === void 0 && (e.burstMode = !1), e.emissionShape === void 0 && (e.emissionShape = "cube"), e.lifetime === void 0 && (e.lifetime = 5), e.emissionRate === void 0 && (e.emissionRate = 10), e.emissionDuration === void 0 && (e.emissionDuration = 10), e.cubeLength === void 0 && (e.cubeLength = 2), e.outerLength === void 0 && (e.outerLength = 2), e.innerLength === void 0 && (e.innerLength = 0), e.outerRadius === void 0 && (e.outerRadius = 2), e.innerRadius === void 0 && (e.innerRadius = 0), e.squareSize === void 0 && (e.squareSize = 2), e.squareInnerSize === void 0 && (e.squareInnerSize = 0), e.circleInnerRadius === void 0 && (e.circleInnerRadius = 0), e.circleOuterRadius === void 0 && (e.circleOuterRadius = 2), e.circleVelocityDirection === void 0 && (e.circleVelocityDirection = "outward"), e.cylinderInnerRadius === void 0 && (e.cylinderInnerRadius = 0), e.cylinderOuterRadius === void 0 && (e.cylinderOuterRadius = 2), e.cylinderHeight === void 0 && (e.cylinderHeight = 4), e.cylinderVelocityDirection === void 0 && (e.cylinderVelocityDirection = "outward"), e.planeWidth === void 0 && (e.planeWidth = 2), e.planeDepth === void 0 && (e.planeDepth = 2), e.coneOuterRadius === void 0 && (e.coneOuterRadius = 2), e.coneInnerRadius === void 0 && (e.coneInnerRadius = 0), e.coneHeight === void 0 && (e.coneHeight = 4), e.torusMajorRadius === void 0 && (e.torusMajorRadius = 2), e.torusMinorRadius === void 0 && (e.torusMinorRadius = 0.5), e.lineLength === void 0 && (e.lineLength = 4), e.hemisphereOuterRadius === void 0 && (e.hemisphereOuterRadius = 2), e.hemisphereInnerRadius === void 0 && (e.hemisphereInnerRadius = 0), e.discRadius === void 0 && (e.discRadius = 2), e.annulusInnerRadius === void 0 && (e.annulusInnerRadius = 1), e.annulusOuterRadius === void 0 && (e.annulusOuterRadius = 2), e.capsuleRadius === void 0 && (e.capsuleRadius = 0.5), e.capsuleHeight === void 0 && (e.capsuleHeight = 4), e.arcStartAngle === void 0 && (e.arcStartAngle = 0), e.arcEndAngle === void 0 && (e.arcEndAngle = 180), e.arcInnerRadius === void 0 && (e.arcInnerRadius = 0), e.arcOuterRadius === void 0 && (e.arcOuterRadius = 2), e.spiralTurns === void 0 && (e.spiralTurns = 3), e.spiralRadiusStart === void 0 && (e.spiralRadiusStart = 0.5), e.spiralRadiusEnd === void 0 && (e.spiralRadiusEnd = 2), e.spiralHeight === void 0 && (e.spiralHeight = 4), e.frustumRadiusNear === void 0 && (e.frustumRadiusNear = 0.5), e.frustumRadiusFar === void 0 && (e.frustumRadiusFar = 2), e.frustumHeight === void 0 && (e.frustumHeight = 4), e.cubeSurfaceSize === void 0 && (e.cubeSurfaceSize = 2), e.sphereSurfaceRadius === void 0 && (e.sphereSurfaceRadius = 2), e.boxFrameSize === void 0 && (e.boxFrameSize = 2), e.polygonSides === void 0 && (e.polygonSides = 6), e.polygonRadius === void 0 && (e.polygonRadius = 2), e.shapeRotationX === void 0 && (e.shapeRotationX = 0), e.shapeRotationY === void 0 && (e.shapeRotationY = 0), e.shapeRotationZ === void 0 && (e.shapeRotationZ = 0), e.shapeTranslationX === void 0 && (e.shapeTranslationX = 0), e.shapeTranslationY === void 0 && (e.shapeTranslationY = 0), e.shapeTranslationZ === void 0 && (e.shapeTranslationZ = 0), e.pulseEnabled === void 0 && (e.pulseEnabled = !1), e.pulseAmplitude === void 0 && (e.pulseAmplitude = 0.5), e.pulseFrequency === void 0 && (e.pulseFrequency = 1), e.pulsePhaseRandom === void 0 && (e.pulsePhaseRandom = 0), e.pulseOpacity === void 0 && (e.pulseOpacity = !1), e.confinementEnabled === void 0 && (e.confinementEnabled = !1), e.confinementShape === void 0 && (e.confinementShape = "box"), e.confinementMode === void 0 && (e.confinementMode = "bounce"), e.confinementSpace === void 0 && (e.confinementSpace = "world"), e.confinementBoxHalfSize === void 0 && (e.confinementBoxHalfSize = [2, 2, 2]), e.confinementSphereRadius === void 0 && (e.confinementSphereRadius = 3), e.confinementRestitution === void 0 && (e.confinementRestitution = 0.8), e.confinementFriction === void 0 && (e.confinementFriction = 0.1), e.softBoundaryEnabled === void 0 && (e.softBoundaryEnabled = !1), e.softBoundaryStrength === void 0 && (e.softBoundaryStrength = 5), e.softBoundaryFalloff === void 0 && (e.softBoundaryFalloff = 0.5), e.depthWriteEnabled === void 0 && (e.depthWriteEnabled = !1), e.velocityStretchEnabled === void 0 && (e.velocityStretchEnabled = !1), e.velocityStretchFactor === void 0 && (e.velocityStretchFactor = 1), e.emissionTrailEnabled === void 0 && (e.emissionTrailEnabled = !1), e.emissionTrailDuration === void 0 && (e.emissionTrailDuration = 1), e.emissionTrailWidth === void 0 && (e.emissionTrailWidth = 0.3), e.emissionTrailMinDistance === void 0 && (e.emissionTrailMinDistance = 0.05), e.emissionTrailMaxPoints === void 0 && (e.emissionTrailMaxPoints = 256), e.emissionTrailSegments === void 0 && (e.emissionTrailSegments = 8), e.emissionTrailShape === void 0 && (e.emissionTrailShape = "straight"), e.emissionTrailShapeAmplitude === void 0 && (e.emissionTrailShapeAmplitude = 0.1), e.emissionTrailShapeFrequency === void 0 && (e.emissionTrailShapeFrequency = 4), e.emissionTrailShapeSpeed === void 0 && (e.emissionTrailShapeSpeed = 0), e.shapeDisplay === void 0 && (e.shapeDisplay = !0), e.followSystemTranslation === void 0 && (e.followSystemTranslation = !0), e.followSystemId === void 0 && (e.followSystemId = null), this._newEmissions = [], this._emptyEmissions = [], this._pendingFollowEmissions = this._emptyEmissions, this.glbVertexBuffer = null, this.glbIndexBuffer = null, this.glbIndexCount = 0, this.glbIndexFormat = "uint16", this.glbMeshData = null, this.glbRawArrayBuffer = null, this.glbAnimator = null, this.glbAnimated = !1, this._glbInterleavedData = null, this._appearanceData = new Float32Array(44), this._bloomIntensityData = new Float32Array(16), this._simPosition = [0, 0, 0], this._simVelocity = [0, 0, 0], this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0, this.emitter = new Z(e), this.physics = new q(t, this.MAX_PARTICLES), this.textureManager = new $(t), e.gravityEnabled && this.setGravity(e.gravityStrength || 0), e.dampingEnabled && this.physics.setDamping(e.dampingStrength || 0), e.attractorEnabled && e.attractorPosition && this.setAttractor(e.attractorStrength || 0, e.attractorPosition), e.confinementEnabled && this.setConfinement({
1498
+ }), e.overrideXVelocity === void 0 && (e.overrideXVelocity = !1), e.overrideYVelocity === void 0 && (e.overrideYVelocity = !1), e.overrideZVelocity === void 0 && (e.overrideZVelocity = !1), e.xVelocity === void 0 && (e.xVelocity = 0), e.yVelocity === void 0 && (e.yVelocity = 0), e.zVelocity === void 0 && (e.zVelocity = 0), e.textureEnabled === void 0 && (e.textureEnabled = !1), e.glbModelEnabled === void 0 && (e.glbModelEnabled = !1), e.textureType === void 0 && (e.textureType = "image"), e.glbFileName === void 0 && (e.glbFileName = null), e.animationIndex === void 0 && (e.animationIndex = 0), e.animationSpeed === void 0 && (e.animationSpeed = 1), e.animationLoop === void 0 && (e.animationLoop = !0), e.useGlbTexture === void 0 && (e.useGlbTexture = !1), e.glbHasTexture === void 0 && (e.glbHasTexture = !1), e.particleShape === void 0 && (e.particleShape = "square"), e.particleShapeRotation !== void 0 && (e.rotation = (e.rotation || 0) + e.particleShapeRotation, delete e.particleShapeRotation), e.particleShapeRotationX === void 0 && (e.particleShapeRotationX = 0), e.particleShapeRotationY === void 0 && (e.particleShapeRotationY = 0), e.particleShapeRotationZ === void 0 && (e.particleShapeRotationZ = 0), e.particleColor === void 0 && (e.particleColor = [1, 1, 1]), e.startColor === void 0 && (e.startColor = [1, 0, 0]), e.endColor === void 0 && (e.endColor = [0, 0, 1]), e.fadeEnabled === void 0 && (e.fadeEnabled = !0), e.colorTransitionEnabled === void 0 && (e.colorTransitionEnabled = !1), e.randomColorEnabled === void 0 && (e.randomColorEnabled = !1), e.randomColors === void 0 && (e.randomColors = []), e.particleSize === void 0 && (e.particleSize = 0.1), e.particleSpeed === void 0 && (e.particleSpeed = 1), e.opacity === void 0 && (e.opacity = 1), e.aspectRatio === void 0 && (e.aspectRatio = 1), e.rotation === void 0 && (e.rotation = 0), e.rotationMode === void 0 && (e.rotationMode = "fixed"), e.minRotation === void 0 && (e.minRotation = 0), e.maxRotation === void 0 && (e.maxRotation = 90), e.randomSize === void 0 && (e.randomSize = !1), e.minSize === void 0 && (e.minSize = 0.05), e.maxSize === void 0 && (e.maxSize = 0.15), e.randomSpeed === void 0 && (e.randomSpeed = !1), e.minSpeed === void 0 && (e.minSpeed = 0.1), e.maxSpeed === void 0 && (e.maxSpeed = 1), e.fadeSizeEnabled === void 0 && (e.fadeSizeEnabled = !1), e.increaseSizeEnabled === void 0 && (e.increaseSizeEnabled = !1), e.sizeLifetimeSpeed === void 0 && (e.sizeLifetimeSpeed = 1), e.bloomEnabled === void 0 && (e.bloomEnabled = !0), e.bloomIntensity === void 0 && (e.bloomIntensity = 1), e.bloomColor === void 0 && (e.bloomColor = [1, 1, 1]), e.gravityEnabled === void 0 && (e.gravityEnabled = !1), e.gravityStrength === void 0 && (e.gravityStrength = 2), e.dampingEnabled === void 0 && (e.dampingEnabled = !1), e.dampingStrength === void 0 && (e.dampingStrength = 1), e.attractorEnabled === void 0 && (e.attractorEnabled = !1), e.attractorStrength === void 0 && (e.attractorStrength = 1), e.attractorPosition === void 0 && (e.attractorPosition = [0, 0, 0]), e.burstMode === void 0 && (e.burstMode = !1), e.emissionShape === void 0 && (e.emissionShape = "cube"), e.lifetime === void 0 && (e.lifetime = 5), e.emissionRate === void 0 && (e.emissionRate = 10), e.emissionDuration === void 0 && (e.emissionDuration = 10), e.emissionDurationInfinite === void 0 && (e.emissionDurationInfinite = !1), e.emissionDuration > 300 && (e.emissionDurationInfinite = !0, e.emissionDuration = 10), e.outerLength === void 0 && (e.outerLength = e.cubeLength ?? 2), e.innerLength === void 0 && (e.innerLength = 0), e.outerRadius === void 0 && (e.outerRadius = 2), e.innerRadius === void 0 && (e.innerRadius = 0), e.squareSize === void 0 && (e.squareSize = 2), e.squareInnerSize === void 0 && (e.squareInnerSize = 0), e.circleInnerRadius === void 0 && (e.circleInnerRadius = 0), e.circleOuterRadius === void 0 && (e.circleOuterRadius = 2), e.circleVelocityDirection === void 0 && (e.circleVelocityDirection = "outward"), e.cylinderInnerRadius === void 0 && (e.cylinderInnerRadius = 0), e.cylinderOuterRadius === void 0 && (e.cylinderOuterRadius = 2), e.cylinderHeight === void 0 && (e.cylinderHeight = 4), e.cylinderVelocityDirection === void 0 && (e.cylinderVelocityDirection = "outward"), e.planeWidth === void 0 && (e.planeWidth = 2), e.planeDepth === void 0 && (e.planeDepth = 2), e.coneOuterRadius === void 0 && (e.coneOuterRadius = 2), e.coneInnerRadius === void 0 && (e.coneInnerRadius = 0), e.coneHeight === void 0 && (e.coneHeight = 4), e.torusMajorRadius === void 0 && (e.torusMajorRadius = 2), e.torusMinorRadius === void 0 && (e.torusMinorRadius = 0.5), e.lineLength === void 0 && (e.lineLength = 4), e.hemisphereOuterRadius === void 0 && (e.hemisphereOuterRadius = 2), e.hemisphereInnerRadius === void 0 && (e.hemisphereInnerRadius = 0), e.discRadius === void 0 && (e.discRadius = 2), e.annulusInnerRadius === void 0 && (e.annulusInnerRadius = 1), e.annulusOuterRadius === void 0 && (e.annulusOuterRadius = 2), e.capsuleRadius === void 0 && (e.capsuleRadius = 0.5), e.capsuleHeight === void 0 && (e.capsuleHeight = 4), e.arcStartAngle === void 0 && (e.arcStartAngle = 0), e.arcEndAngle === void 0 && (e.arcEndAngle = 180), e.arcInnerRadius === void 0 && (e.arcInnerRadius = 0), e.arcOuterRadius === void 0 && (e.arcOuterRadius = 2), e.spiralTurns === void 0 && (e.spiralTurns = 3), e.spiralRadiusStart === void 0 && (e.spiralRadiusStart = 0.5), e.spiralRadiusEnd === void 0 && (e.spiralRadiusEnd = 2), e.spiralHeight === void 0 && (e.spiralHeight = 4), e.frustumRadiusNear === void 0 && (e.frustumRadiusNear = 0.5), e.frustumRadiusFar === void 0 && (e.frustumRadiusFar = 2), e.frustumHeight === void 0 && (e.frustumHeight = 4), e.cubeSurfaceSize === void 0 && (e.cubeSurfaceSize = 2), e.sphereSurfaceRadius === void 0 && (e.sphereSurfaceRadius = 2), e.boxFrameSize === void 0 && (e.boxFrameSize = 2), e.polygonSides === void 0 && (e.polygonSides = 6), e.polygonRadius === void 0 && (e.polygonRadius = 2), e.emissionRotationX === void 0 && (e.emissionRotationX = 0), e.emissionRotationY === void 0 && (e.emissionRotationY = 0), e.emissionRotationZ === void 0 && (e.emissionRotationZ = 0), e.emissionPositionX === void 0 && (e.emissionPositionX = e.emissionTranslationX ?? 0), e.emissionPositionY === void 0 && (e.emissionPositionY = e.emissionTranslationY ?? 0), e.emissionPositionZ === void 0 && (e.emissionPositionZ = e.emissionTranslationZ ?? 0), e.pulseEnabled === void 0 && (e.pulseEnabled = !1), e.pulseAmplitude === void 0 && (e.pulseAmplitude = 0.5), e.pulseFrequency === void 0 && (e.pulseFrequency = 1), e.pulsePhaseRandom === void 0 && (e.pulsePhaseRandom = 0), e.pulseOpacity === void 0 && (e.pulseOpacity = !1), e.confinementEnabled === void 0 && (e.confinementEnabled = !1), e.confinementShape === void 0 && (e.confinementShape = "box"), e.confinementMode === void 0 && (e.confinementMode = "bounce"), e.confinementSpace === void 0 && (e.confinementSpace = "world"), e.confinementBoxHalfSize === void 0 && (e.confinementBoxHalfSize = [2, 2, 2]), e.confinementSphereRadius === void 0 && (e.confinementSphereRadius = 3), e.confinementRestitution === void 0 && (e.confinementRestitution = 0.8), e.confinementFriction === void 0 && (e.confinementFriction = 0.1), e.softBoundaryEnabled === void 0 && (e.softBoundaryEnabled = !1), e.softBoundaryStrength === void 0 && (e.softBoundaryStrength = 5), e.softBoundaryFalloff === void 0 && (e.softBoundaryFalloff = 0.5), e.depthWriteEnabled === void 0 && (e.depthWriteEnabled = !1), e.velocityStretchEnabled === void 0 && (e.velocityStretchEnabled = !1), e.velocityStretchFactor === void 0 && (e.velocityStretchFactor = 1), e.blendMode === void 0 && (e.blendMode = "normal"), e.noiseDistortEnabled === void 0 && (e.noiseDistortEnabled = !1), e.noiseTilingX === void 0 && (e.noiseTilingX = 3), e.noiseTilingY === void 0 && (e.noiseTilingY = 3), e.noiseSpeed === void 0 && (e.noiseSpeed = -1.5), e.noiseAmplitude === void 0 && (e.noiseAmplitude = 0.08), e.emissionTrailEnabled === void 0 && (e.emissionTrailEnabled = !1), e.emissionTrailDuration === void 0 && (e.emissionTrailDuration = 1), e.emissionTrailWidth === void 0 && (e.emissionTrailWidth = 0.3), e.emissionTrailMinDistance === void 0 && (e.emissionTrailMinDistance = 0.05), e.emissionTrailMaxPoints === void 0 && (e.emissionTrailMaxPoints = 256), e.emissionTrailSegments === void 0 && (e.emissionTrailSegments = 8), e.emissionTrailMode === void 0 && (e.emissionTrailMode = "ribbon"), e.emissionTrailShape === void 0 && (e.emissionTrailShape = "straight"), e.emissionTrailShapeAmplitude === void 0 && (e.emissionTrailShapeAmplitude = 0.1), e.emissionTrailShapeFrequency === void 0 && (e.emissionTrailShapeFrequency = 4), e.emissionTrailShapeSpeed === void 0 && (e.emissionTrailShapeSpeed = 0), e.shapeDisplay === void 0 && (e.shapeDisplay = !0), e.followSystemTranslation === void 0 && (e.followSystemTranslation = !0), e.followSystemId === void 0 && (e.followSystemId = null), this._newEmissions = [], this._emptyEmissions = [], this._pendingFollowEmissions = this._emptyEmissions, this.glbVertexBuffer = null, this.glbIndexBuffer = null, this.glbIndexCount = 0, this.glbIndexFormat = "uint16", this.glbMeshData = null, this.glbRawArrayBuffer = null, this.glbAnimator = null, this.glbAnimated = !1, this._glbInterleavedData = null, this._appearanceData = new Float32Array(52), this._bloomIntensityData = new Float32Array(16), this._simPosition = [0, 0, 0], this._simVelocity = [0, 0, 0], this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0, this._emitSimRotY = 0, this.emitter = new cs(e), this.physics = new us(t, this.MAX_PARTICLES), this.textureManager = new ds(t), e.gravityEnabled && this.setGravity(e.gravityStrength || 0), e.dampingEnabled && this.physics.setDamping(e.dampingStrength || 0), e.attractorEnabled && e.attractorPosition && this.setAttractor(e.attractorStrength || 0, e.attractorPosition), e.confinementEnabled && this.setConfinement({
1170
1499
  enabled: !0,
1171
1500
  shape: e.confinementShape,
1172
1501
  mode: e.confinementMode,
@@ -1179,26 +1508,33 @@ class C {
1179
1508
  enabled: !0,
1180
1509
  strength: e.softBoundaryStrength,
1181
1510
  falloff: e.softBoundaryFalloff
1182
- }), this.particleTexture = this.textureManager.getDefaultTexture(), this.updateBloomIntensity(), this.updateAppearanceUniform(), this.frameCount = 0, this.shouldReset = !1, this.initComputePipeline(t);
1511
+ }), this.particleTexture = this.textureManager.getDefaultTexture(), this.updateBloomIntensity(), this.updateAppearanceUniform(), this.frameCount = 0, this.shouldReset = !1, this._scriptParticleData = new Float32Array(this.MAX_PARTICLES * 8), this._scriptVelocityData = new Float32Array(this.MAX_PARTICLES * 4), this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptFrame = 0, this._scriptTime = 0, this._scriptConfigRestored = !1, this._particleScript = null, e.script && (this._particleScript = new si(e.script, e, this.MAX_PARTICLES)), this.initComputePipeline(t);
1183
1512
  }
1184
1513
  async initComputePipeline(t) {
1185
1514
  this.computeReady = await this.physics.initComputePipeline(this.instanceBuffer, this.velocityBuffer, this.trailBuffer);
1186
1515
  }
1516
+ /**
1517
+ * Set or clear the per-frame CPU script for this particle system.
1518
+ * @param {string|null} source - Script source code, or null to disable
1519
+ */
1520
+ setScript(t) {
1521
+ this._particleScript && (this._particleScript.destroy(), this._particleScript = null), this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptFrame = 0, this._scriptTime = 0, this._scriptConfigRestored = !1, t ? (this.config.script = t, this._particleScript = new si(t, this.config, this.MAX_PARTICLES), this._particleScript.snapshotConfig(this.config)) : delete this.config.script;
1522
+ }
1187
1523
  async setTexture(t) {
1188
- this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = await this.textureManager.loadTexture(t), this.config.textureEnabled = !0, this.updateAppearanceUniform(), this.updateBuffers();
1524
+ this.destroyed || (this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = await this.textureManager.loadTexture(t), this.config.textureEnabled = !0, this.updateAppearanceUniform(), this.updateBuffers());
1189
1525
  }
1190
1526
  resetTexture() {
1191
- this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = this.textureManager.getDefaultTexture(), this.config.textureEnabled = !1, this.updateAppearanceUniform(), this.updateBuffers();
1527
+ this.destroyed || (this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = this.textureManager.getDefaultTexture(), this.config.textureEnabled = !1, this.updateAppearanceUniform(), this.updateBuffers());
1192
1528
  }
1193
1529
  async setGLBModel(t) {
1194
1530
  try {
1195
1531
  this.glbRawArrayBuffer = t;
1196
- const e = await O(t);
1532
+ const e = await gi(t);
1197
1533
  this.glbMeshData = e, this.config.glbHasTexture = e.hasBaseColorTexture || !1;
1198
1534
  const i = new Float32Array(e.vertexCount * 8);
1199
- for (let a = 0; a < e.vertexCount; a++) {
1200
- const r = a * 8, n = a * 3, o = a * 2;
1201
- i[r + 0] = e.positions[n + 0], i[r + 1] = e.positions[n + 1], i[r + 2] = e.positions[n + 2], i[r + 3] = e.normals[n + 0], i[r + 4] = e.normals[n + 1], i[r + 5] = e.normals[n + 2], e.texCoords ? (i[r + 6] = e.texCoords[o + 0], i[r + 7] = e.texCoords[o + 1]) : (i[r + 6] = 0, i[r + 7] = 0);
1535
+ for (let s = 0; s < e.vertexCount; s++) {
1536
+ const n = s * 8, o = s * 3, a = s * 2;
1537
+ i[n + 0] = e.positions[o + 0], i[n + 1] = e.positions[o + 1], i[n + 2] = e.positions[o + 2], i[n + 3] = e.normals[o + 0], i[n + 4] = e.normals[o + 1], i[n + 5] = e.normals[o + 2], e.texCoords ? (i[n + 6] = e.texCoords[a + 0], i[n + 7] = e.texCoords[a + 1]) : (i[n + 6] = 0, i[n + 7] = 0);
1202
1538
  }
1203
1539
  if (this.glbVertexBuffer && this.glbVertexBuffer.destroy(), this.glbIndexBuffer && this.glbIndexBuffer.destroy(), this.glbVertexBuffer = this.device.createBuffer({
1204
1540
  size: i.byteLength,
@@ -1209,11 +1545,11 @@ class C {
1209
1545
  usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
1210
1546
  label: "glbIndexBuffer"
1211
1547
  }), this.device.queue.writeBuffer(this.glbIndexBuffer, 0, e.indices), this.glbIndexCount = e.indexCount, this.glbIndexFormat = e.indices instanceof Uint32Array ? "uint32" : "uint16", this.config.glbModelEnabled = !0, this.config.textureType = "glb", e.animationData) {
1212
- this.glbAnimator = new ne(e.animationData), this.glbAnimator.setRestPose(e.positions, e.normals), this.glbAnimated = !0, this.config.glbAnimated = !0, this.glbAnimator.loop = this.config.animationLoop, this._glbInterleavedData = new Float32Array(e.vertexCount * 8);
1548
+ this.glbAnimator = new Ts(e.animationData), this.glbAnimator.setRestPose(e.positions, e.normals), this.glbAnimated = !0, this.config.glbAnimated = !0, this.glbAnimator.loop = this.config.animationLoop, this._glbInterleavedData = new Float32Array(e.vertexCount * 8);
1213
1549
  try {
1214
1550
  await this.glbAnimator.initGPUSkinning(this.device, this.glbVertexBuffer, e.texCoords);
1215
- } catch (a) {
1216
- console.warn("GPU skinning init failed, using CPU fallback:", a);
1551
+ } catch (s) {
1552
+ console.warn("GPU skinning init failed, using CPU fallback:", s);
1217
1553
  }
1218
1554
  console.log(`GLB animated model loaded: ${e.animationData.animations.length} animations`);
1219
1555
  } else
@@ -1236,21 +1572,21 @@ class C {
1236
1572
  */
1237
1573
  setSimulationTransform(t) {
1238
1574
  if (t.position && (this._simPosition[0] = t.position[0], this._simPosition[1] = t.position[1], this._simPosition[2] = t.position[2]), t.rotation) {
1239
- this._simRotX = t.rotation[0], this._simRotZ = t.rotation[1];
1240
- const e = Math.cos(this._simRotX), i = Math.sin(this._simRotX), a = Math.cos(this._simRotZ), r = Math.sin(this._simRotZ);
1575
+ this._simRotX = t.rotation[0] || 0, this._simRotZ = t.rotation[1] || 0, this._simRotY = t.rotation[2] || 0;
1576
+ const e = Math.cos(this._simRotX), i = Math.sin(this._simRotX), s = Math.cos(this._simRotZ), n = Math.sin(this._simRotZ), o = Math.cos(this._simRotY), a = Math.sin(this._simRotY);
1241
1577
  this._simRotMatrix = [
1242
- a,
1243
- -r * e,
1244
- r * i,
1245
- r,
1246
- a * e,
1247
- -a * i,
1248
- 0,
1249
- i,
1250
- e
1578
+ o * s,
1579
+ -o * n * e + a * i,
1580
+ o * n * i + a * e,
1581
+ n,
1582
+ s * e,
1583
+ -s * i,
1584
+ -a * s,
1585
+ a * n * e + o * i,
1586
+ -a * n * i + o * e
1251
1587
  ];
1252
1588
  } else
1253
- this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0;
1589
+ this._simRotMatrix = null, this._simRotX = 0, this._simRotZ = 0, this._simRotY = 0;
1254
1590
  t.velocity && (this._simVelocity[0] = t.velocity[0], this._simVelocity[1] = t.velocity[1], this._simVelocity[2] = t.velocity[2]);
1255
1591
  }
1256
1592
  clearSimulationTransform() {
@@ -1261,19 +1597,20 @@ class C {
1261
1597
  if (this.glbAnimator._gpuSkinningReady)
1262
1598
  return !0;
1263
1599
  const t = this.glbAnimator.skinnedPositions, e = this.glbAnimator.skinnedNormals, i = this.glbMeshData.texCoords;
1264
- for (let a = 0; a < this.glbMeshData.vertexCount; a++) {
1265
- const r = a * 8, n = a * 3, o = a * 2;
1266
- this._glbInterleavedData[r] = t[n], this._glbInterleavedData[r + 1] = t[n + 1], this._glbInterleavedData[r + 2] = t[n + 2], this._glbInterleavedData[r + 3] = e[n], this._glbInterleavedData[r + 4] = e[n + 1], this._glbInterleavedData[r + 5] = e[n + 2], i ? (this._glbInterleavedData[r + 6] = i[o], this._glbInterleavedData[r + 7] = i[o + 1]) : (this._glbInterleavedData[r + 6] = 0, this._glbInterleavedData[r + 7] = 0);
1600
+ for (let s = 0; s < this.glbMeshData.vertexCount; s++) {
1601
+ const n = s * 8, o = s * 3, a = s * 2;
1602
+ this._glbInterleavedData[n] = t[o], this._glbInterleavedData[n + 1] = t[o + 1], this._glbInterleavedData[n + 2] = t[o + 2], this._glbInterleavedData[n + 3] = e[o], this._glbInterleavedData[n + 4] = e[o + 1], this._glbInterleavedData[n + 5] = e[o + 2], i ? (this._glbInterleavedData[n + 6] = i[a], this._glbInterleavedData[n + 7] = i[a + 1]) : (this._glbInterleavedData[n + 6] = 0, this._glbInterleavedData[n + 7] = 0);
1267
1603
  }
1268
1604
  return this.device.queue.writeBuffer(this.glbVertexBuffer, 0, this._glbInterleavedData), !0;
1269
1605
  }
1270
1606
  updateAppearanceUniform() {
1607
+ if (this.destroyed) return;
1271
1608
  let t = 0;
1272
1609
  this.config.rotationMode === "random" ? t = 1 : this.config.rotationMode === "velocity" && (t = 2);
1273
- const i = { square: 0, circle: 1, triangle: 2, diamond: 3, star: 4, hexagon: 5, ring: 6, heart: 7, cross: 8, spark: 9, leaf: 10, capsule: 11, crescent: 12, line: 13, "curved-line": 14 }[this.config.particleShape] ?? 0, a = this._appearanceData;
1274
- a[0] = this.config.fadeEnabled ? 1 : 0, a[1] = this.config.randomColorEnabled ? 2 : this.config.colorTransitionEnabled ? 1 : 0, a[2] = this.config.particleSize, a[3] = this.config.textureEnabled ? 1 : 0, a[4] = this.config.particleColor[0], a[5] = this.config.particleColor[1], a[6] = this.config.particleColor[2], a[7] = this.config.rotation || 0, a[8] = this.config.startColor[0], a[9] = this.config.startColor[1], a[10] = this.config.startColor[2], a[11] = t, a[12] = this.config.endColor[0], a[13] = this.config.endColor[1], a[14] = this.config.endColor[2], a[15] = this.config.minRotation || 0, a[16] = this.config.maxRotation || 90, a[17] = this.config.aspectRatio || 1, a[18] = this.config.randomSize ? 1 : 0, a[19] = this.config.minSize || 0.1, a[20] = this.config.maxSize || 0.5, a[21] = this.config.fadeSizeEnabled ? 1 : 0, a[22] = this.config.opacity !== void 0 ? this.config.opacity : 1, a[23] = this.config.increaseSizeEnabled ? 1 : 0, a[24] = this.config.sizeLifetimeSpeed ?? 1, a[25] = i, a[26] = this.config.particleShapeRotation || 0, a[27] = this.config.pulseEnabled ? 1 : 0, a[28] = this.config.pulseAmplitude ?? 0.5, a[29] = this.config.pulseFrequency ?? 1, a[30] = this.config.pulsePhaseRandom ?? 0, a[31] = this.config.pulseOpacity ? 1 : 0, a[32] = this.config.particleShapeRotationX || 0, a[33] = this.config.particleShapeRotationY || 0, a[34] = this.config.particleShapeRotationZ || 0, a[35] = 0, (a[32] !== 0 || a[33] !== 0 || a[34] !== 0) && console.log(`[updateAppearanceUniform] ${this.config.name}: d[32-34] = ${a[32]}, ${a[33]}, ${a[34]}`);
1275
- const r = this.config.followSystemTranslation ?? !0;
1276
- a[36] = r ? this._simPosition[0] : 0, a[37] = r ? this._simPosition[1] : 0, a[38] = r ? this._simPosition[2] : 0, a[39] = 0, a[40] = this._simRotX, a[41] = this._simRotZ, a[42] = this.config.velocityStretchEnabled ? 1 : 0, a[43] = this.config.velocityStretchFactor ?? 1, this.device.queue.writeBuffer(this.appearanceUniformBuffer, 0, a);
1610
+ const i = { square: 0, circle: 1, triangle: 2, diamond: 3, star: 4, hexagon: 5, ring: 6, heart: 7, cross: 8, spark: 9, leaf: 10, capsule: 11, crescent: 12, line: 13, "curved-line": 14 }[this.config.particleShape] ?? 0, s = this._appearanceData;
1611
+ s[0] = this.config.fadeEnabled ? 1 : 0, s[1] = this.config.randomColorEnabled ? 2 : this.config.colorTransitionEnabled ? 1 : 0, s[2] = this.config.particleSize, s[3] = this.config.textureEnabled ? 1 : 0, s[4] = this.config.particleColor[0], s[5] = this.config.particleColor[1], s[6] = this.config.particleColor[2], s[7] = this.config.rotation || 0, s[8] = this.config.startColor[0], s[9] = this.config.startColor[1], s[10] = this.config.startColor[2], s[11] = t, s[12] = this.config.endColor[0], s[13] = this.config.endColor[1], s[14] = this.config.endColor[2], s[15] = this.config.minRotation || 0, s[16] = this.config.maxRotation || 90, s[17] = this.config.aspectRatio || 1, s[18] = this.config.randomSize ? 1 : 0, s[19] = this.config.minSize || 0.1, s[20] = this.config.maxSize || 0.5, s[21] = this.config.fadeSizeEnabled ? 1 : 0, s[22] = this.config.opacity !== void 0 ? this.config.opacity : 1, s[23] = this.config.increaseSizeEnabled ? 1 : 0, s[24] = this.config.sizeLifetimeSpeed ?? 1, s[25] = i, s[26] = 0, s[27] = this.config.pulseEnabled ? 1 : 0, s[28] = this.config.pulseAmplitude ?? 0.5, s[29] = this.config.pulseFrequency ?? 1, s[30] = this.config.pulsePhaseRandom ?? 0, s[31] = this.config.pulseOpacity ? 1 : 0, s[32] = this.config.particleShapeRotationX || 0, s[33] = this.config.particleShapeRotationY || 0, s[34] = this.config.particleShapeRotationZ || 0, s[35] = 0, (s[32] !== 0 || s[33] !== 0 || s[34] !== 0) && console.log(`[updateAppearanceUniform] ${this.config.name}: d[32-34] = ${s[32]}, ${s[33]}, ${s[34]}`);
1612
+ const n = this.config.followSystemTranslation ?? !0;
1613
+ s[36] = n ? this._simPosition[0] : 0, s[37] = n ? this._simPosition[1] : 0, s[38] = n ? this._simPosition[2] : 0, s[39] = 0, s[40] = this._simRotX, s[41] = this._simRotZ, s[42] = this.config.velocityStretchEnabled ? 1 : 0, s[43] = this.config.velocityStretchFactor ?? 1, s[44] = this.config.noiseDistortEnabled ? 1 : 0, s[45] = this.config.noiseTilingX ?? 3, s[46] = this.config.noiseTilingY ?? 3, s[47] = this.config.noiseSpeed ?? -1.5, s[48] = this.config.noiseAmplitude ?? 0.08, s[49] = n ? this._simVelocity[0] : 0, s[50] = n ? this._simVelocity[1] : 0, s[51] = n ? this._simVelocity[2] : 0, this.device.queue.writeBuffer(this.appearanceUniformBuffer, 0, s);
1277
1614
  }
1278
1615
  updateBloomIntensity() {
1279
1616
  const t = this._bloomIntensityData;
@@ -1282,7 +1619,7 @@ class C {
1282
1619
  t[4] = e[0], t[5] = e[1], t[6] = e[2], this.device.queue.writeBuffer(this.bloomIntensityBuffer, 0, t);
1283
1620
  }
1284
1621
  spawnParticles() {
1285
- if (this.activeParticles = 0, this.currentEmissionTime = 0, this._newEmissions.length = 0, this._pendingFollowEmissions = this._emptyEmissions, this.device.queue.writeBuffer(this.trailBuffer, 0, this._trailResetData, 0, this.MAX_PARTICLES * 4), this.glbAnimator && (this.glbAnimator.currentTime = 0, this.glbAnimator.playing = !0), this.config.followSystemId) {
1622
+ if (this.activeParticles = 0, this.currentEmissionTime = 0, this._newEmissions.length = 0, this._pendingFollowEmissions = this._emptyEmissions, this._scriptFrame = 0, this._scriptTime = 0, this._scriptReadbackPending = !1, this._scriptReadbackReady = !1, this._scriptConfigRestored = !1, this._particleScript && (this._particleScript._configSnapshot ? (this._particleScript.restoreConfig(this.config), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition), this.updateAppearanceUniform(), this.updateBloomIntensity()) : this._particleScript.snapshotConfig(this.config)), this.device.queue.writeBuffer(this.trailBuffer, 0, this._trailResetData, 0, this.MAX_PARTICLES * 4), this.glbAnimator && (this.glbAnimator.currentTime = 0, this.glbAnimator.playing = !0), this.config.followSystemId) {
1286
1623
  this.emitting = !0, this.particleCount = this.MAX_PARTICLES;
1287
1624
  return;
1288
1625
  }
@@ -1291,42 +1628,57 @@ class C {
1291
1628
  this.particleCount = t;
1292
1629
  let e = 0;
1293
1630
  const i = 500;
1294
- for (let a = 0; a < t; a++)
1295
- if (this.emitParticle(), e++, e >= i || a === t - 1) {
1296
- const r = a - e + 1, n = r * 8, o = r * 4;
1631
+ for (let s = 0; s < t; s++)
1632
+ if (this.emitParticle(), e++, e >= i || s === t - 1) {
1633
+ const n = s - e + 1, o = n * 8, a = n * 4;
1297
1634
  this.device.queue.writeBuffer(
1298
1635
  this.instanceBuffer,
1299
- n * 4,
1636
+ o * 4,
1300
1637
  // Offset in bytes
1301
1638
  this.particleData,
1302
- n,
1639
+ o,
1303
1640
  e * 8
1304
1641
  ), this.device.queue.writeBuffer(
1305
1642
  this.velocityBuffer,
1306
- o * 4,
1643
+ a * 4,
1307
1644
  // Offset in bytes
1308
1645
  this.particleVelocities,
1309
- o,
1646
+ a,
1310
1647
  e * 4
1311
1648
  ), e = 0;
1312
1649
  }
1313
1650
  this.emitting = !1;
1314
1651
  } else {
1315
1652
  this.emitting = !0;
1316
- const t = this.config.lifetime || 5, e = Math.max(this.config.emissionDuration || 10, t);
1653
+ const t = this.config.lifetime || 5, e = this.config.emissionDurationInfinite ? t : Math.min(this.config.emissionDuration || 10, t);
1317
1654
  this.particleCount = Math.min(Math.ceil((this.config.emissionRate || 10) * e), this.MAX_PARTICLES);
1318
1655
  }
1319
1656
  }
1657
+ // Effective emission window: Infinity when "Infinite Duration" is on (emits forever).
1658
+ // Used by the emission/respawn gates; buffer sizing handles infinity separately.
1659
+ get effectiveEmissionDuration() {
1660
+ return this.config.emissionDurationInfinite ? 1 / 0 : this.config.emissionDuration ?? 10;
1661
+ }
1662
+ // Apply the simulation rotation (and, when not following translation, the world offset) to a
1663
+ // freshly emitted particle at `index`, in local space. MUST be called from BOTH emit routes —
1664
+ // the initial spawn (emitParticle) AND the continuous recycle (respawnParticle). Without it on the
1665
+ // recycle path, a moving emitter's particles lose the sim rotation (e.g. the heading-follow yaw)
1666
+ // after their first lifetime cycle, so the emission orientation silently reverts to the un-rotated
1667
+ // shape mid-flight — the "orientation ne suit pas l'axe" bug.
1668
+ _applySimTransformToParticle(t) {
1669
+ this._emitSimRotY = this._simRotY || 0;
1670
+ const e = t * 8, i = t * 4;
1671
+ if (this._simRotMatrix) {
1672
+ const s = this._simRotMatrix, n = this.particleData[e], o = this.particleData[e + 1], a = this.particleData[e + 2], c = this.particleVelocities[i], l = this.particleVelocities[i + 1], u = this.particleVelocities[i + 2];
1673
+ this.particleData[e] = s[0] * n + s[1] * o + s[2] * a, this.particleData[e + 1] = s[3] * n + s[4] * o + s[5] * a, this.particleData[e + 2] = s[6] * n + s[7] * o + s[8] * a, this.particleVelocities[i] = s[0] * c + s[1] * l + s[2] * u, this.particleVelocities[i + 1] = s[3] * c + s[4] * l + s[5] * u, this.particleVelocities[i + 2] = s[6] * c + s[7] * l + s[8] * u;
1674
+ }
1675
+ (this.config.followSystemTranslation ?? !0) || (this.particleData[e] += this._simPosition[0], this.particleData[e + 1] += this._simPosition[1], this.particleData[e + 2] += this._simPosition[2]);
1676
+ }
1320
1677
  emitParticle() {
1321
1678
  if (this.activeParticles >= this.particleCount) return !1;
1322
1679
  this.emitter.emitParticle(this.particleData, this.activeParticles, this.particleVelocities);
1323
1680
  const t = this.activeParticles * 8, e = this.activeParticles * 4;
1324
- if (this._simRotMatrix) {
1325
- let i = this.particleData[t], a = this.particleData[t + 1], r = this.particleData[t + 2], n = this.particleVelocities[e], o = this.particleVelocities[e + 1], s = this.particleVelocities[e + 2];
1326
- const l = this._simRotMatrix;
1327
- this.particleData[t] = l[0] * i + l[1] * a + l[2] * r, this.particleData[t + 1] = l[3] * i + l[4] * a + l[5] * r, this.particleData[t + 2] = l[6] * i + l[7] * a + l[8] * r, this.particleVelocities[e] = l[0] * n + l[1] * o + l[2] * s, this.particleVelocities[e + 1] = l[3] * n + l[4] * o + l[5] * s, this.particleVelocities[e + 2] = l[6] * n + l[7] * o + l[8] * s;
1328
- }
1329
- return (this.config.followSystemTranslation ?? !0) || (this.particleData[t] += this._simPosition[0], this.particleData[t + 1] += this._simPosition[1], this.particleData[t + 2] += this._simPosition[2]), this._newEmissions.push(
1681
+ return this._applySimTransformToParticle(this.activeParticles), this._newEmissions.push(
1330
1682
  this.particleData[t],
1331
1683
  this.particleData[t + 1],
1332
1684
  this.particleData[t + 2],
@@ -1341,29 +1693,59 @@ class C {
1341
1693
  */
1342
1694
  emitFollowerParticle(t, e, i) {
1343
1695
  if (this.activeParticles >= this.particleCount) return !1;
1344
- const a = this.activeParticles * 8, r = t + (this.config.shapeTranslationX || 0), n = e + (this.config.shapeTranslationY || 0), o = i + (this.config.shapeTranslationZ || 0);
1345
- this.particleData[a] = r, this.particleData[a + 1] = n, this.particleData[a + 2] = o;
1346
- const s = this.activeParticles * 4;
1347
- return this.emitter.calculateVelocity(r, n, o, this.particleVelocities, s), this.emitter.setParticleColor(this.particleData, a), this.emitter.setParticleLifetime(this.particleData, a), this.activeParticles++, !0;
1696
+ const s = this.activeParticles * 8, n = t + (this.config.emissionPositionX || 0), o = e + (this.config.emissionPositionY || 0), a = i + (this.config.emissionPositionZ || 0);
1697
+ this.particleData[s] = n, this.particleData[s + 1] = o, this.particleData[s + 2] = a;
1698
+ const c = this.activeParticles * 4;
1699
+ return this.emitter.calculateVelocity(n, o, a, this.particleVelocities, c), this.emitter.setParticleColor(this.particleData, s), this.emitter.setParticleLifetime(this.particleData, s), this.activeParticles++, !0;
1348
1700
  }
1349
1701
  updateParticles(t, e) {
1702
+ if (this._particleScript && this._scriptReadbackReady) {
1703
+ this._scriptReadbackReady = !1, this._scriptTime += t, this._scriptFrame++;
1704
+ const a = this.config.emissionDurationInfinite ? 1 / 0 : (this.config.emissionDuration || 0) + (this.config.lifetime || 0);
1705
+ if (a > 0 && this._scriptTime >= a && !this._scriptConfigRestored)
1706
+ this._scriptConfigRestored = !0, this._particleScript._configSnapshot && (this._particleScript.restoreConfig(this.config), this.updateAppearanceUniform(), this.updateBloomIntensity(), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition));
1707
+ else if (!this._scriptConfigRestored) {
1708
+ const c = a > 0 ? Math.ceil(a / 0.016666666666666666) : 0, { configDirty: l, particlesDirty: u } = this._particleScript.execute(
1709
+ t,
1710
+ this._scriptTime,
1711
+ this._scriptFrame,
1712
+ c,
1713
+ this._scriptParticleData,
1714
+ this._scriptVelocityData,
1715
+ this.activeParticles
1716
+ );
1717
+ u && this.activeParticles > 0 && (this.device.queue.writeBuffer(
1718
+ this.instanceBuffer,
1719
+ 0,
1720
+ this._scriptParticleData,
1721
+ 0,
1722
+ this.activeParticles * 8
1723
+ ), this.device.queue.writeBuffer(
1724
+ this.velocityBuffer,
1725
+ 0,
1726
+ this._scriptVelocityData,
1727
+ 0,
1728
+ this.activeParticles * 4
1729
+ )), l && (this.updateAppearanceUniform(), this.updateBloomIntensity(), this.config.gravityEnabled && this.setGravity(this.config.gravityStrength), this.config.dampingEnabled && this.physics.setDamping(this.config.dampingStrength), this.config.attractorEnabled && this.setAttractor(this.config.attractorStrength, this.config.attractorPosition));
1730
+ }
1731
+ }
1350
1732
  this.physics.physicsAccumulator += t;
1351
- const i = performance.now() / 1e3, r = i - this.physics.lastUpdateTime > 1 / this.physics.minUpdatesPerSecond, n = this.activeParticles;
1352
- if (this.emitting)
1353
- if (this.currentEmissionTime += t, this.currentEmissionTime < this.config.emissionDuration) {
1354
- const o = this.activeParticles;
1355
- let s = !1;
1733
+ const i = performance.now() / 1e3, n = i - this.physics.lastUpdateTime > 1 / this.physics.minUpdatesPerSecond, o = this.activeParticles;
1734
+ if (!this.emitting && !this.config.burstMode && !this.config.followSystemId && this.currentEmissionTime < this.effectiveEmissionDuration && (this.emitting = !0), this.emitting)
1735
+ if (this.currentEmissionTime += t, this.currentEmissionTime < this.effectiveEmissionDuration) {
1736
+ const a = this.activeParticles;
1737
+ let c = !1;
1356
1738
  if (this.config.followSystemId) {
1357
1739
  if (this._pendingFollowEmissions.length > 0) {
1358
1740
  const l = this._pendingFollowEmissions.length / 6;
1359
1741
  for (let u = 0; u < l; u++) {
1360
- const d = u * 6;
1742
+ const f = u * 6;
1361
1743
  if (this.emitFollowerParticle(
1362
- this._pendingFollowEmissions[d],
1363
- this._pendingFollowEmissions[d + 1],
1364
- this._pendingFollowEmissions[d + 2]
1744
+ this._pendingFollowEmissions[f],
1745
+ this._pendingFollowEmissions[f + 1],
1746
+ this._pendingFollowEmissions[f + 2]
1365
1747
  ))
1366
- s = !0;
1748
+ c = !0;
1367
1749
  else
1368
1750
  break;
1369
1751
  }
@@ -1378,12 +1760,12 @@ class C {
1378
1760
  const u = this.config.emissionRate * t;
1379
1761
  Math.random() < u && (l = 1);
1380
1762
  }
1381
- l === 0 && r && this.config.emissionRate > 0 && this.activeParticles < this.particleCount && (l = 1);
1763
+ l === 0 && n && this.config.emissionRate > 0 && this.activeParticles < this.particleCount && (l = 1);
1382
1764
  for (let u = 0; u < l && this.emitParticle(); u++)
1383
- s = !0;
1765
+ c = !0;
1384
1766
  }
1385
- if (s) {
1386
- const l = this.activeParticles - o, u = o * 8, d = o * 4;
1767
+ if (c) {
1768
+ const l = this.activeParticles - a, u = a * 8, f = a * 4;
1387
1769
  this.device.queue.writeBuffer(
1388
1770
  this.instanceBuffer,
1389
1771
  u * 4,
@@ -1393,10 +1775,10 @@ class C {
1393
1775
  l * 8
1394
1776
  ), this.device.queue.writeBuffer(
1395
1777
  this.velocityBuffer,
1396
- d * 4,
1778
+ f * 4,
1397
1779
  // Offset in bytes (float32 = 4 bytes)
1398
1780
  this.particleVelocities,
1399
- d,
1781
+ f,
1400
1782
  l * 4
1401
1783
  );
1402
1784
  }
@@ -1405,20 +1787,30 @@ class C {
1405
1787
  for (; this.physics.physicsAccumulator >= this.physics.fixedDeltaTime; )
1406
1788
  this.physics.updatePhysics(
1407
1789
  this.physics.fixedDeltaTime,
1408
- n,
1790
+ o,
1409
1791
  this.config,
1410
1792
  this.instanceBuffer,
1411
1793
  this.velocityBuffer,
1412
1794
  e
1413
1795
  ), this.physics.physicsAccumulator -= this.physics.fixedDeltaTime, this.physics.physicsClock += this.physics.fixedDeltaTime;
1414
- r && n > 0 && (this.physics.updatePhysics(
1796
+ n && o > 0 && (this.physics.updatePhysics(
1415
1797
  this.physics.fixedDeltaTime,
1416
- n,
1798
+ o,
1417
1799
  this.config,
1418
1800
  this.instanceBuffer,
1419
1801
  this.velocityBuffer,
1420
1802
  e
1421
- ), this.physics.lastUpdateTime = i), this.frameCount++ % 300 === 0 && this.readbackAndProcessParticles();
1803
+ ), this.physics.lastUpdateTime = i), this.frameCount++, (this.activeParticles >= this.particleCount || this.frameCount % 300 === 0) && this.readbackAndProcessParticles(), this._particleScript && this.activeParticles > 0 && !this._scriptReadbackPending && (this._scriptReadbackPending = !0, this.physics.readbackForScript(
1804
+ this.activeParticles,
1805
+ this._scriptParticleData,
1806
+ this._scriptVelocityData,
1807
+ this.instanceBuffer,
1808
+ this.velocityBuffer
1809
+ ).then((a) => {
1810
+ this._scriptReadbackPending = !1, a.shouldUpdate && (this._scriptReadbackReady = !0);
1811
+ }).catch(() => {
1812
+ this._scriptReadbackPending = !1;
1813
+ }));
1422
1814
  }
1423
1815
  async readbackAndProcessParticles() {
1424
1816
  if (!(this.activeParticles <= 0))
@@ -1430,58 +1822,60 @@ class C {
1430
1822
  this.instanceBuffer,
1431
1823
  this.velocityBuffer
1432
1824
  )).shouldUpdate) return;
1433
- let e = 0;
1434
- for (let i = 0; i < this.activeParticles; i++) {
1435
- const a = this.particleData[i * 8 + 6], r = this.particleData[i * 8 + 7];
1436
- if (a >= r) {
1437
- if (this.emitting && this.currentEmissionTime < this.config.emissionDuration && e < this.particleCount) {
1438
- this.respawnParticle(i, e), e++;
1825
+ let e = 0, i = !1;
1826
+ for (let s = 0; s < this.activeParticles; s++) {
1827
+ const n = this.particleData[s * 8 + 6], o = this.particleData[s * 8 + 7];
1828
+ if (n >= o) {
1829
+ if (this.emitting && this.currentEmissionTime < this.effectiveEmissionDuration && e < this.particleCount) {
1830
+ this.respawnParticle(s, e), e++, i = !0;
1439
1831
  continue;
1440
1832
  }
1441
1833
  continue;
1442
1834
  }
1443
- if (e !== i) {
1444
- const n = i * 8, o = e * 8;
1445
- this.particleData.copyWithin(o, n, n + 8);
1446
- const s = i * 4, l = e * 4;
1447
- this.particleVelocities.copyWithin(l, s, s + 4);
1835
+ if (e !== s) {
1836
+ const a = s * 8, c = e * 8;
1837
+ this.particleData.copyWithin(c, a, a + 8);
1838
+ const l = s * 4, u = e * 4;
1839
+ this.particleVelocities.copyWithin(u, l, l + 4), i = !0;
1448
1840
  }
1449
1841
  e++;
1450
1842
  }
1451
- e !== this.activeParticles && (this.activeParticles = e, this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8), this.device.queue.writeBuffer(this.velocityBuffer, 0, this.particleVelocities, 0, this.activeParticles * 4));
1843
+ (e !== this.activeParticles || i) && (this.activeParticles = e, this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8), this.device.queue.writeBuffer(this.velocityBuffer, 0, this.particleVelocities, 0, this.activeParticles * 4));
1452
1844
  } catch (t) {
1453
- console.error("Error reading back particle data:", t);
1845
+ t && t.name === "AbortError" || console.error("Error reading back particle data:", t);
1454
1846
  }
1455
1847
  }
1456
1848
  respawnParticle(t, e) {
1457
- !this.emitting || this.currentEmissionTime >= this.config.emissionDuration || this.config.followSystemId || this.emitter.emitParticle(this.particleData, e, this.particleVelocities);
1849
+ !this.emitting || this.currentEmissionTime >= this.effectiveEmissionDuration || this.config.followSystemId || (this.emitter.emitParticle(this.particleData, e, this.particleVelocities), this._applySimTransformToParticle(e));
1458
1850
  }
1459
1851
  updateBuffers() {
1460
- this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
1852
+ this.destroyed || !this.particleData || this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
1461
1853
  }
1462
1854
  updateParticleColors() {
1463
- for (let t = 0; t < this.activeParticles; t++) {
1464
- const e = t * 8;
1465
- if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
1466
- const i = this.config.randomColors, a = i[Math.floor(Math.random() * i.length)];
1467
- this.particleData[e + 3] = a[0], this.particleData[e + 4] = a[1], this.particleData[e + 5] = a[2];
1468
- } else this.config.colorTransitionEnabled ? (this.particleData[e + 3] = this.config.startColor[0], this.particleData[e + 4] = this.config.startColor[1], this.particleData[e + 5] = this.config.startColor[2]) : (this.particleData[e + 3] = this.config.particleColor[0], this.particleData[e + 4] = this.config.particleColor[1], this.particleData[e + 5] = this.config.particleColor[2]);
1855
+ if (!(this.destroyed || !this.particleData)) {
1856
+ for (let t = 0; t < this.activeParticles; t++) {
1857
+ const e = t * 8;
1858
+ if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
1859
+ const i = this.config.randomColors, s = i[Math.floor(Math.random() * i.length)];
1860
+ this.particleData[e + 3] = s[0], this.particleData[e + 4] = s[1], this.particleData[e + 5] = s[2];
1861
+ } else this.config.colorTransitionEnabled ? (this.particleData[e + 3] = this.config.startColor[0], this.particleData[e + 4] = this.config.startColor[1], this.particleData[e + 5] = this.config.startColor[2]) : (this.particleData[e + 3] = this.config.particleColor[0], this.particleData[e + 4] = this.config.particleColor[1], this.particleData[e + 5] = this.config.particleColor[2]);
1862
+ }
1863
+ this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
1469
1864
  }
1470
- this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
1471
1865
  }
1472
1866
  updateParticleVelocities() {
1473
1867
  for (let t = 0; t < this.activeParticles; t++) {
1474
- const e = t * 8, i = t * 4, a = this.particleData[e], r = this.particleData[e + 1], n = this.particleData[e + 2], o = this.particleVelocities[i], s = this.particleVelocities[i + 1], l = this.particleVelocities[i + 2], u = Math.sqrt(
1475
- o * o + s * s + l * l
1868
+ const e = t * 8, i = t * 4, s = this.particleData[e], n = this.particleData[e + 1], o = this.particleData[e + 2], a = this.particleVelocities[i], c = this.particleVelocities[i + 1], l = this.particleVelocities[i + 2], u = Math.sqrt(
1869
+ a * a + c * c + l * l
1476
1870
  );
1477
1871
  if (u > 1e-3) {
1478
- const d = this.config.particleSpeed * 2;
1479
- this.particleVelocities[i] = o / u * d, this.particleVelocities[i + 1] = s / u * d, this.particleVelocities[i + 2] = l / u * d;
1872
+ const f = this.config.particleSpeed * 2;
1873
+ this.particleVelocities[i] = a / u * f, this.particleVelocities[i + 1] = c / u * f, this.particleVelocities[i + 2] = l / u * f;
1480
1874
  } else {
1481
- const d = Math.sqrt(a * a + r * r + n * n);
1482
- if (d > 1e-3) {
1483
- const f = this.config.particleSpeed * 2;
1484
- this.particleVelocities[i] = a / d * f, this.particleVelocities[i + 1] = r / d * f, this.particleVelocities[i + 2] = n / d * f;
1875
+ const f = Math.sqrt(s * s + n * n + o * o);
1876
+ if (f > 1e-3) {
1877
+ const h = this.config.particleSpeed * 2;
1878
+ this.particleVelocities[i] = s / f * h, this.particleVelocities[i + 1] = n / f * h, this.particleVelocities[i + 2] = o / f * h;
1485
1879
  } else
1486
1880
  this.particleVelocities[i] = 0, this.particleVelocities[i + 1] = this.config.particleSpeed * 2, this.particleVelocities[i + 2] = 0;
1487
1881
  }
@@ -1510,7 +1904,7 @@ class C {
1510
1904
  * Call this when the system is no longer needed.
1511
1905
  */
1512
1906
  destroy() {
1513
- this.instanceBuffer.destroy(), this.velocityBuffer.destroy(), this.trailBuffer.destroy(), this.appearanceUniformBuffer.destroy(), this.bloomIntensityBuffer.destroy(), this.physics.destroy(), this.glbVertexBuffer && (this.glbVertexBuffer.destroy(), this.glbVertexBuffer = null), this.glbIndexBuffer && (this.glbIndexBuffer.destroy(), this.glbIndexBuffer = null), this.textureManager.destroyTexture(this.particleTexture), this.glbAnimator = null, this.glbMeshData = null, this.glbRawArrayBuffer = null, this.particleData = null, this.particleVelocities = null;
1907
+ this.destroyed = !0, this.instanceBuffer.destroy(), this.velocityBuffer.destroy(), this.trailBuffer.destroy(), this.appearanceUniformBuffer.destroy(), this.bloomIntensityBuffer.destroy(), this.physics.destroy(), this.glbVertexBuffer && (this.glbVertexBuffer.destroy(), this.glbVertexBuffer = null), this.glbIndexBuffer && (this.glbIndexBuffer.destroy(), this.glbIndexBuffer = null), this.textureManager.destroyTexture(this.particleTexture), this._particleScript && (this._particleScript.destroy(), this._particleScript = null), this.glbAnimator = null, this.glbMeshData = null, this.glbRawArrayBuffer = null, this.particleData = null, this.particleVelocities = null, this._scriptParticleData = null, this._scriptVelocityData = null;
1514
1908
  }
1515
1909
  setGravity(t) {
1516
1910
  this.physics.setGravity(t);
@@ -1519,27 +1913,27 @@ class C {
1519
1913
  this.physics.setAttractor(t, e);
1520
1914
  }
1521
1915
  setConfinement(t) {
1522
- const e = t.space === "local" ? [this.config.shapeTranslationX || 0, this.config.shapeTranslationY || 0, this.config.shapeTranslationZ || 0] : [0, 0, 0];
1523
- this.physics.setConfinement({ ...t, center: e });
1916
+ const e = t.center || this.config.confinementCenter || [0, 0, 0], i = t.space === "local" ? [this.config.emissionPositionX || 0, this.config.emissionPositionY || 0, this.config.emissionPositionZ || 0] : [0, 0, 0], s = [i[0] + (e[0] || 0), i[1] + (e[1] || 0), i[2] + (e[2] || 0)];
1917
+ this.physics.setConfinement({ ...t, center: s });
1524
1918
  }
1525
1919
  setSoftBoundary(t) {
1526
1920
  this.physics.setSoftBoundary(t);
1527
1921
  }
1528
1922
  }
1529
- class me {
1923
+ class Es {
1530
1924
  constructor(t) {
1531
- this.device = t, this.particleSystems = [], this.activeSystemIndex = 0, this.systemCounter = 1, this.onSystemCreated = null;
1925
+ this.device = t, this.particleSystems = [], this.activeSystemIndex = 0, this.systemCounter = 1, this.onSystemCreated = null, this.loop = void 0, this.ready = !0;
1532
1926
  }
1533
1927
  createParticleSystem(t = {}) {
1534
- const e = this.systemCounter++, i = t.name || `System ${e + 1}`, a = {
1928
+ const e = this.systemCounter++, i = t.name || `System ${e + 1}`, s = {
1535
1929
  ...t,
1536
1930
  name: i,
1537
1931
  id: e
1538
- }, r = new C(this.device, a);
1932
+ }, n = new bt(this.device, s);
1539
1933
  return this.particleSystems.push({
1540
- system: r,
1541
- config: a
1542
- }), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e, a), e;
1934
+ system: n,
1935
+ config: s
1936
+ }), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e, s), e;
1543
1937
  }
1544
1938
  getActiveSystem() {
1545
1939
  return this.particleSystems.length === 0 ? null : this.particleSystems[this.activeSystemIndex].system;
@@ -1566,8 +1960,8 @@ class me {
1566
1960
  const e = this.particleSystems[t].config;
1567
1961
  this.particleSystems[t].system.destroy(), this.particleSystems.splice(t, 1);
1568
1962
  const i = e.id;
1569
- for (const { config: a } of this.particleSystems)
1570
- a.followSystemId === i && (a.followSystemId = null);
1963
+ for (const { config: s } of this.particleSystems)
1964
+ s.followSystemId === i && (s.followSystemId = null);
1571
1965
  return this.particleSystems.length === 0 ? this.activeSystemIndex = 0 : t <= this.activeSystemIndex && (this.activeSystemIndex = Math.max(0, this.activeSystemIndex - 1)), !0;
1572
1966
  }
1573
1967
  return !1;
@@ -1579,21 +1973,21 @@ class me {
1579
1973
  updateAllSystems(t) {
1580
1974
  const e = this.device.createCommandEncoder({ label: "BatchedPhysicsEncoder" });
1581
1975
  let i = !1;
1582
- for (const { system: a, config: r } of this.particleSystems) {
1583
- if (r.hidden || r.followSystemId) continue;
1584
- const n = a.activeParticles > 0;
1585
- a.updateParticles(t, e), (n || a.activeParticles > 0) && (i = !0);
1976
+ for (const { system: s, config: n } of this.particleSystems) {
1977
+ if (n.hidden || n.followSystemId) continue;
1978
+ const o = s.activeParticles > 0;
1979
+ s.updateParticles(t, e), (o || s.activeParticles > 0) && (i = !0);
1586
1980
  }
1587
- for (const { system: a, config: r } of this.particleSystems) {
1588
- if (r.hidden || !r.followSystemId) continue;
1589
- const n = this.getSystemById(r.followSystemId);
1590
- n && (a._pendingFollowEmissions = n.system._newEmissions);
1591
- const o = a.activeParticles > 0;
1592
- a.updateParticles(t, e), (o || a.activeParticles > 0) && (i = !0);
1981
+ for (const { system: s, config: n } of this.particleSystems) {
1982
+ if (n.hidden || !n.followSystemId) continue;
1983
+ const o = this.getSystemById(n.followSystemId);
1984
+ o && (s._pendingFollowEmissions = o.system._newEmissions);
1985
+ const a = s.activeParticles > 0;
1986
+ s.updateParticles(t, e), (a || s.activeParticles > 0) && (i = !0);
1593
1987
  }
1594
1988
  i && this.device.queue.submit([e.finish()]);
1595
- for (const { system: a } of this.particleSystems)
1596
- a._newEmissions.length = 0, a._pendingFollowEmissions = a._emptyEmissions;
1989
+ for (const { system: s } of this.particleSystems)
1990
+ s._newEmissions.length = 0, s._pendingFollowEmissions = s._emptyEmissions;
1597
1991
  }
1598
1992
  getSystemsList() {
1599
1993
  return this.particleSystems.map(({ config: t }, e) => ({
@@ -1618,68 +2012,71 @@ class me {
1618
2012
  var e;
1619
2013
  if (!t || !t.systems || !Array.isArray(t.systems))
1620
2014
  return console.error("Invalid scene data provided"), !1;
2015
+ this.ready = !1;
1621
2016
  try {
1622
2017
  this.particleSystems = [], this.systemCounter = 1;
1623
- for (const a of t.systems) {
1624
- const r = this.systemCounter++, n = {
1625
- ...a,
1626
- id: r
1627
- }, o = new C(this.device, n);
2018
+ for (const s of t.systems) {
2019
+ const n = this.systemCounter++, o = {
2020
+ ...s,
2021
+ id: n
2022
+ }, a = new bt(this.device, o);
1628
2023
  this.particleSystems.push({
1629
- system: o,
1630
- config: n
2024
+ system: a,
2025
+ config: o
1631
2026
  });
1632
2027
  }
1633
2028
  const i = {};
1634
- t.systems.forEach((a, r) => {
1635
- i[a.id] = this.particleSystems[r].config.id;
2029
+ t.systems.forEach((s, n) => {
2030
+ i[s.id] = this.particleSystems[n].config.id;
1636
2031
  });
1637
- for (const { config: a } of this.particleSystems)
1638
- a.followSystemId && i[a.followSystemId] !== void 0 && (a.followSystemId = i[a.followSystemId]);
1639
- t.activeSystemIndex !== void 0 && t.activeSystemIndex >= 0 && t.activeSystemIndex < this.particleSystems.length ? this.activeSystemIndex = t.activeSystemIndex : this.activeSystemIndex = 0;
1640
- for (const { system: a, config: r } of this.particleSystems)
1641
- if (r.glbModelEnabled)
2032
+ for (const { config: s } of this.particleSystems)
2033
+ s.followSystemId && i[s.followSystemId] !== void 0 && (s.followSystemId = i[s.followSystemId]);
2034
+ t.activeSystemIndex !== void 0 && t.activeSystemIndex >= 0 && t.activeSystemIndex < this.particleSystems.length ? this.activeSystemIndex = t.activeSystemIndex : this.activeSystemIndex = 0, this.loop = t.loop;
2035
+ for (const { system: s, config: n } of this.particleSystems)
2036
+ if (n.glbModelEnabled)
1642
2037
  try {
1643
- let n = null;
1644
- if (r.glbModelData)
1645
- n = D(r.glbModelData);
1646
- else if (r.glbFileName) {
1647
- const o = await fetch(`/${r.glbFileName}`);
1648
- o.ok ? n = await o.arrayBuffer() : console.warn(`GLB file not found: ${r.glbFileName}`);
2038
+ let o = null;
2039
+ if (n.glbModelData)
2040
+ o = ci(n.glbModelData);
2041
+ else if (n.glbFileName) {
2042
+ const a = await fetch(`/${n.glbFileName}`);
2043
+ a.ok ? o = await a.arrayBuffer() : console.warn(`GLB file not found: ${n.glbFileName}`);
1649
2044
  }
1650
- if (n) {
1651
- if (await a.setGLBModel(n), r.animationIndex !== void 0 && a.glbAnimator && a.glbAnimator.setAnimation(r.animationIndex), r.animationSpeed !== void 0 && a.glbAnimator && (a.glbAnimator.speed = r.animationSpeed), r.animationLoop !== void 0 && a.glbAnimator && (a.glbAnimator.loop = r.animationLoop), r.useGlbTexture && (r.textureEnabled = !0), r.useGlbTexture && ((e = a.glbMeshData) != null && e.hasBaseColorTexture))
2045
+ if (o) {
2046
+ if (await s.setGLBModel(o), n.animationIndex !== void 0 && s.glbAnimator && s.glbAnimator.setAnimation(n.animationIndex), n.animationSpeed !== void 0 && s.glbAnimator && (s.glbAnimator.speed = n.animationSpeed), n.animationLoop !== void 0 && s.glbAnimator && (s.glbAnimator.loop = n.animationLoop), n.useGlbTexture && (n.textureEnabled = !0), n.useGlbTexture && ((e = s.glbMeshData) != null && e.hasBaseColorTexture))
1652
2047
  try {
1653
- const { extractGLBTexture: o } = await Promise.resolve().then(() => U), s = await o(n);
1654
- if (s) {
1655
- const l = await createImageBitmap(s.imageBlob);
1656
- await a.setTexture(l), console.log(`GLB embedded texture restored for ${r.name}`);
2048
+ const { extractGLBTexture: a } = await Promise.resolve().then(() => ni), c = await a(o);
2049
+ if (c) {
2050
+ const l = await createImageBitmap(c.imageBlob);
2051
+ await s.setTexture(l), console.log(`GLB embedded texture restored for ${n.name}`);
1657
2052
  }
1658
- } catch (o) {
1659
- console.warn(`Failed to restore GLB texture for ${r.name}:`, o), r.useGlbTexture = !1;
2053
+ } catch (a) {
2054
+ console.warn(`Failed to restore GLB texture for ${n.name}:`, a), n.useGlbTexture = !1;
1660
2055
  }
1661
2056
  } else
1662
- r.glbModelEnabled = !1;
1663
- } catch (n) {
1664
- console.warn(`Failed to load GLB for ${r.name}:`, n), r.glbModelEnabled = !1;
2057
+ n.glbModelEnabled = !1;
2058
+ } catch (o) {
2059
+ console.warn(`Failed to load GLB for ${n.name}:`, o), n.glbModelEnabled = !1;
1665
2060
  }
1666
- for (const { system: a, config: r } of this.particleSystems)
1667
- if (r.textureEnabled && !r.glbModelEnabled && r.textureImageData)
2061
+ for (const { system: s, config: n } of this.particleSystems)
2062
+ if (n.textureEnabled && !n.glbModelEnabled && n.textureImageData)
1668
2063
  try {
1669
- const n = new Image();
1670
- await new Promise((s, l) => {
1671
- n.onload = s, n.onerror = l, n.src = r.textureImageData;
2064
+ const o = new Image();
2065
+ await new Promise((c, l) => {
2066
+ o.onload = c, o.onerror = l, o.src = n.textureImageData;
1672
2067
  });
1673
- const o = await createImageBitmap(n);
1674
- await a.setTexture(o);
1675
- } catch (n) {
1676
- console.warn(`Failed to restore texture for ${r.name}:`, n), r.textureEnabled = !1;
2068
+ const a = await createImageBitmap(o);
2069
+ await s.setTexture(a);
2070
+ } catch (o) {
2071
+ console.warn(`Failed to restore texture for ${n.name}:`, o), n.textureEnabled = !1;
1677
2072
  }
1678
- for (const { system: a, config: r } of this.particleSystems)
1679
- a.updateAppearanceUniform(), (r.particleShapeRotationX || r.particleShapeRotationY || r.particleShapeRotationZ) && console.log(`[replaceSystems] ${r.name}: glbRotation XYZ = ${r.particleShapeRotationX}, ${r.particleShapeRotationY}, ${r.particleShapeRotationZ} | glbModelEnabled=${r.glbModelEnabled} | glbMeshData=${!!a.glbMeshData}`);
2073
+ for (const { system: s, config: n } of this.particleSystems)
2074
+ s.updateAppearanceUniform(), (n.particleShapeRotationX || n.particleShapeRotationY || n.particleShapeRotationZ) && console.log(`[replaceSystems] ${n.name}: glbRotation XYZ = ${n.particleShapeRotationX}, ${n.particleShapeRotationY}, ${n.particleShapeRotationZ} | glbModelEnabled=${n.glbModelEnabled} | glbMeshData=${!!s.glbMeshData}`);
1680
2075
  return this.respawnAllSystems(), !0;
1681
2076
  } catch (i) {
1682
2077
  return console.error("Error replacing systems:", i), !1;
2078
+ } finally {
2079
+ this.ready = !0;
1683
2080
  }
1684
2081
  }
1685
2082
  /**
@@ -1690,132 +2087,139 @@ class me {
1690
2087
  * @returns {boolean} - Whether the addition was successful
1691
2088
  */
1692
2089
  async addSystems(t, e = [0, 0, 0]) {
1693
- var i;
2090
+ var s;
1694
2091
  if (!t || !t.systems || !Array.isArray(t.systems))
1695
2092
  return console.error("Invalid scene data provided"), !1;
2093
+ this.ready = !1;
2094
+ const i = [];
1696
2095
  try {
1697
- for (const n of t.systems) {
1698
- const o = this.systemCounter++, s = {
1699
- ...n,
1700
- id: o,
1701
- // Apply world-space offset to shape translation
1702
- shapeTranslationX: (n.shapeTranslationX || 0) + e[0],
1703
- shapeTranslationY: (n.shapeTranslationY || 0) + e[1],
1704
- shapeTranslationZ: (n.shapeTranslationZ || 0) + e[2]
2096
+ for (const a of t.systems) {
2097
+ const c = this.systemCounter++;
2098
+ i.push(c);
2099
+ const l = {
2100
+ ...a,
2101
+ id: c,
2102
+ // Apply world-space offset to emission translation
2103
+ emissionPositionX: (a.emissionPositionX || 0) + e[0],
2104
+ emissionPositionY: (a.emissionPositionY || 0) + e[1],
2105
+ emissionPositionZ: (a.emissionPositionZ || 0) + e[2]
1705
2106
  };
1706
- n.attractorEnabled && n.attractorPosition && (s.attractorPosition = [
1707
- n.attractorPosition[0] + e[0],
1708
- n.attractorPosition[1] + e[1],
1709
- n.attractorPosition[2] + e[2]
2107
+ a.attractorEnabled && a.attractorPosition && (l.attractorPosition = [
2108
+ a.attractorPosition[0] + e[0],
2109
+ a.attractorPosition[1] + e[1],
2110
+ a.attractorPosition[2] + e[2]
1710
2111
  ]);
1711
- const l = new C(this.device, s);
2112
+ const u = new bt(this.device, l);
1712
2113
  this.particleSystems.push({
1713
- system: l,
1714
- config: s
1715
- }), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(o, s);
2114
+ system: u,
2115
+ config: l
2116
+ }), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(c, l);
1716
2117
  }
1717
- const a = this.particleSystems.length - t.systems.length, r = {};
1718
- t.systems.forEach((n, o) => {
1719
- r[n.id] = this.particleSystems[a + o].config.id;
2118
+ const n = this.particleSystems.length - t.systems.length, o = {};
2119
+ t.systems.forEach((a, c) => {
2120
+ o[a.id] = this.particleSystems[n + c].config.id;
1720
2121
  });
1721
- for (let n = a; n < this.particleSystems.length; n++) {
1722
- const { config: o } = this.particleSystems[n];
1723
- o.followSystemId && r[o.followSystemId] !== void 0 && (o.followSystemId = r[o.followSystemId]);
2122
+ for (let a = n; a < this.particleSystems.length; a++) {
2123
+ const { config: c } = this.particleSystems[a];
2124
+ c.followSystemId && o[c.followSystemId] !== void 0 && (c.followSystemId = o[c.followSystemId]);
1724
2125
  }
1725
- for (const { system: n, config: o } of this.particleSystems)
1726
- if (o.glbModelEnabled && !n.glbMeshData)
2126
+ for (const { system: a, config: c } of this.particleSystems)
2127
+ if (c.glbModelEnabled && !a.glbMeshData)
1727
2128
  try {
1728
- let s = null;
1729
- if (o.glbModelData)
1730
- s = D(o.glbModelData);
1731
- else if (o.glbFileName) {
1732
- const l = await fetch(`/${o.glbFileName}`);
1733
- l.ok ? s = await l.arrayBuffer() : console.warn(`GLB file not found: ${o.glbFileName}`);
2129
+ let l = null;
2130
+ if (c.glbModelData)
2131
+ l = ci(c.glbModelData);
2132
+ else if (c.glbFileName) {
2133
+ const u = await fetch(`/${c.glbFileName}`);
2134
+ u.ok ? l = await u.arrayBuffer() : console.warn(`GLB file not found: ${c.glbFileName}`);
1734
2135
  }
1735
- if (s) {
1736
- if (await n.setGLBModel(s), o.animationIndex !== void 0 && n.glbAnimator && n.glbAnimator.setAnimation(o.animationIndex), o.animationSpeed !== void 0 && n.glbAnimator && (n.glbAnimator.speed = o.animationSpeed), o.animationLoop !== void 0 && n.glbAnimator && (n.glbAnimator.loop = o.animationLoop), o.useGlbTexture && (o.textureEnabled = !0), o.useGlbTexture && ((i = n.glbMeshData) != null && i.hasBaseColorTexture))
2136
+ if (l) {
2137
+ if (await a.setGLBModel(l), c.animationIndex !== void 0 && a.glbAnimator && a.glbAnimator.setAnimation(c.animationIndex), c.animationSpeed !== void 0 && a.glbAnimator && (a.glbAnimator.speed = c.animationSpeed), c.animationLoop !== void 0 && a.glbAnimator && (a.glbAnimator.loop = c.animationLoop), c.useGlbTexture && (c.textureEnabled = !0), c.useGlbTexture && ((s = a.glbMeshData) != null && s.hasBaseColorTexture))
1737
2138
  try {
1738
- const { extractGLBTexture: l } = await Promise.resolve().then(() => U), u = await l(s);
1739
- if (u) {
1740
- const d = await createImageBitmap(u.imageBlob);
1741
- await n.setTexture(d), console.log(`GLB embedded texture restored for ${o.name}`);
2139
+ const { extractGLBTexture: u } = await Promise.resolve().then(() => ni), f = await u(l);
2140
+ if (f) {
2141
+ const h = await createImageBitmap(f.imageBlob);
2142
+ await a.setTexture(h), console.log(`GLB embedded texture restored for ${c.name}`);
1742
2143
  }
1743
- } catch (l) {
1744
- console.warn(`Failed to restore GLB texture for ${o.name}:`, l), o.useGlbTexture = !1;
2144
+ } catch (u) {
2145
+ console.warn(`Failed to restore GLB texture for ${c.name}:`, u), c.useGlbTexture = !1;
1745
2146
  }
1746
2147
  } else
1747
- o.glbModelEnabled = !1;
1748
- } catch (s) {
1749
- console.warn(`Failed to load GLB for ${o.name}:`, s), o.glbModelEnabled = !1;
2148
+ c.glbModelEnabled = !1;
2149
+ } catch (l) {
2150
+ console.warn(`Failed to load GLB for ${c.name}:`, l), c.glbModelEnabled = !1;
1750
2151
  }
1751
- for (const { system: n, config: o } of this.particleSystems)
1752
- if (o.textureEnabled && !o.glbModelEnabled && o.textureImageData && !n._textureRestored)
2152
+ for (const { system: a, config: c } of this.particleSystems)
2153
+ if (c.textureEnabled && !c.glbModelEnabled && c.textureImageData && !a._textureRestored)
1753
2154
  try {
1754
- const s = new Image();
1755
- await new Promise((u, d) => {
1756
- s.onload = u, s.onerror = d, s.src = o.textureImageData;
2155
+ const l = new Image();
2156
+ await new Promise((f, h) => {
2157
+ l.onload = f, l.onerror = h, l.src = c.textureImageData;
1757
2158
  });
1758
- const l = await createImageBitmap(s);
1759
- await n.setTexture(l), n._textureRestored = !0;
1760
- } catch (s) {
1761
- console.warn(`Failed to restore texture for ${o.name}:`, s), o.textureEnabled = !1;
2159
+ const u = await createImageBitmap(l);
2160
+ await a.setTexture(u), a._textureRestored = !0;
2161
+ } catch (l) {
2162
+ console.warn(`Failed to restore texture for ${c.name}:`, l), c.textureEnabled = !1;
1762
2163
  }
1763
- return !0;
1764
- } catch (a) {
1765
- return console.error("Error adding systems:", a), !1;
2164
+ return i;
2165
+ } catch (n) {
2166
+ return console.error("Error adding systems:", n), !1;
2167
+ } finally {
2168
+ this.ready = !0;
1766
2169
  }
1767
2170
  }
1768
2171
  }
1769
- async function ye(c) {
1770
- if (!c)
2172
+ async function Cs(r) {
2173
+ if (!r)
1771
2174
  throw new Error("canvas is required for initWebGPU()");
1772
2175
  if (!navigator.gpu)
1773
2176
  throw new Error("WebGPU not supported on this browser.");
1774
- const t = c.getContext("webgpu"), i = await (await navigator.gpu.requestAdapter()).requestDevice(), a = navigator.gpu.getPreferredCanvasFormat();
2177
+ const t = r.getContext("webgpu"), i = await (await navigator.gpu.requestAdapter()).requestDevice(), s = navigator.gpu.getPreferredCanvasFormat();
1775
2178
  return t.configure({
1776
2179
  device: i,
1777
- format: a,
2180
+ format: s,
1778
2181
  alphaMode: "premultiplied"
1779
- }), { device: i, context: t, format: a, canvas: c };
2182
+ }), { device: i, context: t, format: s, canvas: r };
1780
2183
  }
1781
- function ge(c, t, e, i) {
1782
- const a = c.createTexture({
2184
+ const le = "rgba16float";
2185
+ function ui(r, t, e, i) {
2186
+ const s = r.createTexture({
1783
2187
  size: [e, i],
1784
- format: t,
2188
+ format: le,
1785
2189
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1786
2190
  mipLevelCount: 1,
1787
2191
  sampleCount: 1
1788
- }), r = c.createTexture({
2192
+ }), n = r.createTexture({
1789
2193
  size: [e, i],
1790
- format: t,
2194
+ format: le,
1791
2195
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1792
2196
  mipLevelCount: 1,
1793
2197
  sampleCount: 1
1794
- }), n = c.createTexture({
2198
+ }), o = r.createTexture({
1795
2199
  size: [e, i],
1796
- format: t,
2200
+ format: le,
1797
2201
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1798
2202
  mipLevelCount: 1,
1799
2203
  sampleCount: 1
1800
2204
  });
1801
- return { sceneTexture: a, bloomTexA: r, bloomTexB: n };
2205
+ return { sceneTexture: s, bloomTexA: n, bloomTexB: o };
1802
2206
  }
1803
- function be(c, t, e) {
1804
- return c.createTexture({
2207
+ function di(r, t, e) {
2208
+ return r.createTexture({
1805
2209
  size: [t, e],
1806
2210
  format: "depth24plus",
1807
2211
  usage: GPUTextureUsage.RENDER_ATTACHMENT
1808
2212
  });
1809
2213
  }
1810
- function E(c, t, e) {
1811
- const i = c.createBuffer({
2214
+ function Ge(r, t, e) {
2215
+ const i = r.createBuffer({
1812
2216
  size: t.byteLength,
1813
2217
  usage: e,
1814
2218
  mappedAtCreation: !0
1815
2219
  });
1816
2220
  return new t.constructor(i.getMappedRange()).set(t), i.unmap(), i;
1817
2221
  }
1818
- const j = `
2222
+ const bi = `
1819
2223
  struct Uniforms {
1820
2224
  transform: mat4x4<f32>,
1821
2225
  cameraPosition: vec3<f32>,
@@ -1860,6 +2264,14 @@ const j = `
1860
2264
  simRotZ: f32, // simulation rotation Z (radians)
1861
2265
  velocityStretchEnabled: f32, // 0=off, 1=on
1862
2266
  velocityStretchFactor: f32, // multiplier for stretch (0-10)
2267
+ noiseDistortEnabled: f32, // 0=off, 1=on — UV distortion by scrolling noise (flames)
2268
+ noiseTilingX: f32, // noise tiling along U
2269
+ noiseTilingY: f32, // noise tiling along V
2270
+ noiseSpeed: f32, // vertical scroll speed (negative = noise rises, flame dances upward)
2271
+ noiseAmplitude: f32, // UV distortion amplitude
2272
+ systemVelX: f32, // emitter/system world velocity (for velocity-aligned rotation
2273
+ systemVelY: f32, // of trail particles that move WITH the emitter, e.g. a ball —
2274
+ systemVelZ: f32, // their local velocity is ~0 so they need the system velocity)
1863
2275
  }
1864
2276
 
1865
2277
  @binding(0) @group(0) var<uniform> uniforms : Uniforms;
@@ -1881,6 +2293,22 @@ const j = `
1881
2293
  @location(0) color : vec3<f32>,
1882
2294
  @location(1) alpha : f32,
1883
2295
  @location(2) texCoord : vec2<f32>,
2296
+ @location(3) noiseOffset : vec2<f32>,
2297
+ }
2298
+
2299
+ fn hash21(p: vec2<f32>) -> f32 {
2300
+ return fract(sin(dot(p, vec2<f32>(127.1, 311.7))) * 43758.5453);
2301
+ }
2302
+
2303
+ fn valueNoise(p: vec2<f32>) -> f32 {
2304
+ let i = floor(p);
2305
+ let f = fract(p);
2306
+ let u = f * f * (3.0 - 2.0 * f);
2307
+ let a = hash21(i);
2308
+ let b = hash21(i + vec2<f32>(1.0, 0.0));
2309
+ let c = hash21(i + vec2<f32>(0.0, 1.0));
2310
+ let d = hash21(i + vec2<f32>(1.0, 1.0));
2311
+ return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
1884
2312
  }
1885
2313
 
1886
2314
  @vertex
@@ -1958,9 +2386,13 @@ const j = `
1958
2386
  fract(sin(lifetime * 12345.67) * 43758.5453) *
1959
2387
  (appearance.maxRotation - appearance.minRotation);
1960
2388
  } else if (appearance.rotationMode == 2.0) {
1961
- // Calculate rotation based on velocity direction in screen space
1962
- // Transform velocity from world to view space to get correct orientation
1963
- let viewVelocity = (uniforms.transform * vec4<f32>(input.particleVelocity, 0.0)).xyz;
2389
+ // Calculate rotation based on velocity direction in screen space. Use the COMBINED velocity
2390
+ // (particle-local + system/emitter): a trail particle riding a moving emitter (e.g. the driven
2391
+ // ball) has ~0 local velocity, so without the system term it would never align to the motion
2392
+ // ("la particule ne suit jamais la direction de la vélocité"). Stays a camera-facing billboard,
2393
+ // just rotated to point along the movement.
2394
+ let combinedVel = input.particleVelocity + vec3<f32>(appearance.systemVelX, appearance.systemVelY, appearance.systemVelZ);
2395
+ let viewVelocity = (uniforms.transform * vec4<f32>(combinedVel, 0.0)).xyz;
1964
2396
 
1965
2397
  // Calculate the angle from the transformed velocity
1966
2398
  // We only care about the XY plane in screen space
@@ -2023,6 +2455,14 @@ const j = `
2023
2455
  // Convert the quad position to texture coordinates (0,0 to 1,1)
2024
2456
  output.texCoord = vec2<f32>(input.position.x + 0.5, -input.position.y + 0.5);
2025
2457
 
2458
+ // Per-particle phase (seeded from lifetime) desynchronizes flames sharing
2459
+ // the same system; y carries the vertical noise scroll over time.
2460
+ let noisePhase = fract(sin(lifetime * 76543.21) * 43758.5453) * 6.283185;
2461
+ output.noiseOffset = vec2<f32>(
2462
+ noisePhase,
2463
+ uniforms.elapsedTime * appearance.noiseSpeed + noisePhase
2464
+ );
2465
+
2026
2466
  return output;
2027
2467
  }
2028
2468
 
@@ -2139,13 +2579,27 @@ const j = `
2139
2579
  }
2140
2580
 
2141
2581
  if (appearance.textureEnabled > 0.5) {
2142
- let texColor = textureSample(particleTexture, particleSampler, input.texCoord);
2582
+ var sampleUV = input.texCoord;
2583
+ if (appearance.noiseDistortEnabled > 0.5) {
2584
+ // Flame-style distortion: a scrolling noise field offsets the sample UV
2585
+ // (n = noise(uv×tiling + (phase, t×speed + phase)) − 0.5)
2586
+ let nUV = input.texCoord * vec2<f32>(appearance.noiseTilingX, appearance.noiseTilingY)
2587
+ + input.noiseOffset;
2588
+ let n1 = valueNoise(nUV) - 0.5;
2589
+ let n2 = valueNoise(nUV + vec2<f32>(13.7, 7.3)) - 0.5;
2590
+ sampleUV = clamp(
2591
+ input.texCoord + vec2<f32>(n1, n2) * appearance.noiseAmplitude,
2592
+ vec2<f32>(0.001, 0.001),
2593
+ vec2<f32>(0.999, 0.999)
2594
+ );
2595
+ }
2596
+ let texColor = textureSample(particleTexture, particleSampler, sampleUV);
2143
2597
  return vec4<f32>(input.color * texColor.rgb, alpha * texColor.a);
2144
2598
  } else {
2145
2599
  return vec4<f32>(input.color, alpha);
2146
2600
  }
2147
2601
  }
2148
- `, N = `
2602
+ `, Si = `
2149
2603
  struct BloomUniforms {
2150
2604
  direction: vec2<f32>,
2151
2605
  resolution: vec2<f32>,
@@ -2205,7 +2659,7 @@ const j = `
2205
2659
 
2206
2660
  return result / totalWeight * 1.1;
2207
2661
  }
2208
- `, X = `
2662
+ `, xi = `
2209
2663
  struct BloomIntensityUniforms {
2210
2664
  intensity: f32,
2211
2665
  color: vec3<f32>,
@@ -2251,7 +2705,7 @@ const j = `
2251
2705
 
2252
2706
  return vec4<f32>(originalColor.rgb + (mappedBloom * bloomUniforms.intensity), originalColor.a);
2253
2707
  }
2254
- `, k = `
2708
+ `, vi = `
2255
2709
  struct BloomIntensityUniforms {
2256
2710
  intensity: f32,
2257
2711
  color: vec3<f32>,
@@ -2292,7 +2746,39 @@ const j = `
2292
2746
  fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
2293
2747
  return textureSample(originalTexture, texSampler, input.texCoord);
2294
2748
  }
2295
- `, oe = `
2749
+ `, Pi = `
2750
+ @binding(0) @group(0) var texSampler: sampler;
2751
+ @binding(1) @group(0) var originalTexture: texture_2d<f32>;
2752
+ @binding(2) @group(0) var blurredTexture: texture_2d<f32>;
2753
+ struct BloomIntensityUniforms { intensity: f32, color: vec3<f32> }
2754
+ @binding(3) @group(0) var<uniform> bloomUniforms: BloomIntensityUniforms;
2755
+
2756
+ struct VertexOutput {
2757
+ @builtin(position) position: vec4<f32>,
2758
+ @location(0) texCoord: vec2<f32>,
2759
+ }
2760
+
2761
+ @vertex
2762
+ fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
2763
+ var output: VertexOutput;
2764
+ let positions = array<vec2<f32>, 3>(vec2<f32>(-1.0, -1.0), vec2<f32>(3.0, -1.0), vec2<f32>(-1.0, 3.0));
2765
+ let texCoords = array<vec2<f32>, 3>(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 1.0), vec2<f32>(0.0, -1.0));
2766
+ output.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);
2767
+ output.texCoord = texCoords[vertexIndex];
2768
+ return output;
2769
+ }
2770
+
2771
+ fn aces(x: vec3<f32>) -> vec3<f32> {
2772
+ let a = 2.51; let b = 0.03; let c = 2.43; let d = 0.59; let e = 0.14;
2773
+ return clamp((x * (a * x + b)) / (x * (c * x + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));
2774
+ }
2775
+
2776
+ @fragment
2777
+ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
2778
+ let c = textureSample(originalTexture, texSampler, input.texCoord);
2779
+ return vec4<f32>(aces(c.rgb), c.a);
2780
+ }
2781
+ `, As = `
2296
2782
  struct PhysicsUniforms {
2297
2783
  deltaTime: f32,
2298
2784
  particleSpeed: f32,
@@ -2502,7 +2988,7 @@ const j = `
2502
2988
  particleBuffer[baseIndex + 1u] = newPos.y;
2503
2989
  particleBuffer[baseIndex + 2u] = newPos.z;
2504
2990
  }
2505
- `, le = `
2991
+ `, Us = `
2506
2992
  @group(0) @binding(0) var<storage, read> restData: array<f32>;
2507
2993
  @group(0) @binding(1) var<storage, read> jointWeightsData: array<f32>;
2508
2994
  @group(0) @binding(2) var<storage, read> jointIndicesData: array<u32>;
@@ -2558,15 +3044,16 @@ const j = `
2558
3044
  outputData[outBase + 6u] = uv_u;
2559
3045
  outputData[outBase + 7u] = uv_v;
2560
3046
  }
2561
- `, Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3047
+ `, _i = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2562
3048
  __proto__: null,
2563
- blurShader: N,
2564
- compositeShader: X,
2565
- directRenderShader: k,
2566
- particlePhysicsShader: oe,
2567
- particleShader: j,
2568
- skinningComputeShader: le
2569
- }, Symbol.toStringTag, { value: "Module" })), ce = `
3049
+ blurShader: Si,
3050
+ compositeShader: xi,
3051
+ directRenderShader: vi,
3052
+ finalCompositeShader: Pi,
3053
+ particlePhysicsShader: As,
3054
+ particleShader: bi,
3055
+ skinningComputeShader: Us
3056
+ }, Symbol.toStringTag, { value: "Module" })), Is = `
2570
3057
  struct Uniforms {
2571
3058
  transform: mat4x4<f32>,
2572
3059
  cameraPosition: vec3<f32>,
@@ -2628,7 +3115,7 @@ const j = `
2628
3115
 
2629
3116
  return finalColor;
2630
3117
  }
2631
- `, ue = `
3118
+ `, Gs = `
2632
3119
  struct Uniforms {
2633
3120
  transform: mat4x4<f32>,
2634
3121
  cameraPosition: vec3<f32>,
@@ -2713,9 +3200,14 @@ const j = `
2713
3200
 
2714
3201
  // Determine particle color
2715
3202
  var finalColor = input.particleColor;
2716
- if (appearance.colorTransitionEnabled > 0.5) {
3203
+ if (appearance.colorTransitionEnabled > 1.5) {
3204
+ // Random color mode: use per-particle color from instance data
3205
+ finalColor = input.particleColor;
3206
+ } else if (appearance.colorTransitionEnabled > 0.5) {
3207
+ // Color transition mode: interpolate from start to end color over lifetime
2717
3208
  finalColor = mix(appearance.startColor, appearance.endColor, lifeRatio);
2718
3209
  } else {
3210
+ // Single color mode
2719
3211
  finalColor = appearance.singleColor;
2720
3212
  }
2721
3213
 
@@ -2859,8 +3351,8 @@ const j = `
2859
3351
  return finalColor;
2860
3352
  }
2861
3353
  `;
2862
- function Se(c) {
2863
- const t = c.createBindGroupLayout({
3354
+ function Ds(r) {
3355
+ const t = r.createBindGroupLayout({
2864
3356
  entries: [
2865
3357
  {
2866
3358
  binding: 0,
@@ -2883,7 +3375,7 @@ function Se(c) {
2883
3375
  sampler: {}
2884
3376
  }
2885
3377
  ]
2886
- }), e = c.createBindGroupLayout({
3378
+ }), e = r.createBindGroupLayout({
2887
3379
  entries: [
2888
3380
  {
2889
3381
  binding: 0,
@@ -2901,7 +3393,7 @@ function Se(c) {
2901
3393
  buffer: { type: "uniform" }
2902
3394
  }
2903
3395
  ]
2904
- }), i = c.createBindGroupLayout({
3396
+ }), i = r.createBindGroupLayout({
2905
3397
  entries: [
2906
3398
  {
2907
3399
  binding: 0,
@@ -2924,7 +3416,7 @@ function Se(c) {
2924
3416
  buffer: { type: "uniform" }
2925
3417
  }
2926
3418
  ]
2927
- }), a = c.createBindGroupLayout({
3419
+ }), s = r.createBindGroupLayout({
2928
3420
  entries: [
2929
3421
  {
2930
3422
  binding: 0,
@@ -2942,37 +3434,37 @@ function Se(c) {
2942
3434
  particleBindGroupLayout: t,
2943
3435
  bloomBindGroupLayout: e,
2944
3436
  compositeBindGroupLayout: i,
2945
- object3dBindGroupLayout: a
3437
+ object3dBindGroupLayout: s
2946
3438
  };
2947
3439
  }
2948
- function xe(c, t, e, i = {}) {
2949
- const { depthCompare: a } = i, r = a || "less", {
2950
- particleBindGroupLayout: n,
2951
- bloomBindGroupLayout: o,
2952
- compositeBindGroupLayout: s,
3440
+ function zs(r, t, e, i = {}) {
3441
+ const { depthCompare: s } = i, n = s || "less", {
3442
+ particleBindGroupLayout: o,
3443
+ bloomBindGroupLayout: a,
3444
+ compositeBindGroupLayout: c,
2953
3445
  object3dBindGroupLayout: l
2954
- } = e, u = c.createPipelineLayout({
2955
- bindGroupLayouts: [n]
2956
- }), d = c.createPipelineLayout({
3446
+ } = e, u = r.createPipelineLayout({
2957
3447
  bindGroupLayouts: [o]
2958
- }), f = c.createPipelineLayout({
2959
- bindGroupLayouts: [s]
2960
- }), h = c.createShaderModule({
2961
- code: j
2962
- }), p = c.createShaderModule({
2963
- code: N
2964
- }), m = c.createShaderModule({
2965
- code: X
2966
- }), b = c.createShaderModule({
2967
- code: k
2968
- }), S = c.createShaderModule({
2969
- code: ce
2970
- }), y = c.createShaderModule({
2971
- code: ue
2972
- }), P = c.createRenderPipeline({
3448
+ }), f = r.createPipelineLayout({
3449
+ bindGroupLayouts: [a]
3450
+ }), h = r.createPipelineLayout({
3451
+ bindGroupLayouts: [c]
3452
+ }), m = r.createShaderModule({
3453
+ code: bi
3454
+ }), S = r.createShaderModule({
3455
+ code: Si
3456
+ }), R = r.createShaderModule({
3457
+ code: xi
3458
+ }), D = r.createShaderModule({
3459
+ code: vi
3460
+ }), C = r.createShaderModule({
3461
+ code: Is
3462
+ }), B = r.createShaderModule({
3463
+ code: Gs
3464
+ }), A = (at) => r.createRenderPipeline({
2973
3465
  layout: u,
2974
3466
  vertex: {
2975
- module: h,
3467
+ module: m,
2976
3468
  entryPoint: "vs_main",
2977
3469
  buffers: [
2978
3470
  {
@@ -3033,22 +3525,11 @@ function xe(c, t, e, i = {}) {
3033
3525
  ]
3034
3526
  },
3035
3527
  fragment: {
3036
- module: h,
3528
+ module: m,
3037
3529
  entryPoint: "fs_main",
3038
3530
  targets: [{
3039
- format: t,
3040
- blend: {
3041
- color: {
3042
- srcFactor: "src-alpha",
3043
- dstFactor: "one-minus-src-alpha",
3044
- operation: "add"
3045
- },
3046
- alpha: {
3047
- srcFactor: "one",
3048
- dstFactor: "one-minus-src-alpha",
3049
- operation: "add"
3050
- }
3051
- }
3531
+ format: le,
3532
+ blend: at
3052
3533
  }]
3053
3534
  },
3054
3535
  primitive: {
@@ -3057,13 +3538,35 @@ function xe(c, t, e, i = {}) {
3057
3538
  },
3058
3539
  depthStencil: {
3059
3540
  depthWriteEnabled: !1,
3060
- depthCompare: r,
3541
+ depthCompare: n,
3061
3542
  format: "depth24plus"
3062
3543
  }
3063
- }), g = c.createRenderPipeline({
3544
+ }), P = A({
3545
+ color: {
3546
+ srcFactor: "src-alpha",
3547
+ dstFactor: "one-minus-src-alpha",
3548
+ operation: "add"
3549
+ },
3550
+ alpha: {
3551
+ srcFactor: "one",
3552
+ dstFactor: "one-minus-src-alpha",
3553
+ operation: "add"
3554
+ }
3555
+ }), _ = A({
3556
+ color: {
3557
+ srcFactor: "src-alpha",
3558
+ dstFactor: "one",
3559
+ operation: "add"
3560
+ },
3561
+ alpha: {
3562
+ srcFactor: "one",
3563
+ dstFactor: "one-minus-src-alpha",
3564
+ operation: "add"
3565
+ }
3566
+ }), T = r.createRenderPipeline({
3064
3567
  layout: u,
3065
3568
  vertex: {
3066
- module: h,
3569
+ module: m,
3067
3570
  entryPoint: "vs_main",
3068
3571
  buffers: [
3069
3572
  {
@@ -3124,10 +3627,10 @@ function xe(c, t, e, i = {}) {
3124
3627
  ]
3125
3628
  },
3126
3629
  fragment: {
3127
- module: h,
3630
+ module: m,
3128
3631
  entryPoint: "fs_main",
3129
3632
  targets: [{
3130
- format: t,
3633
+ format: le,
3131
3634
  writeMask: 0
3132
3635
  // No color write — depth only
3133
3636
  }]
@@ -3142,33 +3645,33 @@ function xe(c, t, e, i = {}) {
3142
3645
  // Always write depth (don't self-occlude)
3143
3646
  format: "depth24plus"
3144
3647
  }
3145
- }), x = c.createRenderPipeline({
3146
- layout: d,
3648
+ }), L = r.createRenderPipeline({
3649
+ layout: f,
3147
3650
  vertex: {
3148
- module: p,
3651
+ module: S,
3149
3652
  entryPoint: "vs_main"
3150
3653
  },
3151
3654
  fragment: {
3152
- module: p,
3655
+ module: S,
3153
3656
  entryPoint: "fs_main",
3154
3657
  targets: [{
3155
- format: t
3658
+ format: le
3156
3659
  }]
3157
3660
  },
3158
3661
  primitive: {
3159
3662
  topology: "triangle-list"
3160
3663
  }
3161
- }), M = c.createRenderPipeline({
3162
- layout: f,
3664
+ }), N = r.createRenderPipeline({
3665
+ layout: h,
3163
3666
  vertex: {
3164
- module: m,
3667
+ module: R,
3165
3668
  entryPoint: "vs_main"
3166
3669
  },
3167
3670
  fragment: {
3168
- module: m,
3671
+ module: R,
3169
3672
  entryPoint: "fs_main",
3170
3673
  targets: [{
3171
- format: t,
3674
+ format: le,
3172
3675
  blend: {
3173
3676
  color: {
3174
3677
  srcFactor: "one",
@@ -3186,17 +3689,17 @@ function xe(c, t, e, i = {}) {
3186
3689
  primitive: {
3187
3690
  topology: "triangle-list"
3188
3691
  }
3189
- }), R = c.createRenderPipeline({
3190
- layout: f,
3692
+ }), k = r.createRenderPipeline({
3693
+ layout: h,
3191
3694
  vertex: {
3192
- module: b,
3695
+ module: D,
3193
3696
  entryPoint: "vs_main"
3194
3697
  },
3195
3698
  fragment: {
3196
- module: b,
3699
+ module: D,
3197
3700
  entryPoint: "fs_main",
3198
3701
  targets: [{
3199
- format: t,
3702
+ format: le,
3200
3703
  blend: {
3201
3704
  color: {
3202
3705
  srcFactor: "one",
@@ -3214,12 +3717,27 @@ function xe(c, t, e, i = {}) {
3214
3717
  primitive: {
3215
3718
  topology: "triangle-list"
3216
3719
  }
3217
- }), B = c.createPipelineLayout({
3720
+ }), X = r.createShaderModule({ code: Pi }), z = r.createRenderPipeline({
3721
+ layout: h,
3722
+ vertex: { module: X, entryPoint: "vs_main" },
3723
+ fragment: {
3724
+ module: X,
3725
+ entryPoint: "fs_main",
3726
+ targets: [{
3727
+ format: t,
3728
+ blend: {
3729
+ color: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" },
3730
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" }
3731
+ }
3732
+ }]
3733
+ },
3734
+ primitive: { topology: "triangle-list" }
3735
+ }), me = r.createPipelineLayout({
3218
3736
  bindGroupLayouts: [l]
3219
- }), T = c.createRenderPipeline({
3220
- layout: B,
3737
+ }), De = r.createRenderPipeline({
3738
+ layout: me,
3221
3739
  vertex: {
3222
- module: S,
3740
+ module: C,
3223
3741
  entryPoint: "vs_main",
3224
3742
  buffers: [
3225
3743
  {
@@ -3244,10 +3762,10 @@ function xe(c, t, e, i = {}) {
3244
3762
  ]
3245
3763
  },
3246
3764
  fragment: {
3247
- module: S,
3765
+ module: C,
3248
3766
  entryPoint: "fs_main",
3249
3767
  targets: [{
3250
- format: t,
3768
+ format: le,
3251
3769
  blend: {
3252
3770
  color: {
3253
3771
  srcFactor: "src-alpha",
@@ -3268,13 +3786,13 @@ function xe(c, t, e, i = {}) {
3268
3786
  },
3269
3787
  depthStencil: {
3270
3788
  depthWriteEnabled: !0,
3271
- depthCompare: r,
3789
+ depthCompare: n,
3272
3790
  format: "depth24plus"
3273
3791
  }
3274
- }), w = c.createRenderPipeline({
3792
+ }), ze = r.createRenderPipeline({
3275
3793
  layout: u,
3276
3794
  vertex: {
3277
- module: y,
3795
+ module: B,
3278
3796
  entryPoint: "vs_main",
3279
3797
  buffers: [
3280
3798
  {
@@ -3346,10 +3864,10 @@ function xe(c, t, e, i = {}) {
3346
3864
  ]
3347
3865
  },
3348
3866
  fragment: {
3349
- module: y,
3867
+ module: B,
3350
3868
  entryPoint: "fs_main",
3351
3869
  targets: [{
3352
- format: t,
3870
+ format: le,
3353
3871
  blend: {
3354
3872
  color: {
3355
3873
  srcFactor: "src-alpha",
@@ -3370,33 +3888,35 @@ function xe(c, t, e, i = {}) {
3370
3888
  },
3371
3889
  depthStencil: {
3372
3890
  depthWriteEnabled: !0,
3373
- depthCompare: r,
3891
+ depthCompare: n,
3374
3892
  format: "depth24plus"
3375
3893
  }
3376
3894
  });
3377
3895
  return {
3378
3896
  particlePipeline: P,
3379
- particleDepthWritePipeline: g,
3380
- blurPipeline: x,
3381
- compositePipeline: M,
3382
- directRenderPipeline: R,
3383
- object3dPipeline: T,
3384
- glbMeshPipeline: w
3897
+ particleAdditivePipeline: _,
3898
+ particleDepthWritePipeline: T,
3899
+ blurPipeline: L,
3900
+ compositePipeline: N,
3901
+ directRenderPipeline: k,
3902
+ finalCompositePipeline: z,
3903
+ object3dPipeline: De,
3904
+ glbMeshPipeline: ze
3385
3905
  };
3386
3906
  }
3387
- function ve(c, t, e, i) {
3907
+ function St(r, t, e, i) {
3388
3908
  const {
3389
- uniformBuffer: a,
3390
- appearanceUniformBuffer: r,
3391
- horizontalBlurUniformBuffer: n,
3392
- verticalBlurUniformBuffer: o,
3393
- bloomIntensityBuffer: s
3909
+ uniformBuffer: s,
3910
+ appearanceUniformBuffer: n,
3911
+ horizontalBlurUniformBuffer: o,
3912
+ verticalBlurUniformBuffer: a,
3913
+ bloomIntensityBuffer: c
3394
3914
  } = e, {
3395
3915
  sceneTexture: l,
3396
3916
  bloomTexA: u,
3397
- bloomTexB: d
3398
- } = i, f = c.createBindGroup({
3399
- layout: c.createBindGroupLayout({
3917
+ bloomTexB: f
3918
+ } = i, h = r.createBindGroup({
3919
+ layout: r.createBindGroupLayout({
3400
3920
  entries: [
3401
3921
  {
3402
3922
  binding: 0,
@@ -3413,15 +3933,15 @@ function ve(c, t, e, i) {
3413
3933
  entries: [
3414
3934
  {
3415
3935
  binding: 0,
3416
- resource: { buffer: a }
3936
+ resource: { buffer: s }
3417
3937
  },
3418
3938
  {
3419
3939
  binding: 1,
3420
- resource: { buffer: r }
3940
+ resource: { buffer: n }
3421
3941
  }
3422
3942
  ]
3423
- }), h = c.createBindGroup({
3424
- layout: c.createBindGroupLayout({
3943
+ }), m = r.createBindGroup({
3944
+ layout: r.createBindGroupLayout({
3425
3945
  entries: [
3426
3946
  {
3427
3947
  binding: 0,
@@ -3451,11 +3971,11 @@ function ve(c, t, e, i) {
3451
3971
  },
3452
3972
  {
3453
3973
  binding: 2,
3454
- resource: { buffer: n }
3974
+ resource: { buffer: o }
3455
3975
  }
3456
3976
  ]
3457
- }), p = c.createBindGroup({
3458
- layout: c.createBindGroupLayout({
3977
+ }), S = r.createBindGroup({
3978
+ layout: r.createBindGroupLayout({
3459
3979
  entries: [
3460
3980
  {
3461
3981
  binding: 0,
@@ -3485,11 +4005,11 @@ function ve(c, t, e, i) {
3485
4005
  },
3486
4006
  {
3487
4007
  binding: 2,
3488
- resource: { buffer: o }
4008
+ resource: { buffer: a }
3489
4009
  }
3490
4010
  ]
3491
- }), m = c.createBindGroup({
3492
- layout: c.createBindGroupLayout({
4011
+ }), R = r.createBindGroup({
4012
+ layout: r.createBindGroupLayout({
3493
4013
  entries: [
3494
4014
  {
3495
4015
  binding: 0,
@@ -3524,15 +4044,15 @@ function ve(c, t, e, i) {
3524
4044
  },
3525
4045
  {
3526
4046
  binding: 2,
3527
- resource: d.createView()
4047
+ resource: f.createView()
3528
4048
  },
3529
4049
  {
3530
4050
  binding: 3,
3531
- resource: { buffer: s }
4051
+ resource: { buffer: c }
3532
4052
  }
3533
4053
  ]
3534
- }), b = c.createBindGroup({
3535
- layout: c.createBindGroupLayout({
4054
+ }), D = r.createBindGroup({
4055
+ layout: r.createBindGroupLayout({
3536
4056
  entries: [
3537
4057
  {
3538
4058
  binding: 0,
@@ -3567,24 +4087,24 @@ function ve(c, t, e, i) {
3567
4087
  },
3568
4088
  {
3569
4089
  binding: 2,
3570
- resource: d.createView()
4090
+ resource: f.createView()
3571
4091
  },
3572
4092
  {
3573
4093
  binding: 3,
3574
- resource: { buffer: s }
4094
+ resource: { buffer: c }
3575
4095
  }
3576
4096
  ]
3577
4097
  });
3578
4098
  return {
3579
- particleBindGroup: f,
3580
- horizontalBlurBindGroup: h,
3581
- verticalBlurBindGroup: p,
3582
- compositeBindGroup: m,
3583
- directRenderBindGroup: b
4099
+ particleBindGroup: h,
4100
+ horizontalBlurBindGroup: m,
4101
+ verticalBlurBindGroup: S,
4102
+ compositeBindGroup: R,
4103
+ directRenderBindGroup: D
3584
4104
  };
3585
4105
  }
3586
- function Pe(c) {
3587
- return c.createSampler({
4106
+ function Vs(r) {
4107
+ return r.createSampler({
3588
4108
  magFilter: "linear",
3589
4109
  minFilter: "linear",
3590
4110
  mipmapFilter: "linear",
@@ -3593,8 +4113,8 @@ function Pe(c) {
3593
4113
  maxAnisotropy: 16
3594
4114
  });
3595
4115
  }
3596
- function de() {
3597
- const c = new Float32Array([
4116
+ function Fs() {
4117
+ const r = new Float32Array([
3598
4118
  // Front face (z = 0.5)
3599
4119
  -0.5,
3600
4120
  -0.5,
@@ -3789,38 +4309,38 @@ function de() {
3789
4309
  23
3790
4310
  // left
3791
4311
  ]);
3792
- return { vertices: c, indices: t };
4312
+ return { vertices: r, indices: t };
3793
4313
  }
3794
- function fe(c = 16, t = 16) {
4314
+ function Os(r = 16, t = 16) {
3795
4315
  const e = [], i = [];
3796
- for (let a = 0; a <= c; a++) {
3797
- const r = a * Math.PI / c, n = Math.sin(r), o = Math.cos(r);
3798
- for (let s = 0; s <= t; s++) {
3799
- const l = s * 2 * Math.PI / t, u = Math.sin(l), f = Math.cos(l) * n, h = o, p = u * n;
3800
- e.push(f * 0.5, h * 0.5, p * 0.5), e.push(f, h, p);
4316
+ for (let s = 0; s <= r; s++) {
4317
+ const n = s * Math.PI / r, o = Math.sin(n), a = Math.cos(n);
4318
+ for (let c = 0; c <= t; c++) {
4319
+ const l = c * 2 * Math.PI / t, u = Math.sin(l), h = Math.cos(l) * o, m = a, S = u * o;
4320
+ e.push(h * 0.5, m * 0.5, S * 0.5), e.push(h, m, S);
3801
4321
  }
3802
4322
  }
3803
- for (let a = 0; a < c; a++)
3804
- for (let r = 0; r < t; r++) {
3805
- const n = a * (t + 1) + r, o = n + t + 1;
3806
- i.push(n), i.push(o), i.push(n + 1), i.push(o), i.push(o + 1), i.push(n + 1);
4323
+ for (let s = 0; s < r; s++)
4324
+ for (let n = 0; n < t; n++) {
4325
+ const o = s * (t + 1) + n, a = o + t + 1;
4326
+ i.push(o), i.push(a), i.push(o + 1), i.push(a), i.push(a + 1), i.push(o + 1);
3807
4327
  }
3808
4328
  return {
3809
4329
  vertices: new Float32Array(e),
3810
4330
  indices: new Uint16Array(i)
3811
4331
  };
3812
4332
  }
3813
- class he {
3814
- constructor(t, e, i, a, r) {
3815
- this.id = t, this.type = e, this.position = i, this.scale = a, this.color = r, this.rotation = [0, 0, 0];
4333
+ class Ls {
4334
+ constructor(t, e, i, s, n) {
4335
+ this.id = t, this.type = e, this.position = i, this.scale = s, this.color = n, this.rotation = [0, 0, 0];
3816
4336
  }
3817
4337
  /**
3818
4338
  * Get the model matrix for this object
3819
4339
  */
3820
4340
  getModelMatrix() {
3821
- const { position: t, scale: e, rotation: i } = this, a = this.createTranslationMatrix(t), r = this.createRotationMatrixX(i[0]), n = this.createRotationMatrixY(i[1]), o = this.createRotationMatrixZ(i[2]), s = this.createScaleMatrix(e);
3822
- let l = a;
3823
- return l = this.multiplyMatrices(l, o), l = this.multiplyMatrices(l, n), l = this.multiplyMatrices(l, r), l = this.multiplyMatrices(l, s), l;
4341
+ const { position: t, scale: e, rotation: i } = this, s = this.createTranslationMatrix(t), n = this.createRotationMatrixX(i[0]), o = this.createRotationMatrixY(i[1]), a = this.createRotationMatrixZ(i[2]), c = this.createScaleMatrix(e);
4342
+ let l = s;
4343
+ return l = this.multiplyMatrices(l, a), l = this.multiplyMatrices(l, o), l = this.multiplyMatrices(l, n), l = this.multiplyMatrices(l, c), l;
3824
4344
  }
3825
4345
  /**
3826
4346
  * Get the normal matrix (inverse transpose of model matrix)
@@ -3934,17 +4454,17 @@ class he {
3934
4454
  }
3935
4455
  multiplyMatrices(t, e) {
3936
4456
  const i = new Float32Array(16);
3937
- for (let a = 0; a < 4; a++)
3938
- for (let r = 0; r < 4; r++) {
3939
- let n = 0;
3940
- for (let o = 0; o < 4; o++)
3941
- n += t[a * 4 + o] * e[o * 4 + r];
3942
- i[a * 4 + r] = n;
4457
+ for (let s = 0; s < 4; s++)
4458
+ for (let n = 0; n < 4; n++) {
4459
+ let o = 0;
4460
+ for (let a = 0; a < 4; a++)
4461
+ o += t[s * 4 + a] * e[a * 4 + n];
4462
+ i[s * 4 + n] = o;
3943
4463
  }
3944
4464
  return i;
3945
4465
  }
3946
4466
  }
3947
- class Me {
4467
+ class Zs {
3948
4468
  constructor(t) {
3949
4469
  this.device = t, this.objects = [], this.nextId = 0, this.initializeGeometry(), this.onObjectAdded = null, this.onObjectRemoved = null, this.onObjectUpdated = null;
3950
4470
  }
@@ -3952,20 +4472,20 @@ class Me {
3952
4472
  * Initialize geometry buffers for cube and sphere
3953
4473
  */
3954
4474
  initializeGeometry() {
3955
- const t = de(), e = fe(16, 16);
3956
- this.cubeVertexBuffer = E(
4475
+ const t = Fs(), e = Os(16, 16);
4476
+ this.cubeVertexBuffer = Ge(
3957
4477
  this.device,
3958
4478
  t.vertices,
3959
4479
  GPUBufferUsage.VERTEX
3960
- ), this.cubeIndexBuffer = E(
4480
+ ), this.cubeIndexBuffer = Ge(
3961
4481
  this.device,
3962
4482
  t.indices,
3963
4483
  GPUBufferUsage.INDEX
3964
- ), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer = E(
4484
+ ), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer = Ge(
3965
4485
  this.device,
3966
4486
  e.vertices,
3967
4487
  GPUBufferUsage.VERTEX
3968
- ), this.sphereIndexBuffer = E(
4488
+ ), this.sphereIndexBuffer = Ge(
3969
4489
  this.device,
3970
4490
  e.indices,
3971
4491
  GPUBufferUsage.INDEX
@@ -3979,13 +4499,13 @@ class Me {
3979
4499
  * @param {Array} color - [r, g, b, a] (optional, defaults to white)
3980
4500
  * @returns {Object3D} The created object
3981
4501
  */
3982
- addObject(t, e = [0, 0, 0], i = [1, 1, 1], a = [1, 1, 1, 1]) {
3983
- const r = new he(this.nextId++, t, e, i, a);
3984
- return r.uniformBuffer = this.device.createBuffer({
4502
+ addObject(t, e = [0, 0, 0], i = [1, 1, 1], s = [1, 1, 1, 1]) {
4503
+ const n = new Ls(this.nextId++, t, e, i, s);
4504
+ return n.uniformBuffer = this.device.createBuffer({
3985
4505
  size: 192,
3986
4506
  // modelMatrix (64) + normalMatrix (64) + color (16) + padding (48)
3987
4507
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
3988
- }), this.objects.push(r), this.onObjectAdded && this.onObjectAdded(r), r;
4508
+ }), this.objects.push(n), this.onObjectAdded && this.onObjectAdded(n), n;
3989
4509
  }
3990
4510
  /**
3991
4511
  * Remove an object by ID
@@ -4001,7 +4521,7 @@ class Me {
4001
4521
  * @param {Array} position - [x, y, z]
4002
4522
  */
4003
4523
  updateObjectPosition(t, e) {
4004
- const i = this.objects.find((a) => a.id === t);
4524
+ const i = this.objects.find((s) => s.id === t);
4005
4525
  i && (i.position = e, this.onObjectUpdated && this.onObjectUpdated(i));
4006
4526
  }
4007
4527
  /**
@@ -4010,7 +4530,7 @@ class Me {
4010
4530
  * @param {Array} scale - [sx, sy, sz]
4011
4531
  */
4012
4532
  updateObjectScale(t, e) {
4013
- const i = this.objects.find((a) => a.id === t);
4533
+ const i = this.objects.find((s) => s.id === t);
4014
4534
  i && (i.scale = e, this.onObjectUpdated && this.onObjectUpdated(i));
4015
4535
  }
4016
4536
  /**
@@ -4019,7 +4539,7 @@ class Me {
4019
4539
  * @param {Array} color - [r, g, b, a]
4020
4540
  */
4021
4541
  updateObjectColor(t, e) {
4022
- const i = this.objects.find((a) => a.id === t);
4542
+ const i = this.objects.find((s) => s.id === t);
4023
4543
  i && (i.color = e, this.onObjectUpdated && this.onObjectUpdated(i));
4024
4544
  }
4025
4545
  /**
@@ -4040,78 +4560,78 @@ class Me {
4040
4560
  * @param {Object3D} object
4041
4561
  */
4042
4562
  updateObjectUniforms(t) {
4043
- const e = t.getModelMatrix(), i = t.getNormalMatrix(), a = new Float32Array(t.color);
4044
- this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128, a);
4563
+ const e = t.getModelMatrix(), i = t.getNormalMatrix(), s = new Float32Array(t.color);
4564
+ this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128, s);
4045
4565
  }
4046
4566
  /**
4047
4567
  * Render all objects
4048
4568
  * @param {GPURenderPassEncoder} passEncoder
4049
4569
  * @param {GPUBindGroup} cameraBindGroup - Bind group with camera uniforms
4050
4570
  */
4051
- renderObjects(t, e, i, a) {
4052
- for (const r of this.objects) {
4053
- this.updateObjectUniforms(r);
4054
- const n = this.device.createBindGroup({
4571
+ renderObjects(t, e, i, s) {
4572
+ for (const n of this.objects) {
4573
+ this.updateObjectUniforms(n);
4574
+ const o = this.device.createBindGroup({
4055
4575
  layout: i,
4056
4576
  entries: [
4057
- { binding: 0, resource: { buffer: a } },
4058
- { binding: 1, resource: { buffer: r.uniformBuffer } }
4577
+ { binding: 0, resource: { buffer: s } },
4578
+ { binding: 1, resource: { buffer: n.uniformBuffer } }
4059
4579
  ]
4060
4580
  });
4061
- let o, s, l;
4062
- if (r.type === "cube")
4063
- o = this.cubeVertexBuffer, s = this.cubeIndexBuffer, l = this.cubeIndexCount;
4064
- else if (r.type === "sphere")
4065
- o = this.sphereVertexBuffer, s = this.sphereIndexBuffer, l = this.sphereIndexCount;
4581
+ let a, c, l;
4582
+ if (n.type === "cube")
4583
+ a = this.cubeVertexBuffer, c = this.cubeIndexBuffer, l = this.cubeIndexCount;
4584
+ else if (n.type === "sphere")
4585
+ a = this.sphereVertexBuffer, c = this.sphereIndexBuffer, l = this.sphereIndexCount;
4066
4586
  else
4067
4587
  continue;
4068
- t.setPipeline(e), t.setBindGroup(0, n), t.setVertexBuffer(0, o), t.setIndexBuffer(s, "uint16"), t.drawIndexed(l);
4588
+ t.setPipeline(e), t.setBindGroup(0, o), t.setVertexBuffer(0, a), t.setIndexBuffer(c, "uint16"), t.drawIndexed(l);
4069
4589
  }
4070
4590
  }
4071
4591
  }
4072
- function Re(c) {
4073
- const t = parseInt(c.slice(1, 3), 16) / 255, e = parseInt(c.slice(3, 5), 16) / 255, i = parseInt(c.slice(5, 7), 16) / 255;
4592
+ function $s(r) {
4593
+ const t = parseInt(r.slice(1, 3), 16) / 255, e = parseInt(r.slice(3, 5), 16) / 255, i = parseInt(r.slice(5, 7), 16) / 255;
4074
4594
  return [t, e, i];
4075
4595
  }
4076
- function we(c) {
4077
- if (!c) return "#ffffff";
4078
- const t = Math.round(c[0] * 255).toString(16).padStart(2, "0"), e = Math.round(c[1] * 255).toString(16).padStart(2, "0"), i = Math.round(c[2] * 255).toString(16).padStart(2, "0");
4596
+ function Ws(r) {
4597
+ if (!r) return "#ffffff";
4598
+ const t = Math.round(r[0] * 255).toString(16).padStart(2, "0"), e = Math.round(r[1] * 255).toString(16).padStart(2, "0"), i = Math.round(r[2] * 255).toString(16).padStart(2, "0");
4079
4599
  return `#${t}${e}${i}`;
4080
4600
  }
4081
- function Be(c, t, e) {
4082
- const i = V([
4083
- c[0] - t[0],
4084
- c[1] - t[1],
4085
- c[2] - t[2]
4086
- ]), a = V(L(e, i)), r = L(i, a);
4601
+ function Js(r, t, e) {
4602
+ const i = fi([
4603
+ r[0] - t[0],
4604
+ r[1] - t[1],
4605
+ r[2] - t[2]
4606
+ ]), s = fi(pi(e, i)), n = pi(i, s);
4087
4607
  return new Float32Array([
4088
- a[0],
4089
- r[0],
4608
+ s[0],
4609
+ n[0],
4090
4610
  i[0],
4091
4611
  0,
4092
- a[1],
4093
- r[1],
4612
+ s[1],
4613
+ n[1],
4094
4614
  i[1],
4095
4615
  0,
4096
- a[2],
4097
- r[2],
4616
+ s[2],
4617
+ n[2],
4098
4618
  i[2],
4099
4619
  0,
4100
- -A(a, c),
4101
- -A(r, c),
4102
- -A(i, c),
4620
+ -xt(s, r),
4621
+ -xt(n, r),
4622
+ -xt(i, r),
4103
4623
  1
4104
4624
  ]);
4105
4625
  }
4106
- function Te(c, t = Math.PI / 4) {
4107
- const a = 1 / Math.tan(t / 2);
4626
+ function Ks(r, t = Math.PI / 4) {
4627
+ const s = 1 / Math.tan(t / 2);
4108
4628
  return new Float32Array([
4109
- a * c,
4629
+ s * r,
4110
4630
  0,
4111
4631
  0,
4112
4632
  0,
4113
4633
  0,
4114
- a,
4634
+ s,
4115
4635
  0,
4116
4636
  0,
4117
4637
  0,
@@ -4124,264 +4644,1032 @@ function Te(c, t = Math.PI / 4) {
4124
4644
  0
4125
4645
  ]);
4126
4646
  }
4127
- function V(c) {
4128
- const t = Math.sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
4129
- return [c[0] / t, c[1] / t, c[2] / t];
4647
+ function fi(r) {
4648
+ const t = Math.sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]);
4649
+ return [r[0] / t, r[1] / t, r[2] / t];
4130
4650
  }
4131
- function L(c, t) {
4651
+ function pi(r, t) {
4132
4652
  return [
4133
- c[1] * t[2] - c[2] * t[1],
4134
- c[2] * t[0] - c[0] * t[2],
4135
- c[0] * t[1] - c[1] * t[0]
4653
+ r[1] * t[2] - r[2] * t[1],
4654
+ r[2] * t[0] - r[0] * t[2],
4655
+ r[0] * t[1] - r[1] * t[0]
4136
4656
  ];
4137
4657
  }
4138
- function A(c, t) {
4139
- return c[0] * t[0] + c[1] * t[1] + c[2] * t[2];
4658
+ function xt(r, t) {
4659
+ return r[0] * t[0] + r[1] * t[1] + r[2] * t[2];
4140
4660
  }
4141
- function Ee(c, t) {
4661
+ function Ns(r, t) {
4142
4662
  const e = new Float32Array(16);
4143
4663
  for (let i = 0; i < 4; i++)
4144
- for (let a = 0; a < 4; a++) {
4145
- let r = 0;
4146
- for (let n = 0; n < 4; n++)
4147
- r += c[i + n * 4] * t[n + a * 4];
4148
- e[i + a * 4] = r;
4664
+ for (let s = 0; s < 4; s++) {
4665
+ let n = 0;
4666
+ for (let o = 0; o < 4; o++)
4667
+ n += r[i + o * 4] * t[o + s * 4];
4668
+ e[i + s * 4] = n;
4149
4669
  }
4150
4670
  return e;
4151
4671
  }
4152
- function pe(c) {
4153
- const t = new Uint8Array(c);
4672
+ const Pt = 1481005640, wi = 1, Bi = 1313821514, Ri = 5130562, He = "$hzfxAsset", Mi = (r) => typeof atob == "function" ? Uint8Array.from(atob(r), (t) => t.charCodeAt(0)) : new Uint8Array(Buffer.from(r, "base64")), hi = (r) => {
4673
+ if (typeof btoa == "function") {
4674
+ let t = "";
4675
+ for (let e = 0; e < r.length; e++) t += String.fromCharCode(r[e]);
4676
+ return btoa(t);
4677
+ }
4678
+ return Buffer.from(r).toString("base64");
4679
+ };
4680
+ function Xs(r) {
4681
+ const t = r.indexOf(","), e = r.slice(5, t), i = e.split(";")[0] || "application/octet-stream", s = r.slice(t + 1), o = /;base64/i.test(e) ? Mi(s) : new TextEncoder().encode(decodeURIComponent(s));
4682
+ return { mime: i, bytes: o };
4683
+ }
4684
+ function mi(r) {
4685
+ return (4 - r % 4) % 4;
4686
+ }
4687
+ async function ks(r, t = {}) {
4688
+ const { textureFormat: e = "keep", quality: i = 0.85 } = t, s = [], n = [];
4689
+ let o = 0;
4690
+ const a = (_, T, L) => {
4691
+ const N = o, k = _.length;
4692
+ s.push({ offset: N, length: k, mime: T, kind: L }), n.push(_), o += k;
4693
+ const X = mi(k);
4694
+ return X && (n.push(new Uint8Array(X)), o += X), s.length - 1;
4695
+ }, c = e === "webp" && typeof OffscreenCanvas < "u" && typeof createImageBitmap == "function", l = [];
4696
+ for (const _ of r.systems || []) {
4697
+ const T = { ..._ };
4698
+ if (typeof T.textureImageData == "string" && T.textureImageData.startsWith("data:")) {
4699
+ let { mime: L, bytes: N } = Xs(T.textureImageData);
4700
+ if (c && L !== "image/webp")
4701
+ try {
4702
+ const k = await createImageBitmap(new Blob([N], { type: L })), X = new OffscreenCanvas(k.width, k.height);
4703
+ X.getContext("2d").drawImage(k, 0, 0);
4704
+ const z = await X.convertToBlob({ type: "image/webp", quality: i }), me = new Uint8Array(await z.arrayBuffer());
4705
+ me.length < N.length && (N = me, L = "image/webp");
4706
+ } catch {
4707
+ }
4708
+ T.textureImageData = { [He]: a(N, L, "texture") };
4709
+ }
4710
+ if (typeof T.glbModelData == "string" && T.glbModelData.length > 0) {
4711
+ const L = Mi(T.glbModelData);
4712
+ T.glbModelData = { [He]: a(L, "model/gltf-binary", "glb") };
4713
+ }
4714
+ l.push(T);
4715
+ }
4716
+ const u = { ...r, systems: l, assets: s }, f = new TextEncoder().encode(JSON.stringify(u)), h = mi(f.length), m = new Uint8Array(o);
4717
+ let S = 0;
4718
+ for (const _ of n)
4719
+ m.set(_, S), S += _.length;
4720
+ const R = f.length + h, D = 20 + R + 8 + o, C = new ArrayBuffer(D), B = new DataView(C), A = new Uint8Array(C);
4721
+ let P = 0;
4722
+ B.setUint32(P, Pt, !0), P += 4, B.setUint32(P, wi, !0), P += 4, B.setUint32(P, D, !0), P += 4, B.setUint32(P, R, !0), P += 4, B.setUint32(P, Bi, !0), P += 4, A.set(f, P), P += f.length;
4723
+ for (let _ = 0; _ < h; _++) A[P++] = 32;
4724
+ return B.setUint32(P, o, !0), P += 4, B.setUint32(P, Ri, !0), P += 4, A.set(m, P), P += o, C;
4725
+ }
4726
+ function Ti(r) {
4727
+ return !r || r.byteLength < 12 ? !1 : new DataView(r).getUint32(0, !0) === Pt;
4728
+ }
4729
+ function Ei(r) {
4730
+ const t = new DataView(r);
4731
+ if (t.getUint32(0, !0) !== Pt) throw new Error("[unpackHZFX] bad magic — not an .hzfx file");
4732
+ const e = t.getUint32(4, !0);
4733
+ if (e !== wi) throw new Error(`[unpackHZFX] unsupported version ${e}`);
4734
+ let i = 12, s = null, n = -1;
4735
+ const o = new Uint8Array(r);
4736
+ for (; i + 8 <= r.byteLength; ) {
4737
+ const h = t.getUint32(i, !0);
4738
+ i += 4;
4739
+ const m = t.getUint32(i, !0);
4740
+ i += 4, m === Bi ? s = JSON.parse(new TextDecoder().decode(o.subarray(i, i + h))) : m === Ri && (n = i), i += h;
4741
+ }
4742
+ if (!s) throw new Error("[unpackHZFX] missing JSON chunk");
4743
+ const a = s.assets || [], c = (h) => {
4744
+ const m = a[h];
4745
+ return !m || n < 0 ? null : { ...m, bytes: o.subarray(n + m.offset, n + m.offset + m.length) };
4746
+ }, l = (h) => h && typeof h == "object" && typeof h[He] == "number", u = (s.systems || []).map((h) => {
4747
+ const m = { ...h };
4748
+ if (l(m.textureImageData)) {
4749
+ const S = c(m.textureImageData[He]);
4750
+ m.textureImageData = S ? `data:${S.mime};base64,${hi(S.bytes)}` : void 0;
4751
+ }
4752
+ if (l(m.glbModelData)) {
4753
+ const S = c(m.glbModelData[He]);
4754
+ m.glbModelData = S ? hi(S.bytes) : void 0;
4755
+ }
4756
+ return m;
4757
+ }), f = { ...s, systems: u };
4758
+ return delete f.assets, f;
4759
+ }
4760
+ function js(r) {
4761
+ const t = new Uint8Array(r);
4154
4762
  let e = "";
4155
4763
  for (let i = 0; i < t.byteLength; i++)
4156
4764
  e += String.fromCharCode(t[i]);
4157
4765
  return btoa(e);
4158
4766
  }
4159
- function _e(c, t) {
4160
- if (!c || !c.particleSystems || c.particleSystems.length === 0) {
4767
+ function Ys(r) {
4768
+ return {
4769
+ name: r.name,
4770
+ id: r.id,
4771
+ particleCount: r.particleCount,
4772
+ lifetime: r.lifetime,
4773
+ emissionRate: r.emissionRate,
4774
+ emissionDuration: r.emissionDuration,
4775
+ emissionDurationInfinite: r.emissionDurationInfinite || !1,
4776
+ particleSize: r.particleSize,
4777
+ particleSpeed: r.particleSpeed,
4778
+ emissionShape: r.emissionShape,
4779
+ outerLength: r.outerLength ?? r.cubeLength,
4780
+ // cubeLength = legacy alias; migrate to outerLength
4781
+ innerLength: r.innerLength,
4782
+ outerRadius: r.outerRadius,
4783
+ innerRadius: r.innerRadius,
4784
+ squareSize: r.squareSize,
4785
+ squareInnerSize: r.squareInnerSize,
4786
+ circleInnerRadius: r.circleInnerRadius,
4787
+ circleOuterRadius: r.circleOuterRadius,
4788
+ fadeEnabled: r.fadeEnabled,
4789
+ colorTransitionEnabled: r.colorTransitionEnabled,
4790
+ particleColor: r.particleColor,
4791
+ startColor: r.startColor,
4792
+ endColor: r.endColor,
4793
+ randomColorEnabled: r.randomColorEnabled || !1,
4794
+ randomColors: r.randomColors || [],
4795
+ particleShape: r.particleShape || "square",
4796
+ particleShapeRotationX: r.particleShapeRotationX || 0,
4797
+ particleShapeRotationY: r.particleShapeRotationY || 0,
4798
+ particleShapeRotationZ: r.particleShapeRotationZ || 0,
4799
+ pulseEnabled: r.pulseEnabled || !1,
4800
+ pulseAmplitude: r.pulseAmplitude ?? 0.5,
4801
+ pulseFrequency: r.pulseFrequency ?? 1,
4802
+ pulsePhaseRandom: r.pulsePhaseRandom ?? 0,
4803
+ pulseOpacity: r.pulseOpacity || !1,
4804
+ bloomEnabled: r.bloomEnabled,
4805
+ bloomIntensity: r.bloomIntensity,
4806
+ bloomColor: r.bloomColor,
4807
+ depthWriteEnabled: r.depthWriteEnabled || !1,
4808
+ burstMode: r.burstMode,
4809
+ gravityEnabled: r.gravityEnabled,
4810
+ gravityStrength: r.gravityStrength,
4811
+ dampingEnabled: r.dampingEnabled,
4812
+ dampingStrength: r.dampingStrength,
4813
+ attractorEnabled: r.attractorEnabled,
4814
+ attractorStrength: r.attractorStrength,
4815
+ attractorPosition: r.attractorPosition,
4816
+ emissionRotationX: r.emissionRotationX,
4817
+ emissionRotationY: r.emissionRotationY,
4818
+ emissionRotationZ: r.emissionRotationZ,
4819
+ orientToDirection: r.orientToDirection ?? !1,
4820
+ emissionPositionX: r.emissionPositionX,
4821
+ emissionPositionY: r.emissionPositionY,
4822
+ emissionPositionZ: r.emissionPositionZ,
4823
+ rotation: r.rotation,
4824
+ rotationMode: r.rotationMode,
4825
+ minRotation: r.minRotation,
4826
+ maxRotation: r.maxRotation,
4827
+ overrideXVelocity: r.overrideXVelocity,
4828
+ overrideYVelocity: r.overrideYVelocity,
4829
+ overrideZVelocity: r.overrideZVelocity,
4830
+ xVelocity: r.xVelocity,
4831
+ yVelocity: r.yVelocity,
4832
+ zVelocity: r.zVelocity,
4833
+ circleVelocityDirection: r.circleVelocityDirection,
4834
+ cylinderVelocityDirection: r.cylinderVelocityDirection,
4835
+ cylinderInnerRadius: r.cylinderInnerRadius,
4836
+ cylinderOuterRadius: r.cylinderOuterRadius,
4837
+ cylinderHeight: r.cylinderHeight,
4838
+ planeWidth: r.planeWidth,
4839
+ planeDepth: r.planeDepth,
4840
+ rectangleWidth: r.rectangleWidth,
4841
+ rectangleHeight: r.rectangleHeight,
4842
+ coneOuterRadius: r.coneOuterRadius,
4843
+ coneInnerRadius: r.coneInnerRadius,
4844
+ coneHeight: r.coneHeight,
4845
+ torusMajorRadius: r.torusMajorRadius,
4846
+ torusMinorRadius: r.torusMinorRadius,
4847
+ lineLength: r.lineLength,
4848
+ hemisphereOuterRadius: r.hemisphereOuterRadius,
4849
+ hemisphereInnerRadius: r.hemisphereInnerRadius,
4850
+ discRadius: r.discRadius,
4851
+ annulusInnerRadius: r.annulusInnerRadius,
4852
+ annulusOuterRadius: r.annulusOuterRadius,
4853
+ capsuleRadius: r.capsuleRadius,
4854
+ capsuleHeight: r.capsuleHeight,
4855
+ arcStartAngle: r.arcStartAngle,
4856
+ arcEndAngle: r.arcEndAngle,
4857
+ arcInnerRadius: r.arcInnerRadius,
4858
+ arcOuterRadius: r.arcOuterRadius,
4859
+ spiralTurns: r.spiralTurns,
4860
+ spiralRadiusStart: r.spiralRadiusStart,
4861
+ spiralRadiusEnd: r.spiralRadiusEnd,
4862
+ spiralHeight: r.spiralHeight,
4863
+ frustumRadiusNear: r.frustumRadiusNear,
4864
+ frustumRadiusFar: r.frustumRadiusFar,
4865
+ frustumHeight: r.frustumHeight,
4866
+ cubeSurfaceSize: r.cubeSurfaceSize,
4867
+ sphereSurfaceRadius: r.sphereSurfaceRadius,
4868
+ boxFrameSize: r.boxFrameSize,
4869
+ polygonSides: r.polygonSides,
4870
+ polygonRadius: r.polygonRadius,
4871
+ aspectRatio: r.aspectRatio,
4872
+ randomSize: r.randomSize,
4873
+ minSize: r.minSize,
4874
+ maxSize: r.maxSize,
4875
+ fadeSizeEnabled: r.fadeSizeEnabled,
4876
+ increaseSizeEnabled: r.increaseSizeEnabled,
4877
+ sizeLifetimeSpeed: r.sizeLifetimeSpeed,
4878
+ opacity: r.opacity,
4879
+ randomSpeed: r.randomSpeed,
4880
+ minSpeed: r.minSpeed,
4881
+ maxSpeed: r.maxSpeed,
4882
+ oneOnlyMode: r.oneOnlyMode,
4883
+ confinementEnabled: r.confinementEnabled || !1,
4884
+ confinementShape: r.confinementShape || "box",
4885
+ confinementMode: r.confinementMode || "bounce",
4886
+ confinementSpace: r.confinementSpace || "world",
4887
+ confinementBoxHalfSize: r.confinementBoxHalfSize || [2, 2, 2],
4888
+ confinementSphereRadius: r.confinementSphereRadius ?? 3,
4889
+ confinementRestitution: r.confinementRestitution ?? 0.8,
4890
+ confinementFriction: r.confinementFriction ?? 0.1,
4891
+ confinementCenter: r.confinementCenter,
4892
+ softBoundaryEnabled: r.softBoundaryEnabled || !1,
4893
+ softBoundaryStrength: r.softBoundaryStrength ?? 5,
4894
+ softBoundaryFalloff: r.softBoundaryFalloff ?? 0.5,
4895
+ followSystemId: r.followSystemId || null,
4896
+ followSystemTranslation: r.followSystemTranslation ?? !0,
4897
+ hidden: r.hidden || !1,
4898
+ emissionTrailEnabled: r.emissionTrailEnabled || !1,
4899
+ emissionTrailDuration: r.emissionTrailDuration ?? 1,
4900
+ emissionTrailWidth: r.emissionTrailWidth ?? 0.5,
4901
+ emissionTrailMinDistance: r.emissionTrailMinDistance ?? 0.05,
4902
+ emissionTrailMaxPoints: r.emissionTrailMaxPoints ?? 100,
4903
+ emissionTrailSegments: r.emissionTrailSegments ?? 8,
4904
+ emissionTrailMode: r.emissionTrailMode ?? "ribbon",
4905
+ emissionTrailShape: r.emissionTrailShape ?? "straight",
4906
+ emissionTrailShapeAmplitude: r.emissionTrailShapeAmplitude ?? 0.1,
4907
+ emissionTrailShapeFrequency: r.emissionTrailShapeFrequency ?? 4,
4908
+ emissionTrailShapeSpeed: r.emissionTrailShapeSpeed ?? 0,
4909
+ shapeDisplay: r.shapeDisplay ?? !0,
4910
+ blendMode: r.blendMode ?? "normal",
4911
+ noiseDistortEnabled: r.noiseDistortEnabled || !1,
4912
+ noiseTilingX: r.noiseTilingX ?? 3,
4913
+ noiseTilingY: r.noiseTilingY ?? 3,
4914
+ noiseSpeed: r.noiseSpeed ?? -1.5,
4915
+ noiseAmplitude: r.noiseAmplitude ?? 0.08,
4916
+ velocityStretchEnabled: r.velocityStretchEnabled || !1,
4917
+ velocityStretchFactor: r.velocityStretchFactor ?? 1,
4918
+ // Texture / GLB metadata (the binary payloads — textureImageData / glbModelData — are
4919
+ // added by the caller since their encoding differs per export target)
4920
+ textureEnabled: r.textureEnabled || !1,
4921
+ textureType: r.textureType,
4922
+ textureFileName: r.textureFileName,
4923
+ imageDescription: r.imageDescription,
4924
+ glbModelEnabled: r.glbModelEnabled || !1,
4925
+ glbFileName: r.glbFileName,
4926
+ glbHasTexture: r.glbHasTexture || !1,
4927
+ useGlbTexture: r.useGlbTexture || !1,
4928
+ glbAnimated: r.glbAnimated || !1,
4929
+ animationIndex: r.animationIndex,
4930
+ animationSpeed: r.animationSpeed,
4931
+ animationLoop: r.animationLoop,
4932
+ glbDescription: r.glbDescription,
4933
+ script: r.script || void 0,
4934
+ displayUnit: r.displayUnit || "m"
4935
+ };
4936
+ }
4937
+ async function Qs(r, t, e = "hzfx") {
4938
+ if (!r || !r.particleSystems || r.particleSystems.length === 0) {
4161
4939
  alert("No particle systems to save.");
4162
4940
  return;
4163
4941
  }
4164
4942
  try {
4165
- const e = {
4943
+ const i = {
4166
4944
  version: "1.0",
4167
4945
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4168
- systems: c.particleSystems.map(({ config: s, system: l }) => ({
4169
- // Include only the serializable properties of each system
4170
- name: s.name,
4171
- id: s.id,
4172
- particleCount: s.particleCount,
4173
- lifetime: s.lifetime,
4174
- emissionRate: s.emissionRate,
4175
- emissionDuration: s.emissionDuration,
4176
- particleSize: s.particleSize,
4177
- particleSpeed: s.particleSpeed,
4178
- emissionShape: s.emissionShape,
4179
- cubeLength: s.outerLength || s.cubeLength,
4180
- // Always use outerLength if available
4181
- outerLength: s.outerLength || s.cubeLength,
4182
- // Keep them synchronized
4183
- innerLength: s.innerLength,
4184
- outerRadius: s.outerRadius,
4185
- innerRadius: s.innerRadius,
4186
- squareSize: s.squareSize,
4187
- squareInnerSize: s.squareInnerSize,
4188
- circleInnerRadius: s.circleInnerRadius,
4189
- circleOuterRadius: s.circleOuterRadius,
4190
- fadeEnabled: s.fadeEnabled,
4191
- colorTransitionEnabled: s.colorTransitionEnabled,
4192
- particleColor: s.particleColor,
4193
- startColor: s.startColor,
4194
- endColor: s.endColor,
4195
- randomColorEnabled: s.randomColorEnabled || !1,
4196
- randomColors: s.randomColors || [],
4197
- particleShape: s.particleShape || "square",
4198
- particleShapeRotation: s.particleShapeRotation || 0,
4199
- particleShapeRotationX: s.particleShapeRotationX || 0,
4200
- particleShapeRotationY: s.particleShapeRotationY || 0,
4201
- particleShapeRotationZ: s.particleShapeRotationZ || 0,
4202
- pulseEnabled: s.pulseEnabled || !1,
4203
- pulseAmplitude: s.pulseAmplitude ?? 0.5,
4204
- pulseFrequency: s.pulseFrequency ?? 1,
4205
- pulsePhaseRandom: s.pulsePhaseRandom ?? 0,
4206
- pulseOpacity: s.pulseOpacity || !1,
4207
- bloomEnabled: s.bloomEnabled,
4208
- bloomIntensity: s.bloomIntensity,
4209
- burstMode: s.burstMode,
4210
- gravityEnabled: s.gravityEnabled,
4211
- gravityStrength: s.gravityStrength,
4212
- dampingEnabled: s.dampingEnabled,
4213
- dampingStrength: s.dampingStrength,
4214
- attractorEnabled: s.attractorEnabled,
4215
- attractorStrength: s.attractorStrength,
4216
- attractorPosition: s.attractorPosition,
4217
- shapeRotationX: s.shapeRotationX,
4218
- shapeRotationY: s.shapeRotationY,
4219
- shapeRotationZ: s.shapeRotationZ,
4220
- shapeTranslationX: s.shapeTranslationX,
4221
- shapeTranslationY: s.shapeTranslationY,
4222
- shapeTranslationZ: s.shapeTranslationZ,
4223
- rotation: s.rotation,
4224
- rotationMode: s.rotationMode,
4225
- minRotation: s.minRotation,
4226
- maxRotation: s.maxRotation,
4227
- overrideXVelocity: s.overrideXVelocity,
4228
- overrideYVelocity: s.overrideYVelocity,
4229
- overrideZVelocity: s.overrideZVelocity,
4230
- xVelocity: s.xVelocity,
4231
- yVelocity: s.yVelocity,
4232
- zVelocity: s.zVelocity,
4233
- circleVelocityDirection: s.circleVelocityDirection,
4234
- cylinderVelocityDirection: s.cylinderVelocityDirection,
4235
- cylinderInnerRadius: s.cylinderInnerRadius,
4236
- cylinderOuterRadius: s.cylinderOuterRadius,
4237
- cylinderHeight: s.cylinderHeight,
4238
- aspectRatio: s.aspectRatio,
4239
- randomSize: s.randomSize,
4240
- minSize: s.minSize,
4241
- maxSize: s.maxSize,
4242
- fadeSizeEnabled: s.fadeSizeEnabled,
4243
- increaseSizeEnabled: s.increaseSizeEnabled,
4244
- sizeLifetimeSpeed: s.sizeLifetimeSpeed,
4245
- opacity: s.opacity,
4246
- randomSpeed: s.randomSpeed,
4247
- minSpeed: s.minSpeed,
4248
- maxSpeed: s.maxSpeed,
4249
- textureEnabled: s.textureEnabled,
4250
- textureType: s.textureType,
4251
- glbModelEnabled: s.glbModelEnabled,
4252
- glbFileName: s.glbFileName,
4253
- glbAnimated: s.glbAnimated,
4254
- animationIndex: s.animationIndex,
4255
- animationSpeed: s.animationSpeed,
4256
- animationLoop: s.animationLoop,
4257
- useGlbTexture: s.useGlbTexture,
4258
- oneOnlyMode: s.oneOnlyMode,
4259
- confinementEnabled: s.confinementEnabled || !1,
4260
- confinementShape: s.confinementShape || "box",
4261
- confinementMode: s.confinementMode || "bounce",
4262
- confinementSpace: s.confinementSpace || "world",
4263
- confinementBoxHalfSize: s.confinementBoxHalfSize || [2, 2, 2],
4264
- confinementSphereRadius: s.confinementSphereRadius ?? 3,
4265
- confinementRestitution: s.confinementRestitution ?? 0.8,
4266
- confinementFriction: s.confinementFriction ?? 0.1,
4267
- softBoundaryEnabled: s.softBoundaryEnabled || !1,
4268
- softBoundaryStrength: s.softBoundaryStrength ?? 5,
4269
- softBoundaryFalloff: s.softBoundaryFalloff ?? 0.5,
4270
- followSystemId: s.followSystemId || null,
4271
- hidden: s.hidden || !1,
4272
- emissionTrailEnabled: s.emissionTrailEnabled || !1,
4273
- emissionTrailDuration: s.emissionTrailDuration ?? 1,
4274
- emissionTrailWidth: s.emissionTrailWidth ?? 0.5,
4275
- emissionTrailMinDistance: s.emissionTrailMinDistance ?? 0.05,
4276
- emissionTrailMaxPoints: s.emissionTrailMaxPoints ?? 100,
4277
- emissionTrailSegments: s.emissionTrailSegments ?? 8,
4278
- emissionTrailShape: s.emissionTrailShape ?? "straight",
4279
- emissionTrailShapeAmplitude: s.emissionTrailShapeAmplitude ?? 0.1,
4280
- emissionTrailShapeFrequency: s.emissionTrailShapeFrequency ?? 4,
4281
- emissionTrailShapeSpeed: s.emissionTrailShapeSpeed ?? 0,
4282
- shapeDisplay: s.shapeDisplay ?? !0,
4283
- followSystemTranslation: s.followSystemTranslation ?? !0,
4284
- textureImageData: s.textureEnabled && !s.glbModelEnabled && s.textureImageData ? s.textureImageData : void 0,
4285
- glbModelData: s.glbModelEnabled && l.glbRawArrayBuffer ? pe(l.glbRawArrayBuffer) : void 0
4946
+ systems: r.particleSystems.map(({ config: u, system: f }) => ({
4947
+ ...Ys(u),
4948
+ // single source of truth for config fields
4949
+ // Binary assets embedded so replaceSystems() can restore them
4950
+ textureImageData: u.textureEnabled && !u.glbModelEnabled && u.textureImageData ? u.textureImageData : void 0,
4951
+ glbModelData: u.glbModelEnabled && f.glbRawArrayBuffer ? js(f.glbRawArrayBuffer) : void 0
4286
4952
  })),
4287
- activeSystemIndex: c.activeSystemIndex
4288
- }, i = JSON.stringify(e, null, 2);
4289
- let a;
4953
+ activeSystemIndex: r.activeSystemIndex,
4954
+ loop: r.loop || !1
4955
+ // group-level auto-restart
4956
+ }, s = e === "json" ? "json" : "hzfx";
4957
+ let n;
4958
+ if (s === "hzfx") {
4959
+ const u = await ks(i, { textureFormat: "webp" });
4960
+ n = new Blob([u], { type: "application/octet-stream" });
4961
+ } else
4962
+ n = new Blob([JSON.stringify(i, null, 2)], { type: "application/json" });
4963
+ let o;
4290
4964
  if (t)
4291
- a = `${t}.json`;
4965
+ o = t;
4292
4966
  else {
4293
- const s = /* @__PURE__ */ new Date();
4294
- a = `particle-scene_${`${s.getFullYear()}-${(s.getMonth() + 1).toString().padStart(2, "0")}-${s.getDate().toString().padStart(2, "0")}_${s.getHours().toString().padStart(2, "0")}${s.getMinutes().toString().padStart(2, "0")}`}.json`;
4967
+ const u = /* @__PURE__ */ new Date();
4968
+ o = `particle-scene_${`${u.getFullYear()}-${(u.getMonth() + 1).toString().padStart(2, "0")}-${u.getDate().toString().padStart(2, "0")}_${u.getHours().toString().padStart(2, "0")}${u.getMinutes().toString().padStart(2, "0")}`}`;
4295
4969
  }
4296
- const r = new Blob([i], { type: "application/json" }), n = URL.createObjectURL(r), o = document.createElement("a");
4297
- o.href = n, o.download = a, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(n);
4298
- } catch (e) {
4299
- console.error("Error saving scene:", e), alert("Error saving scene. See console for details.");
4970
+ const a = `${o}.${s}`, c = URL.createObjectURL(n), l = document.createElement("a");
4971
+ l.href = c, l.download = a, document.body.appendChild(l), l.click(), document.body.removeChild(l), URL.revokeObjectURL(c);
4972
+ } catch (i) {
4973
+ console.error("Error saving scene:", i), alert("Error saving scene. See console for details.");
4300
4974
  }
4301
4975
  }
4302
- function Ce(c) {
4976
+ function er(r) {
4303
4977
  return new Promise((t, e) => {
4304
4978
  try {
4305
- const i = c.target.files[0];
4979
+ const i = r.target.files[0];
4306
4980
  if (!i) {
4307
4981
  e(new Error("No file selected"));
4308
4982
  return;
4309
4983
  }
4310
- const a = new FileReader();
4311
- a.onload = (r) => {
4984
+ const s = new FileReader();
4985
+ s.onload = (n) => {
4312
4986
  try {
4313
- const n = JSON.parse(r.target.result);
4314
- if (!n.version)
4315
- throw new Error("Invalid scene file: missing version information");
4316
- if (!Array.isArray(n.systems) || n.systems.length === 0)
4987
+ const o = n.target.result;
4988
+ let a;
4989
+ if (Ti(o) ? a = Ei(o) : a = JSON.parse(new TextDecoder().decode(o)), !Array.isArray(a.systems) || a.systems.length === 0)
4317
4990
  throw new Error("No valid particle systems found in the file");
4318
- const o = [];
4319
- for (const s of n.systems)
4320
- o.push(s);
4321
4991
  t({
4322
- systems: o,
4323
- activeSystemIndex: n.activeSystemIndex || 0
4992
+ systems: a.systems.slice(),
4993
+ activeSystemIndex: a.activeSystemIndex || 0
4324
4994
  });
4325
- } catch (n) {
4326
- console.error("Error loading scene:", n), alert("Error loading scene: " + n.message), e(n);
4995
+ } catch (o) {
4996
+ console.error("Error loading scene:", o), alert("Error loading scene: " + o.message), e(o);
4327
4997
  }
4328
- c.target.value = "";
4329
- }, a.onerror = () => {
4330
- alert("Failed to read the file"), e(new Error("Failed to read the file")), c.target.value = "";
4331
- }, a.readAsText(i);
4998
+ r.target.value = "";
4999
+ }, s.onerror = () => {
5000
+ alert("Failed to read the file"), e(new Error("Failed to read the file")), r.target.value = "";
5001
+ }, s.readAsArrayBuffer(i);
4332
5002
  } catch (i) {
4333
5003
  console.error("Error in loadScene:", i), e(i);
4334
5004
  }
4335
5005
  });
4336
5006
  }
4337
- async function Ae(c) {
4338
- if (!c || typeof c != "string")
5007
+ async function tr(r) {
5008
+ if (!r || typeof r != "string")
4339
5009
  throw new Error("[fetchPreset] url must be a non-empty string");
4340
- const t = await fetch(c);
5010
+ const t = await fetch(r);
4341
5011
  if (!t.ok)
4342
5012
  throw new Error(`[fetchPreset] HTTP ${t.status}: ${t.statusText}`);
4343
- const e = await t.json();
4344
- if (!Array.isArray(e.systems) || e.systems.length === 0)
5013
+ const e = await t.arrayBuffer();
5014
+ let i;
5015
+ if (Ti(e) ? i = Ei(e) : i = JSON.parse(new TextDecoder().decode(e)), !Array.isArray(i.systems) || i.systems.length === 0)
4345
5016
  throw new Error('[fetchPreset] Invalid preset: "systems" must be a non-empty array');
4346
5017
  return {
4347
- version: e.version,
4348
- systems: e.systems,
4349
- activeSystemIndex: e.activeSystemIndex ?? 0
5018
+ version: i.version,
5019
+ systems: i.systems,
5020
+ activeSystemIndex: i.activeSystemIndex ?? 0
5021
+ };
5022
+ }
5023
+ const qs = (r) => `
5024
+ @vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
5025
+ var p = array<vec2f, 3>(vec2f(-1.0, -3.0), vec2f(-1.0, 1.0), vec2f(3.0, 1.0));
5026
+ return vec4f(p[i], 0.0, 1.0);
5027
+ }
5028
+ @group(0) @binding(0) var src: ${r ? "texture_depth_multisampled_2d" : "texture_depth_2d"};
5029
+ @fragment fn fs(@builtin(position) pos: vec4f) -> @builtin(frag_depth) f32 {
5030
+ return textureLoad(src, vec2i(pos.xy), 0);
5031
+ }
5032
+ `;
5033
+ async function ir(r, t = {}) {
5034
+ const { getSceneDepth: e = null, autoRespawn: i = !0, respectEffectLoop: s = !0 } = t;
5035
+ let n, o, a;
5036
+ const c = !!(r && r.device && r.context);
5037
+ c ? ({ device: n, context: o, canvas: a } = r, a || (a = o.canvas)) : (a = r, { device: n, context: o } = await Cs(a));
5038
+ const l = navigator.gpu.getPreferredCanvasFormat(), u = t.manager || new Es(n), f = { layouts: {}, pipelines: {} };
5039
+ function h(d) {
5040
+ const p = d ? "ms" : "ss";
5041
+ if (!f.pipelines[p]) {
5042
+ const b = n.createShaderModule({ code: qs(d) }), y = n.createBindGroupLayout({
5043
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "depth", multisampled: d } }]
5044
+ });
5045
+ f.layouts[p] = y, f.pipelines[p] = n.createRenderPipeline({
5046
+ layout: n.createPipelineLayout({ bindGroupLayouts: [y] }),
5047
+ vertex: { module: b, entryPoint: "vs" },
5048
+ fragment: { module: b, entryPoint: "fs", targets: [] },
5049
+ primitive: { topology: "triangle-list" },
5050
+ depthStencil: { format: "depth24plus", depthWriteEnabled: !0, depthCompare: "always" }
5051
+ });
5052
+ }
5053
+ return { pipeline: f.pipelines[p], layout: f.layouts[p] };
5054
+ }
5055
+ const m = {
5056
+ bloomSourceTextures: {},
5057
+ bloomCompositeTextures: {},
5058
+ combinedTexture: null,
5059
+ getBloomSourceTexture(d, p, b) {
5060
+ return this.bloomSourceTextures[d] || (this.bloomSourceTextures[d] = n.createTexture({
5061
+ size: [p, b],
5062
+ format: "rgba16float",
5063
+ // HDR chain (see webgpu.js HDR_FORMAT) — avoids additive clip
5064
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
5065
+ })), this.bloomSourceTextures[d];
5066
+ },
5067
+ getBloomCompositeTexture(d, p, b) {
5068
+ return this.bloomCompositeTextures[d] || (this.bloomCompositeTextures[d] = n.createTexture({
5069
+ size: [p, b],
5070
+ format: "rgba16float",
5071
+ // HDR chain
5072
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
5073
+ })), this.bloomCompositeTextures[d];
5074
+ },
5075
+ getCombinedTexture(d, p) {
5076
+ return this.combinedTexture || (this.combinedTexture = n.createTexture({
5077
+ size: [d, p],
5078
+ format: "rgba16float",
5079
+ // HDR chain — tonemapped to canvas in the final pass
5080
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
5081
+ })), this.combinedTexture;
5082
+ },
5083
+ resizeTextures() {
5084
+ Object.values(this.bloomSourceTextures).forEach((d) => d == null ? void 0 : d.destroy()), Object.values(this.bloomCompositeTextures).forEach((d) => d == null ? void 0 : d.destroy()), this.combinedTexture && this.combinedTexture.destroy(), this.bloomSourceTextures = {}, this.bloomCompositeTextures = {}, this.combinedTexture = null;
5085
+ }
5086
+ }, S = {
5087
+ systemBindGroups: {},
5088
+ systemBloomHorizontalBindGroups: {},
5089
+ secondHorizontalBindGroups: {},
5090
+ finalBindGroup: null,
5091
+ textureStates: {},
5092
+ textureRefs: {},
5093
+ clear() {
5094
+ this.systemBindGroups = {}, this.systemBloomHorizontalBindGroups = {}, this.secondHorizontalBindGroups = {}, this.finalBindGroup = null, this.textureStates = {}, this.textureRefs = {};
5095
+ }
5096
+ }, R = n.createBuffer({ size: 96, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), D = n.createBuffer({ size: 208, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), C = n.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), B = n.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), A = n.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }), P = Ge(n, new Uint16Array([0, 1, 2, 0, 2, 3]), GPUBufferUsage.INDEX), _ = {}, T = () => Ge(n, new Float32Array([-0.5, -0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0, -0.5, 0.5, 0]), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST);
5097
+ u.onSystemCreated = (d) => {
5098
+ _[d] || (_[d] = T());
5099
+ };
5100
+ const L = 4e4, N = new Float32Array(L * 8), k = new Float32Array(L * 4), X = new Float32Array(L * 4), z = n.createBuffer({ size: L * 8 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), me = n.createBuffer({ size: L * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), De = n.createBuffer({ size: L * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }), ze = /* @__PURE__ */ new Map(), at = 8, Q = [];
5101
+ function _t(d) {
5102
+ for (const p of Q) if (p.ids.has(d)) return p;
5103
+ return null;
5104
+ }
5105
+ function Ci(d, p) {
5106
+ if (!d.pos) return;
5107
+ d.hist.push({ t: p, x: d.pos[0], y: d.pos[1], z: d.pos[2] });
5108
+ const b = p - at;
5109
+ for (; d.hist.length > 2 && d.hist[0].t < b; ) d.hist.shift();
5110
+ }
5111
+ function wt(d, p) {
5112
+ const b = d.hist;
5113
+ if (b.length === 0) return d.pos;
5114
+ if (p >= b[b.length - 1].t) {
5115
+ const y = b[b.length - 1];
5116
+ return [y.x, y.y, y.z];
5117
+ }
5118
+ if (p <= b[0].t) return [b[0].x, b[0].y, b[0].z];
5119
+ for (let y = b.length - 1; y > 0; y--)
5120
+ if (b[y - 1].t <= p) {
5121
+ const x = b[y - 1], Y = b[y], Z = (p - x.t) / Math.max(1e-6, Y.t - x.t);
5122
+ return [x.x + (Y.x - x.x) * Z, x.y + (Y.y - x.y) * Z, x.z + (Y.z - x.z) * Z];
5123
+ }
5124
+ return [b[0].x, b[0].y, b[0].z];
5125
+ }
5126
+ const Ai = 0.41421356;
5127
+ function Ui() {
5128
+ ze.clear();
5129
+ let d = 0, p = 0;
5130
+ U.position[0], U.position[1], U.position[2];
5131
+ for (const { system: b, config: y } of u.particleSystems) {
5132
+ if (!y.emissionTrailEnabled || y.hidden || y.glbModelEnabled) continue;
5133
+ b.readbackAndProcessParticles();
5134
+ const x = b.particleData, Y = b.particleVelocities, Z = b.activeParticles;
5135
+ if (!x || !Y || Z <= 0) continue;
5136
+ const $ = y.emissionTrailMode === "particles", W = d, g = y.emissionTrailDuration ?? 1, w = y.opacity ?? 1, G = y.particleSize ?? 0.5, q = y.bloomIntensity || 1, M = Math.max(1, Math.min(64, y.emissionTrailSegments ?? 8)), J = y.emissionTrailShape || "straight", ee = y.followSystemTranslation ?? !0, fe = b._simPosition, O = ee && fe ? fe[0] : 0, Qe = ee && fe ? fe[1] : 0, Vt = ee && fe ? fe[2] : 0, Ae = b._simVelocity, Ft = Ae ? Ae[0] : 0, Ki = Ae ? Ae[1] : 0, Ot = Ae ? Ae[2] : 0, Fe = _t(y.id), Lt = !!(ee && Fe && Fe.hist && Fe.hist.length > 1);
5137
+ for (let et = 0; et < Z; et++) {
5138
+ const ge = et * 8, tt = x[ge], ft = x[ge + 1], it = x[ge + 2], Qi = tt + O, es = ft + Qe, ts = it + Vt;
5139
+ let Oe = x[ge + 3], Le = x[ge + 4], Ne = x[ge + 5];
5140
+ const Xe = x[ge + 6], Ue = x[ge + 7];
5141
+ if (Xe >= Ue || Ue <= 0) continue;
5142
+ const be = Xe / Ue;
5143
+ if (y.colorTransitionEnabled) {
5144
+ const v = y.startColor ?? [1, 0, 0], I = y.endColor ?? [0, 0, 1];
5145
+ Oe = v[0] + (I[0] - v[0]) * be, Le = v[1] + (I[1] - v[1]) * be, Ne = v[2] + (I[2] - v[2]) * be;
5146
+ }
5147
+ Oe = Math.min(1, Oe * q), Le = Math.min(1, Le * q), Ne = Math.min(1, Ne * q);
5148
+ let ke = G;
5149
+ if (y.randomSize) {
5150
+ const v = Math.sin(Ue * 54321.67) * 43758.5453 % 1, I = v < 0 ? v + 1 : v;
5151
+ ke = (y.minSize ?? 0.1) + ((y.maxSize ?? 0.5) - (y.minSize ?? 0.1)) * I;
5152
+ }
5153
+ if (y.fadeSizeEnabled) {
5154
+ const v = Math.max(0.01, Math.min(10, y.sizeLifetimeSpeed ?? 1));
5155
+ ke *= 1 - Math.pow(be, 1 / v);
5156
+ }
5157
+ if (y.increaseSizeEnabled) {
5158
+ const v = Math.max(0.01, Math.min(10, y.sizeLifetimeSpeed ?? 1));
5159
+ ke *= 1 + Math.pow(be, 1 / v);
5160
+ }
5161
+ if (ke <= 0 || be > 0.9) continue;
5162
+ const Nt = Math.min((0.9 - be) * (1 / 0.2), 1), Xt = 0.75 * ke * Ai * Nt;
5163
+ let je = w;
5164
+ if (y.fadeEnabled && (je *= Math.max(0, 1 - be)), je *= Nt, je < 0.01) continue;
5165
+ const pt = et * 4, kt = Y[pt], jt = Y[pt + 1], Yt = Y[pt + 2], st = kt + Ft, rt = jt + Ki, nt = Yt + Ot, qt = Math.sqrt(st * st + rt * rt + nt * nt);
5166
+ if (qt < 1e-3) continue;
5167
+ const ht = 1 / qt, _e = st * ht, we = rt * ht, Se = nt * ht, Ht = U.right[0], Zt = U.right[1], $t = U.right[2];
5168
+ let mt = Ht * _e + Zt * we + $t * Se, ne = Ht - mt * _e, ae = Zt - mt * we, oe = $t - mt * Se, Ye = Math.sqrt(ne * ne + ae * ae + oe * oe);
5169
+ if (Ye < 0.2) {
5170
+ const v = U.up[0], I = U.up[1], H = U.up[2], V = v * _e + I * we + H * Se;
5171
+ ne = v - V * _e, ae = I - V * we, oe = H - V * Se, Ye = Math.sqrt(ne * ne + ae * ae + oe * oe) || 1;
5172
+ }
5173
+ ne /= Ye, ae /= Ye, oe /= Ye;
5174
+ const qe = Math.min(g, Xe);
5175
+ if (qe < 1e-3) continue;
5176
+ const Wt = y.gravityEnabled && y.gravityStrength || 0, Be = new Array(M + 1), Re = new Array(M + 1), Me = new Array(M + 1);
5177
+ if (y.orientToDirection && y.burstMode && Lt) {
5178
+ const v = b._emitSimRotY || 0, I = new Array(M + 1), H = new Array(M + 1), V = new Array(M + 1);
5179
+ for (let E = 0; E <= M; E++) {
5180
+ const F = wt(Fe, ye - E / M * qe);
5181
+ I[E] = F[0], H[E] = F[1], V[E] = F[2];
5182
+ }
5183
+ for (let E = 0; E <= M; E++) {
5184
+ const F = E > 0 ? E - 1 : 0, j = E < M ? E + 1 : M;
5185
+ let Te = I[F] - I[j], Ee = V[F] - V[j];
5186
+ const xe = (Math.hypot(Te, Ee) > 1e-5 ? Math.atan2(Te, Ee) : Math.atan2(Ft, Ot)) - v, se = Math.cos(xe), re = Math.sin(xe), he = E / M * qe, yt = -0.5 * Wt * he * he;
5187
+ Be[E] = se * tt + re * it + I[E], Re[E] = ft + yt + H[E], Me[E] = -re * tt + se * it + V[E];
5188
+ }
5189
+ } else for (let v = 0; v <= M; v++) {
5190
+ const I = v / M * qe, H = -0.5 * Wt * I * I;
5191
+ if (Lt) {
5192
+ const V = wt(Fe, ye - I);
5193
+ Be[v] = tt - kt * I + V[0], Re[v] = ft - jt * I + H + V[1], Me[v] = it - Yt * I + V[2];
5194
+ } else
5195
+ Be[v] = Qi - st * I, Re[v] = es - rt * I + H, Me[v] = ts - nt * I;
5196
+ }
5197
+ if (J !== "straight") {
5198
+ const v = y.emissionTrailShapeAmplitude ?? 0.1, I = y.emissionTrailShapeFrequency ?? 4, H = y.emissionTrailShapeSpeed ?? 0;
5199
+ let V = -Se, E = 0, F = _e, j = Math.sqrt(V * V + F * F);
5200
+ j < 1e-6 && (V = 0, E = Se, F = -we, j = Math.sqrt(V * V + E * E + F * F) || 1), V /= j, E /= j, F /= j;
5201
+ const Te = we * F - Se * E, Ee = Se * V - _e * F, pe = _e * E - we * V;
5202
+ for (let K = 1; K <= M; K++) {
5203
+ const xe = K / M * qe, se = 2 * Math.PI * I * (ye - xe) + H * ye;
5204
+ let re = 0, he = 0;
5205
+ J === "zigzag" ? re = v * Math.sign(Math.sin(se)) : J === "sine" ? re = v * Math.sin(se) : J === "spiral" && (re = v * Math.sin(se), he = v * Math.cos(se)), Be[K] += V * re + Te * he, Re[K] += E * re + Ee * he, Me[K] += F * re + pe * he;
5206
+ }
5207
+ }
5208
+ if ($)
5209
+ for (let v = 1; v <= M && d < L; v++) {
5210
+ const I = v / M, H = Be[v] - O, V = Re[v] - Qe, E = Me[v] - Vt, F = d * 8, j = d * 4;
5211
+ N[F] = H, N[F + 1] = V, N[F + 2] = E, N[F + 3] = Oe, N[F + 4] = Le, N[F + 5] = Ne, N[F + 6] = Xe + (Ue - Xe) * I, N[F + 7] = Ue, k[j] = 0, k[j + 1] = 0, k[j + 2] = 0, k[j + 3] = 0, X[j] = H, X[j + 1] = V, X[j + 2] = E, X[j + 3] = 0, d++;
5212
+ }
5213
+ else
5214
+ for (let v = 0; v < M && !(p + 42 > ue.length); v++) {
5215
+ const I = v / M, H = (v + 1) / M, V = Be[v], E = Re[v], F = Me[v], j = Be[v + 1], Te = Re[v + 1], Ee = Me[v + 1], pe = Xt * (1 - I), K = Xt * (1 - H), xe = je * (1 - I) * (1 - I), se = je * (1 - H) * (1 - H), re = V + ne * pe, he = E + ae * pe, yt = F + oe * pe, Jt = V - ne * pe, Kt = E - ae * pe, Qt = F - oe * pe, ei = j + ne * K, ti = Te + ae * K, ii = Ee + oe * K, is = j - ne * K, ss = Te - ae * K, rs = Ee - oe * K, Ie = (ns, as, os, ls) => {
5216
+ ue[p++] = ns, ue[p++] = as, ue[p++] = os, ue[p++] = Oe, ue[p++] = Le, ue[p++] = Ne, ue[p++] = ls;
5217
+ };
5218
+ Ie(re, he, yt, xe), Ie(Jt, Kt, Qt, xe), Ie(ei, ti, ii, se), Ie(Jt, Kt, Qt, xe), Ie(is, ss, rs, se), Ie(ei, ti, ii, se);
5219
+ }
5220
+ }
5221
+ $ && d > W && ze.set(y.id, { first: W, count: d - W });
5222
+ }
5223
+ d > 0 && (n.queue.writeBuffer(z, 0, N, 0, d * 8), n.queue.writeBuffer(me, 0, k, 0, d * 4), n.queue.writeBuffer(De, 0, X, 0, d * 4)), Ve = p / 7, Ve > 0 && n.queue.writeBuffer(At, 0, ue, 0, p);
5224
+ }
5225
+ const Bt = () => {
5226
+ n.queue.writeBuffer(C, 0, new Float32Array([1, 0, a.width, a.height, 0, 0, 0, 0])), n.queue.writeBuffer(B, 0, new Float32Array([0, 1, a.width, a.height, 0, 0, 0, 0]));
5227
+ };
5228
+ Bt();
5229
+ const Rt = new Float32Array(16).fill(0);
5230
+ Rt[0] = 1, n.queue.writeBuffer(A, 0, Rt);
5231
+ const te = Vs(n), ce = Ds(n), {
5232
+ particlePipeline: Ii,
5233
+ particleAdditivePipeline: Gi,
5234
+ particleDepthWritePipeline: Di,
5235
+ blurPipeline: $e,
5236
+ compositePipeline: zi,
5237
+ directRenderPipeline: Mt,
5238
+ finalCompositePipeline: Vi,
5239
+ glbMeshPipeline: Fi
5240
+ } = zs(n, l, ce), Tt = n.createShaderModule({ code: `
5241
+ struct U { mvp: mat4x4<f32> };
5242
+ @group(0) @binding(0) var<uniform> u: U;
5243
+ struct VIn { @location(0) pos: vec3<f32>, @location(1) col: vec4<f32> };
5244
+ struct VOut { @builtin(position) pos: vec4<f32>, @location(0) col: vec4<f32> };
5245
+ @vertex fn vs(v: VIn) -> VOut { var o: VOut; o.pos = u.mvp * vec4<f32>(v.pos, 1.0); o.col = v.col; return o; }
5246
+ @fragment fn fs(i: VOut) -> @location(0) vec4<f32> { return i.col; }
5247
+ ` }), Et = n.createBindGroupLayout({
5248
+ entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } }]
5249
+ }), Oi = n.createRenderPipeline({
5250
+ layout: n.createPipelineLayout({ bindGroupLayouts: [Et] }),
5251
+ vertex: {
5252
+ module: Tt,
5253
+ entryPoint: "vs",
5254
+ buffers: [{ arrayStride: 28, attributes: [
5255
+ { shaderLocation: 0, offset: 0, format: "float32x3" },
5256
+ { shaderLocation: 1, offset: 12, format: "float32x4" }
5257
+ ] }]
5258
+ },
5259
+ fragment: {
5260
+ module: Tt,
5261
+ entryPoint: "fs",
5262
+ targets: [{ format: "rgba16float", blend: {
5263
+ // renders into the HDR sceneTexture
5264
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
5265
+ alpha: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" }
5266
+ } }]
5267
+ },
5268
+ primitive: { topology: "triangle-list" },
5269
+ // depth24plus to match the non-bloom pass; test against the resolved scene depth
5270
+ // (occlusion) but don't write (transparent ribbon).
5271
+ depthStencil: { format: "depth24plus", depthWriteEnabled: !1, depthCompare: "less-equal" }
5272
+ }), Ct = 512 * 64 * 6, ue = new Float32Array(Ct * 7), At = n.createBuffer({
5273
+ size: Ct * 7 * 4,
5274
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
5275
+ label: "ribbonBuffer"
5276
+ }), Li = n.createBindGroup({
5277
+ layout: Et,
5278
+ entries: [{ binding: 0, resource: { buffer: R } }]
5279
+ });
5280
+ let Ve = 0, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de } = ui(n, l, a.width, a.height), Pe = di(n, a.width, a.height);
5281
+ const ot = { uniformBuffer: R, appearanceUniformBuffer: D, horizontalBlurUniformBuffer: C, verticalBlurUniformBuffer: B, bloomIntensityBuffer: A };
5282
+ let We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de });
5283
+ const U = {
5284
+ mvp: new Float32Array(16),
5285
+ position: new Float32Array([0, 0, 10]),
5286
+ right: new Float32Array([1, 0, 0]),
5287
+ // camera basis (world space) — for stable ribbon width
5288
+ up: new Float32Array([0, 1, 0]),
5289
+ hasCamera: !1
5290
+ };
5291
+ let ye = 0, Ni = 0;
5292
+ const Ce = { key: null, ms: !1, bindGroup: null };
5293
+ let Ut = !1, lt = !0, Je = !1, Ke = null, ct = a.width, ut = a.height;
5294
+ function It() {
5295
+ const d = [ie, ve, de, Pe], p = ui(n, l, a.width, a.height);
5296
+ ie = p.sceneTexture, ve = p.bloomTexA, de = p.bloomTexB, Pe = di(n, a.width, a.height), Bt(), S.clear(), m.resizeTextures(), We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de });
5297
+ let b = !1;
5298
+ const y = () => {
5299
+ if (!b) {
5300
+ b = !0, requestAnimationFrame(y);
5301
+ return;
5302
+ }
5303
+ d.forEach((x) => x.destroy());
5304
+ };
5305
+ requestAnimationFrame(y);
5306
+ }
5307
+ function Xi(d, p, b) {
5308
+ U.mvp.set(Ns(d, p)), p && p.length >= 10 && (U.right[0] = p[0], U.right[1] = p[4], U.right[2] = p[8], U.up[0] = p[1], U.up[1] = p[5], U.up[2] = p[9]), b && (U.position[0] = b.x ?? b[0], U.position[1] = b.y ?? b[1], U.position[2] = b.z ?? b[2]), U.hasCamera = !0;
5309
+ }
5310
+ function ki(d, p) {
5311
+ U.mvp.set(d), p && (U.position[0] = p.x ?? p[0], U.position[1] = p.y ?? p[1], U.position[2] = p.z ?? p[2]), U.hasCamera = !0;
5312
+ }
5313
+ async function dt(d) {
5314
+ if (Je) {
5315
+ Ke = d;
5316
+ return;
5317
+ }
5318
+ Je = !0;
5319
+ try {
5320
+ for (const p in _) delete _[p];
5321
+ S.clear(), m.resizeTextures(), We = St(n, te, ot, { sceneTexture: ie, bloomTexA: ve, bloomTexB: de }), await u.replaceSystems({ systems: [], activeSystemIndex: 0 });
5322
+ for (const p of d)
5323
+ await u.addSystems(p.preset, p.position || [0, 0, 0]);
5324
+ for (const { config: p } of u.particleSystems)
5325
+ _[p.id] || (_[p.id] = T());
5326
+ lt = !0, u.respawnAllSystems();
5327
+ } finally {
5328
+ if (Je = !1, Ke) {
5329
+ const p = Ke;
5330
+ Ke = null, dt(p);
5331
+ }
5332
+ }
5333
+ }
5334
+ async function ji(d, p = [0, 0, 0]) {
5335
+ return dt([{ preset: d, position: p }]);
5336
+ }
5337
+ function Yi(d) {
5338
+ if (Ut || Je || !u.ready || (d > 0.1 && (d = 0.1), d <= 0) || u.particleSystems.length === 0) return;
5339
+ if ((a.width !== ct || a.height !== ut) && (ct = a.width, ut = a.height, It()), ye += d, Q.length) {
5340
+ for (const g of Q) {
5341
+ if (g.getPosition) {
5342
+ const w = g.getPosition();
5343
+ g.pos = w ? Array.isArray(w) ? [w[0], w[1], w[2]] : [w.x, w.y, w.z] : null;
5344
+ }
5345
+ g.vel = g.pos && g.prevPos && g.wasActive && d > 0 ? [(g.pos[0] - g.prevPos[0]) / d, (g.pos[1] - g.prevPos[1]) / d, (g.pos[2] - g.prevPos[2]) / d] : [0, 0, 0], g.justResumed = !!g.pos && !g.wasActive, g.justResumed && (g.hist.length = 0);
5346
+ }
5347
+ for (const { system: g, config: w } of u.particleSystems) {
5348
+ const G = _t(w.id);
5349
+ if (!(!G || G.historyOnly) && (w.hidden = !G.pos, G.pos)) {
5350
+ let q = null;
5351
+ if (G.orientToDirection && G.vel) {
5352
+ const M = G.vel[0], J = G.vel[2];
5353
+ Math.hypot(M, J) > 1e-4 && (q = [0, 0, Math.atan2(M, J)]);
5354
+ }
5355
+ g.setSimulationTransform({ position: G.pos, velocity: G.vel, rotation: q }), g.updateAppearanceUniform(), (G.justResumed || g.activeParticles === 0) && g.spawnParticles();
5356
+ }
5357
+ }
5358
+ for (const g of Q)
5359
+ g.pos ? Ci(g, ye) : g.hist.length = 0, g.prevPos = g.pos ? g.pos.slice() : null, g.wasActive = !!g.pos;
5360
+ if (globalThis.__HZFX_DEBUG && (Ni++ & 63) === 0) {
5361
+ const g = u.particleSystems.reduce((M, J) => M + (J.system.activeParticles | 0), 0), w = Q.find((M) => M.pos), G = w ? Math.hypot(U.position[0] - w.pos[0], U.position[1] - w.pos[1], U.position[2] - w.pos[2]).toFixed(1) : "-", q = Q.map((M) => `{ids:[${[...M.ids]}],pos:${M.pos ? "1" : "0"},hist:${M.hist.length}}`).join(",");
5362
+ console.info(`[HZFX] movingGroups(${Q.length})=[${q}] activeParticles=${g} systems=${u.particleSystems.length} ribbonVerts=${Ve} camDist=${G} t=${ye.toFixed(1)}`);
5363
+ }
5364
+ }
5365
+ if (u.updateAllSystems(d), s ? u.loop ?? i : i) {
5366
+ const g = u.particleSystems.length > 0 && u.particleSystems.every(({ system: w }) => w.activeParticles === 0 && !w.emitting);
5367
+ g && lt && u.respawnAllSystems(), lt = !g;
5368
+ }
5369
+ for (const { system: g, config: w } of u.particleSystems)
5370
+ w.glbModelEnabled && g.glbAnimator && (g.glbAnimator.update(d), g.updateAnimatedGLBBuffer());
5371
+ n.queue.writeBuffer(R, 0, U.mvp), n.queue.writeBuffer(R, 64, new Float32Array([
5372
+ U.position[0],
5373
+ U.position[1],
5374
+ U.position[2],
5375
+ a.height / Math.max(1, a.width),
5376
+ ye
5377
+ ])), Ui();
5378
+ const b = u.particleSystems.some(({ config: g }) => g.bloomEnabled), y = n.createCommandEncoder();
5379
+ let x = !1;
5380
+ if (e)
5381
+ try {
5382
+ const g = e();
5383
+ if (g) {
5384
+ let w = null, G = null, q = !1;
5385
+ if (g instanceof GPUTexture ? g.width === a.width && g.height === a.height && (w = g, G = () => g.createView({ aspect: "depth-only" }), q = g.sampleCount > 1) : g.view && (w = g.view, G = () => g.view, q = !!g.multisampled), w) {
5386
+ const { pipeline: M, layout: J } = h(q);
5387
+ (Ce.key !== w || Ce.ms !== q) && (Ce.key = w, Ce.ms = q, Ce.bindGroup = n.createBindGroup({
5388
+ layout: J,
5389
+ entries: [{ binding: 0, resource: G() }]
5390
+ }));
5391
+ const ee = y.beginRenderPass({
5392
+ colorAttachments: [],
5393
+ depthStencilAttachment: { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "clear", depthStoreOp: "store" }
5394
+ });
5395
+ ee.setPipeline(M), ee.setBindGroup(0, Ce.bindGroup), ee.draw(3), ee.end(), x = !0;
5396
+ }
5397
+ }
5398
+ } catch {
5399
+ }
5400
+ const Y = y.beginRenderPass({
5401
+ colorAttachments: [{ view: ie.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],
5402
+ depthStencilAttachment: x ? { view: Pe.createView(), depthLoadOp: "load", depthStoreOp: "store" } : { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "clear", depthStoreOp: "store" }
5403
+ });
5404
+ for (const { system: g, config: w } of u.particleSystems)
5405
+ w.bloomEnabled || w.hidden || g.activeParticles === 0 || Gt(Y, g, w, !0);
5406
+ if (Ve > 0 && (Y.setPipeline(Oi), Y.setBindGroup(0, Li), Y.setVertexBuffer(0, At), Y.draw(Ve)), Y.end(), b)
5407
+ for (const { system: g, config: w } of u.particleSystems) {
5408
+ if (!w.bloomEnabled || w.hidden || g.activeParticles === 0) continue;
5409
+ const G = g.config.id, q = m.getBloomSourceTexture(G, a.width, a.height), M = y.beginRenderPass({
5410
+ colorAttachments: [{ view: q.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],
5411
+ depthStencilAttachment: { view: Pe.createView(), depthClearValue: 1, depthLoadOp: "load", depthStoreOp: "store" }
5412
+ });
5413
+ Gt(M, g, w, !1), M.end();
5414
+ const J = new Float32Array(16).fill(0);
5415
+ J[0] = w.bloomIntensity, n.queue.writeBuffer(A, 0, J);
5416
+ const ee = {
5417
+ colorAttachments: [{ view: ve.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
5418
+ }, fe = {
5419
+ colorAttachments: [{ view: de.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
5420
+ };
5421
+ S.systemBloomHorizontalBindGroups[G] || (S.systemBloomHorizontalBindGroups[G] = n.createBindGroup({
5422
+ layout: ce.bloomBindGroupLayout,
5423
+ entries: [
5424
+ { binding: 0, resource: te },
5425
+ { binding: 1, resource: q.createView() },
5426
+ { binding: 2, resource: { buffer: C } }
5427
+ ]
5428
+ }));
5429
+ let O = y.beginRenderPass(ee);
5430
+ O.setPipeline($e), O.setBindGroup(0, S.systemBloomHorizontalBindGroups[G]), O.draw(3), O.end(), O = y.beginRenderPass(fe), O.setPipeline($e), O.setBindGroup(0, We.verticalBlurBindGroup), O.draw(3), O.end(), S.secondHorizontalBindGroups[G] || (S.secondHorizontalBindGroups[G] = n.createBindGroup({
5431
+ layout: ce.bloomBindGroupLayout,
5432
+ entries: [
5433
+ { binding: 0, resource: te },
5434
+ { binding: 1, resource: de.createView() },
5435
+ { binding: 2, resource: { buffer: C } }
5436
+ ]
5437
+ })), O = y.beginRenderPass(ee), O.setPipeline($e), O.setBindGroup(0, S.secondHorizontalBindGroups[G]), O.draw(3), O.end(), O = y.beginRenderPass(fe), O.setPipeline($e), O.setBindGroup(0, We.verticalBlurBindGroup), O.draw(3), O.end();
5438
+ const Qe = m.getBloomCompositeTexture(G, a.width, a.height);
5439
+ O = y.beginRenderPass({
5440
+ colorAttachments: [{ view: Qe.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
5441
+ }), O.setPipeline(zi), O.setBindGroup(0, n.createBindGroup({
5442
+ layout: ce.compositeBindGroupLayout,
5443
+ entries: [
5444
+ { binding: 0, resource: te },
5445
+ { binding: 1, resource: q.createView() },
5446
+ { binding: 2, resource: de.createView() },
5447
+ { binding: 3, resource: { buffer: g.bloomIntensityBuffer } }
5448
+ ]
5449
+ })), O.draw(3), O.end();
5450
+ }
5451
+ const Z = m.getCombinedTexture(a.width, a.height), $ = y.beginRenderPass({
5452
+ colorAttachments: [{ view: Z.createView(), loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
5453
+ });
5454
+ $.setPipeline(Mt), $.setBindGroup(0, n.createBindGroup({
5455
+ layout: ce.compositeBindGroupLayout,
5456
+ entries: [
5457
+ { binding: 0, resource: te },
5458
+ { binding: 1, resource: ie.createView() },
5459
+ { binding: 2, resource: ie.createView() },
5460
+ { binding: 3, resource: { buffer: A } }
5461
+ ]
5462
+ })), $.draw(3);
5463
+ for (const { config: g, system: w } of u.particleSystems) {
5464
+ if (!g.bloomEnabled || g.hidden || w.activeParticles === 0) continue;
5465
+ const G = w.config.id;
5466
+ $.setPipeline(Mt), $.setBindGroup(0, n.createBindGroup({
5467
+ layout: ce.compositeBindGroupLayout,
5468
+ entries: [
5469
+ { binding: 0, resource: te },
5470
+ { binding: 1, resource: m.getBloomCompositeTexture(G, a.width, a.height).createView() },
5471
+ { binding: 2, resource: ie.createView() },
5472
+ { binding: 3, resource: { buffer: A } }
5473
+ ]
5474
+ })), $.draw(3);
5475
+ }
5476
+ $.end();
5477
+ const W = y.beginRenderPass({
5478
+ colorAttachments: [{
5479
+ view: o.getCurrentTexture().createView(),
5480
+ loadOp: c ? "load" : "clear",
5481
+ storeOp: "store",
5482
+ clearValue: { r: 0, g: 0, b: 0, a: 0 }
5483
+ }]
5484
+ });
5485
+ W.setPipeline(Vi), S.finalBindGroup || (S.finalBindGroup = n.createBindGroup({
5486
+ layout: ce.compositeBindGroupLayout,
5487
+ entries: [
5488
+ { binding: 0, resource: te },
5489
+ { binding: 1, resource: Z.createView() },
5490
+ { binding: 2, resource: ie.createView() },
5491
+ { binding: 3, resource: { buffer: A } }
5492
+ ]
5493
+ })), W.setBindGroup(0, S.finalBindGroup), W.draw(3), W.end(), n.queue.submit([y.finish()]);
5494
+ }
5495
+ function Gt(d, p, b, y) {
5496
+ const x = p.config.id, Y = b.glbModelEnabled && p.glbMeshData;
5497
+ let Z;
5498
+ if (y) {
5499
+ const W = !S.systemBindGroups[x] || S.textureStates[x] !== b.textureEnabled || S.textureRefs[x] !== p.particleTexture;
5500
+ S.textureStates[x] = b.textureEnabled, S.textureRefs[x] = p.particleTexture, W && (S.systemBindGroups[x] = n.createBindGroup({
5501
+ layout: ce.particleBindGroupLayout,
5502
+ entries: [
5503
+ { binding: 0, resource: { buffer: R } },
5504
+ { binding: 1, resource: { buffer: p.appearanceUniformBuffer } },
5505
+ { binding: 2, resource: p.particleTexture.createView() },
5506
+ { binding: 3, resource: te }
5507
+ ]
5508
+ })), Z = S.systemBindGroups[x];
5509
+ } else
5510
+ Z = n.createBindGroup({
5511
+ layout: ce.particleBindGroupLayout,
5512
+ entries: [
5513
+ { binding: 0, resource: { buffer: R } },
5514
+ { binding: 1, resource: { buffer: p.appearanceUniformBuffer } },
5515
+ { binding: 2, resource: p.particleTexture.createView() },
5516
+ { binding: 3, resource: te }
5517
+ ]
5518
+ });
5519
+ const $ = b.shapeDisplay !== !1;
5520
+ if (Y)
5521
+ $ && (d.setPipeline(Fi), d.setBindGroup(0, Z), d.setVertexBuffer(0, p.glbVertexBuffer), d.setVertexBuffer(1, p.instanceBuffer), d.setVertexBuffer(2, p.velocityBuffer), d.setIndexBuffer(p.glbIndexBuffer, p.glbIndexFormat), d.drawIndexed(p.glbIndexCount, p.activeParticles));
5522
+ else {
5523
+ d.setPipeline(b.blendMode === "additive" ? Gi : Ii), d.setIndexBuffer(P, "uint16"), _[x] || (_[x] = T()), d.setVertexBuffer(0, _[x]), d.setBindGroup(0, Z), $ && (d.setVertexBuffer(1, p.instanceBuffer), d.setVertexBuffer(2, p.velocityBuffer), d.setVertexBuffer(3, p.trailBuffer), d.drawIndexed(6, p.activeParticles));
5524
+ const W = ze.get(x);
5525
+ W && (d.setVertexBuffer(1, z), d.setVertexBuffer(2, me), d.setVertexBuffer(3, De), d.drawIndexed(6, W.count, 0, 0, W.first)), $ && b.depthWriteEnabled && (d.setPipeline(Di), d.drawIndexed(6, p.activeParticles));
5526
+ }
5527
+ }
5528
+ function qi() {
5529
+ ct = a.width, ut = a.height, It();
5530
+ }
5531
+ function Hi() {
5532
+ S.clear();
5533
+ }
5534
+ function Zi() {
5535
+ Ut = !0, u.destroy(), [ie, ve, de, Pe].forEach((d) => d == null ? void 0 : d.destroy()), m.resizeTextures(), [
5536
+ R,
5537
+ D,
5538
+ C,
5539
+ B,
5540
+ A,
5541
+ P,
5542
+ z,
5543
+ me,
5544
+ De
5545
+ ].forEach((d) => d == null ? void 0 : d.destroy()), Object.values(_).forEach((d) => d == null ? void 0 : d.destroy());
5546
+ }
5547
+ async function Dt(d, p) {
5548
+ const b = await u.addSystems(d, p);
5549
+ for (const { config: y } of u.particleSystems)
5550
+ _[y.id] || (_[y.id] = T());
5551
+ return u.respawnAllSystems(), new Set(Array.isArray(b) ? b : []);
5552
+ }
5553
+ function zt(d) {
5554
+ for (const p of d) {
5555
+ const b = u.particleSystems.findIndex((y) => y.config.id === p);
5556
+ b >= 0 && u.removeSystem(b);
5557
+ }
5558
+ }
5559
+ async function $i(d, p = [0, 0, 0]) {
5560
+ const b = await Dt(d, p);
5561
+ return { remove() {
5562
+ zt(b);
5563
+ } };
5564
+ }
5565
+ async function Wi(d, p = {}) {
5566
+ const b = await Dt(d, [0, 0, 0]);
5567
+ globalThis.__HZFX_DEBUG && console.info(`[HZFX] addMovingEmitter: presetSystems=${(d && d.systems || []).length} newIds=[${[...b]}]`);
5568
+ const y = { ids: b, pos: null, hist: [], getPosition: p.getPosition || null, orientToDirection: !!p.orientToDirection };
5569
+ return Q.push(y), {
5570
+ setPosition(x) {
5571
+ x && (y.pos = Array.isArray(x) ? [x[0], x[1], x[2]] : [x.x, x.y, x.z]);
5572
+ },
5573
+ setOrientToDirection(x) {
5574
+ y.orientToDirection = !!x;
5575
+ },
5576
+ remove() {
5577
+ zt(b);
5578
+ const x = Q.indexOf(y);
5579
+ x >= 0 && Q.splice(x, 1);
5580
+ }
5581
+ };
5582
+ }
5583
+ function Ji(d, p) {
5584
+ const y = { ids: d instanceof Set ? d : new Set(d), pos: null, hist: [], getPosition: p, historyOnly: !0 };
5585
+ return Q.push(y), {
5586
+ remove() {
5587
+ const x = Q.indexOf(y);
5588
+ x >= 0 && Q.splice(x, 1);
5589
+ },
5590
+ // Update which systems this history group covers WITHOUT losing the accumulated path
5591
+ // history. Needed when the scene's systems change (e.g. duplicate/add/remove) while the
5592
+ // group is active — otherwise a newly-added system's id isn't in the set and its trail
5593
+ // can't follow the recorded movement path (it falls back to straight extrapolation).
5594
+ setIds(x) {
5595
+ y.ids = x instanceof Set ? x : new Set(x);
5596
+ }
5597
+ };
5598
+ }
5599
+ return {
5600
+ manager: u,
5601
+ device: n,
5602
+ context: o,
5603
+ setCamera: Xi,
5604
+ setCameraMVP: ki,
5605
+ setEmitters: dt,
5606
+ loadPreset: ji,
5607
+ addEmitter: $i,
5608
+ addMovingEmitter: Wi,
5609
+ render: Yi,
5610
+ resize: qi,
5611
+ clearCaches: Hi,
5612
+ trackHistoryGroup: Ji,
5613
+ destroy: Zi
5614
+ };
5615
+ }
5616
+ function sr(r) {
5617
+ return () => {
5618
+ var t, e, i, s, n, o;
5619
+ try {
5620
+ const a = r.backend;
5621
+ if (!a) return null;
5622
+ if (r.needsFrameBufferTarget && r._frameBufferTarget) {
5623
+ const u = (i = (e = (t = r._textures) == null ? void 0 : t.get) == null ? void 0 : e.call(t, r._frameBufferTarget)) == null ? void 0 : i.depthTexture, f = u ? (s = a.get(u)) == null ? void 0 : s.texture : null;
5624
+ if (f && f.width === r.domElement.width && f.height === r.domElement.height) return f;
5625
+ }
5626
+ const c = r.getCanvasTarget ? a.get(r.getCanvasTarget()) : null, l = ((o = (n = c == null ? void 0 : c.descriptor) == null ? void 0 : n.depthStencilAttachment) == null ? void 0 : o.view) ?? null;
5627
+ return l ? { view: l, multisampled: (r.currentSamples ?? 0) > 1 } : null;
5628
+ } catch {
5629
+ return null;
5630
+ }
4350
5631
  };
4351
5632
  }
4352
5633
  export {
4353
- ne as GLBAnimator,
4354
- Me as Objects3DManager,
4355
- Z as ParticleEmitter,
4356
- q as ParticlePhysics,
4357
- C as ParticleSystem,
4358
- me as ParticleSystemManager,
4359
- $ as ParticleTextureManager,
4360
- N as blurShader,
4361
- X as compositeShader,
4362
- Se as createBindGroupLayouts,
4363
- ve as createBindGroups,
4364
- E as createBuffer,
4365
- de as createCubeGeometry,
4366
- be as createDepthTexture,
4367
- Be as createLookAtMatrix,
4368
- Te as createProjectionMatrix,
4369
- xe as createRenderPipelines,
4370
- ge as createRenderTextures,
4371
- Pe as createSampler,
4372
- fe as createSphereGeometry,
4373
- k as directRenderShader,
4374
- ie as extractGLBTexture,
4375
- Ae as fetchPreset,
4376
- ue as glbMeshParticleShader,
4377
- Re as hexToRgb,
4378
- ye as initWebGPU,
4379
- Ce as loadScene,
4380
- Ee as multiplyMatrices,
4381
- ce as object3dShader,
4382
- O as parseGLB,
4383
- oe as particlePhysicsShader,
4384
- j as particleShader,
4385
- we as rgbToHex,
4386
- _e as saveScene
5634
+ Ts as GLBAnimator,
5635
+ Zs as Objects3DManager,
5636
+ cs as ParticleEmitter,
5637
+ us as ParticlePhysics,
5638
+ si as ParticleScript,
5639
+ bt as ParticleSystem,
5640
+ Es as ParticleSystemManager,
5641
+ ds as ParticleTextureManager,
5642
+ Si as blurShader,
5643
+ xi as compositeShader,
5644
+ Ds as createBindGroupLayouts,
5645
+ St as createBindGroups,
5646
+ Ge as createBuffer,
5647
+ Fs as createCubeGeometry,
5648
+ di as createDepthTexture,
5649
+ Js as createLookAtMatrix,
5650
+ Ks as createProjectionMatrix,
5651
+ zs as createRenderPipelines,
5652
+ ui as createRenderTextures,
5653
+ Vs as createSampler,
5654
+ Os as createSphereGeometry,
5655
+ vi as directRenderShader,
5656
+ ws as extractGLBTexture,
5657
+ tr as fetchPreset,
5658
+ Gs as glbMeshParticleShader,
5659
+ $s as hexToRgb,
5660
+ ir as initHzFxOverlay,
5661
+ Cs as initWebGPU,
5662
+ Ti as isHZFX,
5663
+ er as loadScene,
5664
+ sr as makeThreeSceneDepth,
5665
+ Ns as multiplyMatrices,
5666
+ Is as object3dShader,
5667
+ ks as packHZFX,
5668
+ gi as parseGLB,
5669
+ As as particlePhysicsShader,
5670
+ bi as particleShader,
5671
+ Ws as rgbToHex,
5672
+ Qs as saveScene,
5673
+ Ys as serializeSystemConfig,
5674
+ Ei as unpackHZFX
4387
5675
  };