hz-particles 1.0.13 → 1.0.15

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 W {
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,20 +6,20 @@ 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, r = e * Math.PI / 180, n = i * Math.PI / 180, o = Math.cos(s), a = Math.sin(s), l = Math.cos(r), d = Math.sin(r), u = Math.cos(n), f = Math.sin(n);
14
14
  this._rotMatrix = [
15
- l * d,
16
- s * u * d - o * f,
17
- o * u * d + s * f,
15
+ l * u,
16
+ a * d * u - o * f,
17
+ o * d * u + a * f,
18
18
  l * f,
19
- s * u * f + o * d,
20
- o * u * f - s * d,
21
- -u,
22
- s * l,
19
+ a * d * f + o * u,
20
+ o * d * f - a * u,
21
+ -d,
22
+ a * l,
23
23
  o * l
24
24
  ], this._invRotMatrix = [
25
25
  this._rotMatrix[0],
@@ -34,79 +34,79 @@ 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._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 o = this._rotMatrix, a = s[0], l = s[1], d = s[2];
41
+ s[0] = o[0] * a + o[1] * l + o[2] * d, s[1] = o[3] * a + o[4] * l + o[5] * d, s[2] = o[6] * a + o[7] * l + o[8] * d;
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);
43
+ (this.config.emissionTranslationX || this.config.emissionTranslationY || this.config.emissionTranslationZ) && (s[0] += this.config.emissionTranslationX || 0, s[1] += this.config.emissionTranslationY || 0, s[2] += this.config.emissionTranslationZ || 0);
44
44
  const r = e * 8;
45
- t[r] = a[0], t[r + 1] = a[1], t[r + 2] = a[2];
45
+ t[r] = s[0], t[r + 1] = s[1], t[r + 2] = s[2];
46
46
  const n = e * 4;
47
- this.calculateVelocity(a[0], a[1], a[2], i, n), this.setParticleColor(t, r), this.setParticleLifetime(t, r);
47
+ this.calculateVelocity(s[0], s[1], s[2], i, n), this.setParticleColor(t, r), this.setParticleLifetime(t, r);
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), r = Math.random() - 0.5, n = Math.random() - 0.5;
73
+ let o, a, l;
74
+ switch (s) {
75
75
  case 0:
76
- o = r, s = n, l = 0.5;
76
+ o = r, a = n, l = 0.5;
77
77
  break;
78
78
  case 1:
79
- o = r, s = n, l = -0.5;
79
+ o = r, a = n, l = -0.5;
80
80
  break;
81
81
  case 2:
82
- o = 0.5, s = r, l = n;
82
+ o = 0.5, a = r, l = n;
83
83
  break;
84
84
  case 3:
85
- o = -0.5, s = r, l = n;
85
+ o = -0.5, a = r, l = n;
86
86
  break;
87
87
  case 4:
88
- o = r, s = 0.5, l = n;
88
+ o = r, a = 0.5, l = n;
89
89
  break;
90
90
  case 5:
91
- o = r, s = -0.5, l = n;
91
+ o = r, a = -0.5, l = n;
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 d = Math.random(), u = e + d * (i - e);
95
+ t[0] = o * u, t[1] = a * u, t[2] = l * u;
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);
100
+ const e = Math.random() * 2 * Math.PI, i = Math.acos(2 * Math.random() - 1), s = Math.sin(i) * Math.cos(e), r = Math.sin(i) * Math.sin(e), n = Math.cos(i);
101
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;
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] = s * o, t[1] = r * o, t[2] = n * o;
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);
107
+ const s = Math.floor(Math.random() * 4);
108
108
  let r = e + (i - e) * Math.random();
109
- switch (a) {
109
+ switch (s) {
110
110
  case 0:
111
111
  t[0] = (Math.random() * 2 - 1) * r, t[1] = r;
112
112
  break;
@@ -125,71 +125,71 @@ 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;
128
+ const e = this.config.circleInnerRadius || 0, i = this.config.circleOuterRadius || 2, s = Math.random() * Math.PI * 2;
129
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;
130
+ e > 0 ? r = e + (i - e) * Math.random() : r = i * Math.sqrt(Math.random()), t[0] = Math.cos(s) * r, t[1] = Math.sin(s) * r, 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, r = Math.random() * Math.PI * 2, n = Math.random(), o = n * s, a = i * (1 - n);
138
138
  let l;
139
139
  if (e > 0) {
140
- const u = e * (1 - n);
141
- l = u + (s - u) * Math.random();
140
+ const d = e * (1 - n);
141
+ l = d + (a - d) * Math.random();
142
142
  } else
143
- l = s * Math.sqrt(Math.random());
143
+ l = a * Math.sqrt(Math.random());
144
144
  t[0] = Math.cos(r) * l, t[1] = o, t[2] = Math.sin(r) * 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, r = Math.random() * Math.PI * 2, n = i * Math.sqrt(Math.random());
148
+ t[0] = (e + n * Math.cos(r)) * Math.cos(s), t[1] = n * Math.sin(r), t[2] = (e + n * Math.cos(r)) * 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, r = Math.acos(Math.random()), n = Math.sin(r) * Math.cos(s), o = Math.cos(r), a = Math.sin(r) * 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] = n * l, t[1] = o * l, t[2] = a * 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, r = e + (i - e) * Math.random();
165
+ t[0] = Math.cos(s) * r, t[1] = 0, t[2] = Math.sin(s) * r;
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);
168
+ const e = this.config.capsuleRadius || 0.5, i = this.config.capsuleHeight || 4, s = i * 0.5, r = Math.PI * e * e * i, n = 4 / 3 * Math.PI * e * e * e, o = r / (r + n);
169
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;
170
+ const a = Math.random() * Math.PI * 2, l = e * Math.sqrt(Math.random());
171
+ t[0] = Math.cos(a) * l, t[1] = (Math.random() - 0.5) * i, t[2] = Math.sin(a) * 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 a = Math.random() * Math.PI * 2, l = Math.acos(2 * Math.random() - 1), d = e * Math.cbrt(Math.random());
174
+ t[0] = d * Math.sin(l) * Math.cos(a), t[1] = d * Math.cos(l), t[2] = d * Math.sin(l) * Math.sin(a), 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, r = this.config.arcOuterRadius || 2, n = e * Math.PI / 180, o = i * Math.PI / 180, a = n + Math.random() * (o - n);
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 + (r - s) * Math.random() : l = r * Math.sqrt(Math.random()), t[0] = Math.cos(a) * l, t[1] = Math.sin(a) * 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, r = this.config.spiralHeight || 4, n = Math.random(), o = n * e * Math.PI * 2, a = i + (s - i) * n;
184
+ t[0] = Math.cos(o) * a, t[1] = (n - 0.5) * r, t[2] = Math.sin(o) * a;
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());
187
+ const e = this.config.frustumRadiusNear || 0.5, i = this.config.frustumRadiusFar || 2, s = this.config.frustumHeight || 4, r = Math.random() * Math.PI * 2, n = Math.random(), o = n * s, l = (e + (i - e) * n) * Math.sqrt(Math.random());
188
188
  t[0] = Math.cos(r) * l, t[1] = o, t[2] = Math.sin(r) * 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), r = (Math.random() - 0.5) * e, n = (Math.random() - 0.5) * e;
192
+ switch (s) {
193
193
  case 0:
194
194
  t[0] = r, t[1] = n, t[2] = i;
195
195
  break;
@@ -211,67 +211,71 @@ class Z {
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), n = (Math.random() - 0.5) * e, o = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
219
+ if (s < 4) {
220
+ const [a, l] = o[s];
221
+ t[0] = n, t[1] = a * i, t[2] = l * i;
222
+ } else if (s < 8) {
223
+ const [a, l] = o[s - 4];
224
+ t[0] = a * i, t[1] = n, 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 [a, l] = o[s - 8];
227
+ t[0] = a * i, t[1] = l * i, t[2] = n;
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);
235
- t[0] = l * i, t[1] = u * i, t[2] = 0;
231
+ const e = Math.max(3, Math.floor(this.config.polygonSides || 6)), i = this.config.polygonRadius || 2, s = Math.floor(Math.random() * e), r = s / e * Math.PI * 2, n = (s + 1) / e * Math.PI * 2;
232
+ let o = Math.random(), a = Math.random();
233
+ o + a > 1 && (o = 1 - o, a = 1 - a);
234
+ const l = o * Math.cos(r) + a * Math.cos(n), d = o * Math.sin(r) + a * Math.sin(n);
235
+ t[0] = l * i, t[1] = d * i, t[2] = 0;
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;
236
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;
242
+ const e = this.config.cylinderInnerRadius || 0, i = this.config.cylinderOuterRadius || 2, s = this.config.cylinderHeight || 4, r = Math.random() * Math.PI * 2;
239
243
  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;
244
+ 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) * s, t[2] = Math.sin(r) * n;
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);
246
+ calculateVelocity(t, e, i, s, r) {
247
+ const n = this.config.emissionTranslationX || 0, o = this.config.emissionTranslationY || 0, a = this.config.emissionTranslationZ || 0, l = t - n, d = e - o, u = i - a, f = Math.sqrt(l * l + d * d + u * u);
244
248
  let h, p, m;
245
249
  if (f > 1e-4) {
246
250
  let S = !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 y = this.inverseRotation(l, d, u), _ = Math.sqrt(y[0] * y[0] + y[1] * y[1]);
253
+ if (_ > 1e-4) {
254
+ const g = -y[1] / _, x = y[0] / _, P = this.applyRotation(g, x, 0);
255
+ h = P[0], p = P[1], m = P[2], S = !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 y = this.inverseRotation(l, d, u), _ = Math.sqrt(y[0] * y[0] + y[2] * y[2]);
259
+ if (_ > 1e-4) {
260
+ const g = -y[2] / _, x = y[0] / _, P = this.applyRotation(g, 0, x);
261
+ h = P[0], p = P[1], m = P[2], S = !0;
258
262
  } else {
259
263
  const g = Math.random() * Math.PI * 2, x = this.applyRotation(Math.cos(g), 0, Math.sin(g));
260
264
  h = x[0], p = x[1], m = x[2], S = !0;
261
265
  }
262
266
  }
263
- S || (h = l / f, p = u / f, m = d / f);
267
+ S || (h = l / f, p = d / f, m = u / f);
264
268
  } else {
265
269
  const S = Math.random() * Math.PI * 2, y = Math.acos(2 * Math.random() - 1);
266
270
  h = Math.sin(y) * Math.cos(S), p = Math.sin(y) * Math.sin(S), m = Math.cos(y);
267
271
  }
268
272
  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;
273
+ this.config.randomSpeed ? b = (this.config.minSpeed || 0) + Math.random() * ((this.config.maxSpeed || 1) - (this.config.minSpeed || 0)) : b = this.config.particleSpeed, s[r] = this.config.overrideXVelocity ? this.config.xVelocity : h * b, s[r + 1] = this.config.overrideYVelocity ? this.config.yVelocity : p * b, s[r + 2] = this.config.overrideZVelocity ? this.config.zVelocity : m * b, s[r + 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 J {
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(() => H);
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,17 +399,17 @@ class q {
387
399
  ]
388
400
  });
389
401
  }
390
- updatePhysics(t, e, i, a, r, n) {
402
+ updatePhysics(t, e, i, s, r, n) {
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" });
396
- 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;
399
- }
400
- async readbackAndProcessParticles(t, e, i, a, r) {
405
+ const o = this._physicsData, a = this.physicsSettings;
406
+ o[0] = t, o[1] = i.particleSpeed, o[2] = a.gravity, o[3] = a.turbulence, o[4] = a.attractorStrength, o[5] = a.damping, o[6] = a.attractorPosition[0], o[7] = a.attractorPosition[1], o[8] = a.attractorPosition[2], this._physicsDataU32View[9] = e, o[10] = a.confinementEnabled ? 1 : 0, o[11] = a.confinementShape === "sphere" ? 1 : 0, o[12] = a.confinementMode === "kill" ? 1 : 0, o[13] = a.confinementSpace === "local" ? 1 : 0, o[14] = a.confinementBoxHalfSize[0], o[15] = a.confinementBoxHalfSize[1], o[16] = a.confinementBoxHalfSize[2], o[17] = a.confinementSphereRadius, o[18] = a.confinementRestitution, o[19] = a.confinementFriction, o[20] = a.confinementCenter[0], o[21] = a.confinementCenter[1], o[22] = a.confinementCenter[2], o[23] = a.softBoundaryEnabled ? 1 : 0, o[24] = a.softBoundaryStrength, o[25] = a.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);
407
+ const l = n || this.device.createCommandEncoder({ label: "ParticlePhysicsEncoder" }), d = l.beginComputePass({ label: "ParticlePhysicsPass" });
408
+ d.setPipeline(this.computePipeline), d.setBindGroup(0, this.computeBindGroup);
409
+ const u = Math.max(1, Math.ceil(e / 64));
410
+ d.dispatchWorkgroups(u, 1, 1), d.end(), n || this.device.queue.submit([l.finish()]), this.lastUpdateTime = performance.now() / 1e3;
411
+ }
412
+ async readbackAndProcessParticles(t, e, i, s, r) {
401
413
  if (t <= 0)
402
414
  return { activeCount: 0, shouldUpdate: !1 };
403
415
  if (this._stagingInUse)
@@ -408,19 +420,19 @@ class q {
408
420
  label: "ParticleReadbackEncoder"
409
421
  }), o = t * 8 * 4;
410
422
  n.copyBufferToBuffer(
411
- a,
423
+ s,
412
424
  0,
413
425
  this._particleDataStagingBuffer,
414
426
  0,
415
427
  o
416
428
  );
417
- const s = t * 4 * 4;
429
+ const a = t * 4 * 4;
418
430
  return n.copyBufferToBuffer(
419
431
  r,
420
432
  0,
421
433
  this._velocityStagingBuffer,
422
434
  0,
423
- s
435
+ a
424
436
  ), this.device.queue.submit([n.finish()]), await Promise.all([
425
437
  (async () => {
426
438
  await this._particleDataStagingBuffer.mapAsync(GPUMapMode.READ, 0, o);
@@ -428,8 +440,8 @@ class q {
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, a);
444
+ const l = new Float32Array(this._velocityStagingBuffer.getMappedRange(0, a));
433
445
  i.set(l), this._velocityStagingBuffer.unmap();
434
446
  })()
435
447
  ]), this._stagingInUse = !1, {
@@ -465,29 +477,29 @@ 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, r) {
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 n = t * 8 * 4, o = t * 4 * 4, a = this.device.createCommandEncoder({
476
488
  label: "RenderReadbackEncoder"
477
489
  });
478
- return s.copyBufferToBuffer(
479
- a,
490
+ return a.copyBufferToBuffer(
491
+ s,
480
492
  0,
481
493
  this._renderStagingParticleBuffer,
482
494
  0,
483
495
  n
484
- ), s.copyBufferToBuffer(
496
+ ), a.copyBufferToBuffer(
485
497
  r,
486
498
  0,
487
499
  this._renderStagingVelocityBuffer,
488
500
  0,
489
501
  o
490
- ), this.device.queue.submit([s.finish()]), await Promise.all([
502
+ ), this.device.queue.submit([a.finish()]), await Promise.all([
491
503
  (async () => {
492
504
  await this._renderStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, n);
493
505
  const l = new Float32Array(this._renderStagingParticleBuffer.getMappedRange(0, n));
@@ -507,18 +519,67 @@ class q {
507
519
  return this._renderStagingInUse = !1, console.error("Error in rendering readback:", n), { shouldUpdate: !1 };
508
520
  }
509
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, r) {
534
+ if (t <= 0)
535
+ return { shouldUpdate: !1 };
536
+ if (this._scriptStagingInUse)
537
+ return { shouldUpdate: !1 };
538
+ try {
539
+ this._scriptStagingInUse = !0;
540
+ const n = t * 8 * 4, o = t * 4 * 4, a = this.device.createCommandEncoder({
541
+ label: "ScriptReadbackEncoder"
542
+ });
543
+ return a.copyBufferToBuffer(
544
+ s,
545
+ 0,
546
+ this._scriptStagingParticleBuffer,
547
+ 0,
548
+ n
549
+ ), a.copyBufferToBuffer(
550
+ r,
551
+ 0,
552
+ this._scriptStagingVelocityBuffer,
553
+ 0,
554
+ o
555
+ ), this.device.queue.submit([a.finish()]), await Promise.all([
556
+ (async () => {
557
+ await this._scriptStagingParticleBuffer.mapAsync(GPUMapMode.READ, 0, n);
558
+ const l = new Float32Array(this._scriptStagingParticleBuffer.getMappedRange(0, n));
559
+ e.set(l), this._scriptStagingParticleBuffer.unmap();
560
+ })(),
561
+ (async () => {
562
+ await this._scriptStagingVelocityBuffer.mapAsync(GPUMapMode.READ, 0, o);
563
+ const l = new Float32Array(this._scriptStagingVelocityBuffer.getMappedRange(0, o));
564
+ i.set(l), this._scriptStagingVelocityBuffer.unmap();
565
+ })()
566
+ ]), this._scriptStagingInUse = !1, { shouldUpdate: !0 };
567
+ } catch (n) {
568
+ return this._scriptStagingInUse = !1, console.error("Error in script readback:", n), { shouldUpdate: !1 };
569
+ }
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 K {
522
583
  constructor(t) {
523
584
  this.device = t, this.defaultTexture = null, this.createDefaultTexture();
524
585
  }
@@ -557,21 +618,289 @@ class $ {
557
618
  t && t.label !== "defaultParticleTexture" && t.destroy();
558
619
  }
559
620
  }
560
- async function O(c) {
621
+ const N = 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(c, t, e) {
636
+ return c < t ? t : c > e ? e : c;
637
+ },
638
+ lerp(c, t, e) {
639
+ return c + (t - c) * e;
640
+ },
641
+ smoothstep(c, t, e) {
642
+ const i = N.clamp((e - c) / (t - c), 0, 1);
643
+ return i * i * (3 - 2 * i);
644
+ }
645
+ }), T = /* @__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 Q {
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 ee {
740
+ constructor() {
741
+ this._proxy = new Q(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 te = 1e6;
751
+ function ie(c) {
752
+ let t = 0;
753
+ return c.replace(
754
+ /\b(for|while)\s*\([^)]*\)\s*\{/g,
755
+ (e) => {
756
+ const i = `__lc${t++}`;
757
+ return `${e} if(++${i}>${te})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 U = /* @__PURE__ */ new Map();
775
+ for (const c of T)
776
+ U.set(c.toLowerCase(), c);
777
+ function se(c) {
778
+ const t = { value: !1 }, e = /* @__PURE__ */ new Set();
779
+ return new Proxy(c, {
780
+ get(s, r) {
781
+ if (r === "__dirty") return t.value;
782
+ if (r === "__resetDirty") return () => {
783
+ t.value = !1;
784
+ };
785
+ if (typeof r != "string") return;
786
+ if (T.has(r)) return s[r];
787
+ const n = U.get(r.toLowerCase());
788
+ if (n)
789
+ return e.has(r) || (e.add(r), console.warn(`[ParticleScript] config.${r} → did you mean config.${n}?`)), s[n];
790
+ },
791
+ set(s, r, n) {
792
+ if (typeof r != "string") return !0;
793
+ let o = r;
794
+ if (!T.has(o)) {
795
+ const a = U.get(o.toLowerCase());
796
+ if (a)
797
+ e.has(r) || (e.add(r), console.warn(`[ParticleScript] config.${r} → did you mean config.${a}?`)), o = a;
798
+ else
799
+ return !0;
800
+ }
801
+ return s[o] = n, t.value = !0, !0;
802
+ }
803
+ });
804
+ }
805
+ class z {
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 ee(), this._configProxy = se(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
+ ${ie(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, r, n, o) {
847
+ if (!this._fn || this._error) return { configDirty: !1, particlesDirty: !1 };
848
+ this._particles._bind(r, n, o), this._configProxy.__resetDirty();
849
+ try {
850
+ this._fn(t, e, i, s, this._particles, this._configProxy, N);
851
+ } catch (a) {
852
+ console.warn("[ParticleScript] Runtime error:", a.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 T) {
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 T)
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 X(c) {
561
890
  const t = new DataView(c);
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);
896
+ const s = t.getUint32(8, !0);
568
897
  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);
898
+ for (; r < s; ) {
899
+ const g = t.getUint32(r, !0), x = t.getUint32(r + 4, !0), P = c.slice(r + 8, r + 8 + g);
571
900
  if (x === 1313821514) {
572
- const B = new TextDecoder("utf-8").decode(M);
573
- n = JSON.parse(B);
574
- } else x === 5130562 && (o = M);
901
+ const w = new TextDecoder("utf-8").decode(P);
902
+ n = JSON.parse(w);
903
+ } else x === 5130562 && (o = P);
575
904
  r += 8 + g;
576
905
  }
577
906
  if (!n)
@@ -581,50 +910,50 @@ async function O(c) {
581
910
  const l = n.meshes[0].primitives[0];
582
911
  if (!l)
583
912
  throw new Error("First mesh has no primitives");
584
- const u = l.attributes.POSITION;
585
- if (u === void 0)
913
+ const d = l.attributes.POSITION;
914
+ if (d === void 0)
586
915
  throw new Error("Mesh primitive missing POSITION attribute");
587
- const d = C(n, o, u, 3, 5126);
916
+ const u = E(n, o, d, 3, 5126);
588
917
  let f;
589
918
  if (l.attributes.NORMAL !== void 0)
590
- f = C(n, o, l.attributes.NORMAL, 3, 5126);
919
+ f = E(n, o, l.attributes.NORMAL, 3, 5126);
591
920
  else {
592
921
  const g = l.indices;
593
922
  if (g === 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 x = F(n, o, g);
925
+ f = ae(u, x);
597
926
  }
598
927
  const h = l.indices;
599
928
  if (h === 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;
930
+ const p = F(n, o, h), m = u.length / 3, b = p.length;
602
931
  let S = null;
603
- l.attributes.TEXCOORD_0 !== void 0 && (S = C(n, o, l.attributes.TEXCOORD_0, 2, 5126));
932
+ l.attributes.TEXCOORD_0 !== void 0 && (S = E(n, o, l.attributes.TEXCOORD_0, 2, 5126));
604
933
  let y = !1;
605
934
  if (n.materials && n.materials.length > 0) {
606
935
  const g = n.materials[0];
607
936
  g.pbrMetallicRoughness && g.pbrMetallicRoughness.baseColorTexture !== void 0 && (y = !0);
608
937
  }
609
- let P = null;
938
+ let _ = null;
610
939
  if (n.skins && n.skins.length > 0)
611
940
  try {
612
- P = te(n, o, l), console.log("Animation data extracted:", P);
941
+ _ = de(n, o, l), console.log("Animation data extracted:", _);
613
942
  } catch (g) {
614
943
  console.warn("Failed to extract animation data:", g);
615
944
  }
616
945
  return {
617
- positions: d,
946
+ positions: u,
618
947
  normals: f,
619
948
  indices: p,
620
949
  texCoords: S,
621
950
  vertexCount: m,
622
951
  indexCount: b,
623
- animationData: P,
952
+ animationData: _,
624
953
  hasBaseColorTexture: y
625
954
  };
626
955
  }
627
- function C(c, t, e, i, a) {
956
+ function E(c, t, e, i, s) {
628
957
  const r = c.accessors[e], o = {
629
958
  SCALAR: 1,
630
959
  VEC2: 2,
@@ -633,130 +962,130 @@ function C(c, t, e, i, a) {
633
962
  }[r.type];
634
963
  if (o !== i)
635
964
  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);
965
+ if (r.componentType !== s)
966
+ throw new Error(`Attribute component type mismatch: expected ${s}, got ${r.componentType}`);
967
+ const l = (c.bufferViews[r.bufferView].byteOffset || 0) + (r.byteOffset || 0), d = r.count, u = new DataView(t, l, d * i * 4), f = new Float32Array(d * i);
968
+ for (let h = 0; h < d * i; h++)
969
+ f[h] = u.getFloat32(h * 4, !0);
641
970
  return f;
642
971
  }
643
- function I(c, t, e) {
972
+ function F(c, t, e) {
644
973
  const i = c.accessors[e];
645
974
  if (i.type !== "SCALAR")
646
975
  throw new Error(`Indices accessor must be SCALAR, got ${i.type}`);
647
976
  const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
648
977
  if (i.componentType === 5123) {
649
- const o = new DataView(t, r, n * 2), s = new Uint16Array(n);
978
+ const o = new DataView(t, r, n * 2), a = new Uint16Array(n);
650
979
  for (let l = 0; l < n; l++)
651
- s[l] = o.getUint16(l * 2, !0);
652
- return s;
980
+ a[l] = o.getUint16(l * 2, !0);
981
+ return a;
653
982
  } else if (i.componentType === 5125) {
654
- const o = new DataView(t, r, n * 4), s = new Uint32Array(n);
983
+ const o = new DataView(t, r, n * 4), a = new Uint32Array(n);
655
984
  for (let l = 0; l < n; l++)
656
- s[l] = o.getUint32(l * 4, !0);
657
- return s;
985
+ a[l] = o.getUint32(l * 4, !0);
986
+ return a;
658
987
  } else
659
988
  throw new Error(`Unsupported index component type: ${i.componentType}`);
660
989
  }
661
- function H(c, t) {
990
+ function ae(c, t) {
662
991
  const e = new Float32Array(c.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]
993
+ const s = t[i] * 3, r = t[i + 1] * 3, n = t[i + 2] * 3, o = [c[s], c[s + 1], c[s + 2]], a = [c[r], c[r + 1], c[r + 2]], l = [c[n], c[n + 1], c[n + 2]], d = [a[0] - o[0], a[1] - o[1], a[2] - o[2]], u = [l[0] - o[0], l[1] - o[1], l[2] - o[2]], f = [
994
+ d[1] * u[2] - d[2] * u[1],
995
+ d[2] * u[0] - d[0] * u[2],
996
+ d[0] * u[1] - d[1] * u[0]
668
997
  ], 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];
998
+ h > 0 && (f[0] /= h, f[1] /= h, f[2] /= h), e[s] = e[r] = e[n] = f[0], e[s + 1] = e[r + 1] = e[n + 1] = f[1], e[s + 2] = e[r + 2] = e[n + 2] = f[2];
670
999
  }
671
1000
  return e;
672
1001
  }
673
- function W(c, t, e) {
1002
+ function re(c, t, e) {
674
1003
  const i = c.accessors[e];
675
1004
  if (i.type !== "VEC4")
676
1005
  throw new Error(`JOINTS_0 must be VEC4, got ${i.type}`);
677
1006
  const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
678
1007
  if (i.componentType === 5121) {
679
- const o = new DataView(t, r, n * 4), s = new Uint8Array(n * 4);
1008
+ const o = new DataView(t, r, n * 4), a = new Uint8Array(n * 4);
680
1009
  for (let l = 0; l < n * 4; l++)
681
- s[l] = o.getUint8(l);
682
- return s;
1010
+ a[l] = o.getUint8(l);
1011
+ return a;
683
1012
  } else if (i.componentType === 5123) {
684
- const o = new DataView(t, r, n * 8), s = new Uint8Array(n * 4);
1013
+ const o = new DataView(t, r, n * 8), a = new Uint8Array(n * 4);
685
1014
  for (let l = 0; l < n * 4; l++)
686
- s[l] = o.getUint16(l * 2, !0);
687
- return s;
1015
+ a[l] = o.getUint16(l * 2, !0);
1016
+ return a;
688
1017
  } else
689
1018
  throw new Error(`Unsupported JOINTS_0 component type: ${i.componentType}`);
690
1019
  }
691
- function J(c, t, e) {
1020
+ function ne(c, t, e) {
692
1021
  const i = c.accessors[e];
693
1022
  if (i.type !== "VEC4")
694
1023
  throw new Error(`WEIGHTS_0 must be VEC4, got ${i.type}`);
695
1024
  const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count;
696
1025
  if (i.componentType === 5126) {
697
- const o = new DataView(t, r, n * 16), s = new Float32Array(n * 4);
1026
+ const o = new DataView(t, r, n * 16), a = new Float32Array(n * 4);
698
1027
  for (let l = 0; l < n * 4; l++)
699
- s[l] = o.getFloat32(l * 4, !0);
700
- return s;
1028
+ a[l] = o.getFloat32(l * 4, !0);
1029
+ return a;
701
1030
  } else if (i.componentType === 5121) {
702
- const o = new DataView(t, r, n * 4), s = new Float32Array(n * 4);
1031
+ const o = new DataView(t, r, n * 4), a = new Float32Array(n * 4);
703
1032
  for (let l = 0; l < n * 4; l++)
704
- s[l] = o.getUint8(l) / 255;
705
- return s;
1033
+ a[l] = o.getUint8(l) / 255;
1034
+ return a;
706
1035
  } else
707
1036
  throw new Error(`Unsupported WEIGHTS_0 component type: ${i.componentType}`);
708
1037
  }
709
- function K(c, t, e) {
1038
+ function oe(c, t, e) {
710
1039
  const i = c.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);
1044
+ const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count, o = new DataView(t, r, n * 64), a = new Float32Array(n * 16);
716
1045
  for (let l = 0; l < n * 16; l++)
717
- s[l] = o.getFloat32(l * 4, !0);
718
- return s;
1046
+ a[l] = o.getFloat32(l * 4, !0);
1047
+ return a;
719
1048
  }
720
- function Q(c, t, e) {
1049
+ function le(c, t, e) {
721
1050
  const i = c.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);
1055
+ const r = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), n = i.count, o = new DataView(t, r, n * 4), a = new Float32Array(n);
727
1056
  for (let l = 0; l < n; l++)
728
- s[l] = o.getFloat32(l * 4, !0);
729
- return s;
1057
+ a[l] = o.getFloat32(l * 4, !0);
1058
+ return a;
730
1059
  }
731
- function ee(c, t, e) {
1060
+ function ce(c, t, e) {
732
1061
  const i = c.accessors[e], r = { VEC3: 3, VEC4: 4 }[i.type];
733
1062
  if (!r)
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);
740
- return u;
1066
+ const o = (c.bufferViews[i.bufferView].byteOffset || 0) + (i.byteOffset || 0), a = i.count, l = new DataView(t, o, a * r * 4), d = new Float32Array(a * r);
1067
+ for (let u = 0; u < a * r; u++)
1068
+ d[u] = l.getFloat32(u * 4, !0);
1069
+ return d;
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;
1071
+ function de(c, t, e) {
1072
+ const i = c.skins[0], s = i.joints, r = oe(c, t, i.inverseBindMatrices), n = e.attributes.JOINTS_0 !== void 0 ? re(c, t, e.attributes.JOINTS_0) : null, o = e.attributes.WEIGHTS_0 !== void 0 ? ne(c, t, e.attributes.WEIGHTS_0) : null;
744
1073
  if (!n || !o)
745
1074
  throw new Error("Mesh missing JOINTS_0 or WEIGHTS_0 attributes");
746
- const s = c.nodes.map((u) => ({
747
- translation: u.translation || [0, 0, 0],
748
- rotation: u.rotation || [0, 0, 0, 1],
749
- scale: u.scale || [1, 1, 1],
750
- children: u.children || [],
751
- name: u.name || ""
1075
+ const a = c.nodes.map((d) => ({
1076
+ translation: d.translation || [0, 0, 0],
1077
+ rotation: d.rotation || [0, 0, 0, 1],
1078
+ scale: d.scale || [1, 1, 1],
1079
+ children: d.children || [],
1080
+ name: d.name || ""
752
1081
  })), l = [];
753
1082
  if (c.animations && c.animations.length > 0)
754
- for (const u of c.animations) {
755
- const d = [];
1083
+ for (const d of c.animations) {
1084
+ const u = [];
756
1085
  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({
1086
+ for (const h of d.channels) {
1087
+ const p = d.samplers[h.sampler], m = le(c, t, p.input), b = ce(c, t, p.output), S = m[m.length - 1];
1088
+ S > f && (f = S), u.push({
760
1089
  targetNode: h.target.node,
761
1090
  targetPath: h.target.path,
762
1091
  interpolation: p.interpolation || "LINEAR",
@@ -765,51 +1094,51 @@ function te(c, t, e) {
765
1094
  });
766
1095
  }
767
1096
  l.push({
768
- name: u.name || `Animation ${l.length}`,
1097
+ name: d.name || `Animation ${l.length}`,
769
1098
  duration: f,
770
- channels: d
1099
+ channels: u
771
1100
  });
772
1101
  }
773
1102
  return {
774
- joints: a,
1103
+ joints: s,
775
1104
  inverseBindMatrices: r,
776
1105
  jointIndices: n,
777
1106
  jointWeights: o,
778
- nodes: s,
1107
+ nodes: a,
779
1108
  animations: l
780
1109
  };
781
1110
  }
782
- async function ie(c) {
1111
+ async function ue(c) {
783
1112
  const t = new DataView(c);
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);
1118
+ const s = t.getUint32(8, !0);
790
1119
  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);
1120
+ for (; r < s; ) {
1121
+ const _ = t.getUint32(r, !0), g = t.getUint32(r + 4, !0), x = c.slice(r + 8, r + 8 + _);
793
1122
  if (g === 1313821514) {
794
- const R = new TextDecoder("utf-8").decode(x);
795
- n = JSON.parse(R);
1123
+ const M = new TextDecoder("utf-8").decode(x);
1124
+ n = JSON.parse(M);
796
1125
  } else g === 5130562 && (o = x);
797
- r += 8 + P;
1126
+ r += 8 + _;
798
1127
  }
799
1128
  if (!n)
800
1129
  throw new Error("GLB file missing JSON chunk");
801
1130
  if (!n.materials || n.materials.length === 0)
802
1131
  return null;
803
- const s = n.materials[0];
804
- if (!s.pbrMetallicRoughness || s.pbrMetallicRoughness.baseColorTexture === void 0)
1132
+ const a = n.materials[0];
1133
+ if (!a.pbrMetallicRoughness || a.pbrMetallicRoughness.baseColorTexture === void 0)
805
1134
  return null;
806
- const l = s.pbrMetallicRoughness.baseColorTexture.index;
1135
+ const l = a.pbrMetallicRoughness.baseColorTexture.index;
807
1136
  if (!n.textures || !n.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 u = n.textures[l].source;
1139
+ if (u === void 0 || !n.images || !n.images[u])
811
1140
  return null;
812
- const f = n.images[d], h = f.mimeType || "image/png";
1141
+ const f = n.images[u], h = f.mimeType || "image/png";
813
1142
  if (f.bufferView === void 0)
814
1143
  return null;
815
1144
  if (!o)
@@ -817,55 +1146,55 @@ async function ie(c) {
817
1146
  const p = n.bufferViews[f.bufferView], m = p.byteOffset || 0, b = p.byteLength, S = o.slice(m, m + b);
818
1147
  return { imageBlob: new Blob([S], { type: h }), mimeType: h };
819
1148
  }
820
- const U = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1149
+ const D = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
821
1150
  __proto__: null,
822
- extractGLBTexture: ie,
823
- parseGLB: O
1151
+ extractGLBTexture: ue,
1152
+ parseGLB: X
824
1153
  }, Symbol.toStringTag, { value: "Module" }));
825
- function z(c, t, e) {
1154
+ function G(c, t, e) {
826
1155
  return [
827
1156
  c[0] + (t[0] - c[0]) * e,
828
1157
  c[1] + (t[1] - c[1]) * e,
829
1158
  c[2] + (t[2] - c[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 V(c, t, e) {
1162
+ let i = c[0] * t[0] + c[1] * t[1] + c[2] * t[2] + c[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
+ c[0] + (s[0] - c[0]) * e,
1166
+ c[1] + (s[1] - c[1]) * e,
1167
+ c[2] + (s[2] - c[2]) * e,
1168
+ c[3] + (s[3] - c[3]) * e
840
1169
  ];
841
- return ae(l);
1170
+ return fe(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 r = Math.acos(i), n = Math.sin(r), o = Math.sin((1 - e) * r) / n, a = Math.sin(e * r) / n;
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
+ c[0] * o + s[0] * a,
1175
+ c[1] * o + s[1] * a,
1176
+ c[2] * o + s[2] * a,
1177
+ c[3] * o + s[3] * a
849
1178
  ];
850
1179
  }
851
- function ae(c) {
1180
+ function fe(c) {
852
1181
  const t = Math.sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
853
1182
  return t > 1e-4 ? [c[0] / t, c[1] / t, c[2] / t, c[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 he(c) {
1185
+ const t = c[0], e = c[1], i = c[2], s = c[3], r = t + t, n = e + e, o = i + i, a = t * r, l = t * n, d = t * o, u = e * n, f = e * o, h = i * o, p = s * r, m = s * n, b = s * o;
857
1186
  return new Float32Array([
858
- 1 - (d + h),
1187
+ 1 - (u + h),
859
1188
  l + b,
860
- u - m,
1189
+ d - m,
861
1190
  0,
862
1191
  l - b,
863
- 1 - (s + h),
1192
+ 1 - (a + h),
864
1193
  f + p,
865
1194
  0,
866
- u + m,
1195
+ d + m,
867
1196
  f - p,
868
- 1 - (s + d),
1197
+ 1 - (a + u),
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 pe(c, t, e) {
1206
+ const i = he(t);
878
1207
  return new Float32Array([
879
1208
  i[0] * e[0],
880
1209
  i[1] * e[0],
@@ -894,14 +1223,14 @@ function re(c, t, e) {
894
1223
  1
895
1224
  ]);
896
1225
  }
897
- function G(c, t) {
1226
+ function L(c, 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] = c[0 + s] * t[i * 4 + 0] + c[4 + s] * t[i * 4 + 1] + c[8 + s] * t[i * 4 + 2] + c[12 + s] * t[i * 4 + 3];
902
1231
  return e;
903
1232
  }
904
- class ne {
1233
+ class me {
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,10 +1254,10 @@ 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, r = new Float32Array(s * 8);
1258
+ for (let l = 0; l < s; l++) {
1259
+ const d = l * 8, u = l * 3, f = l * 2;
1260
+ r[d] = this.restPositions[u], r[d + 1] = this.restPositions[u + 1], r[d + 2] = this.restPositions[u + 2], r[d + 3] = this.restNormals[u], r[d + 4] = this.restNormals[u + 1], r[d + 5] = this.restNormals[u + 2], r[d + 6] = i ? i[f] : 0, r[d + 7] = i ? i[f + 1] : 0;
932
1261
  }
933
1262
  this._gpuRestDataBuffer = t.createBuffer({
934
1263
  size: r.byteLength,
@@ -951,7 +1280,7 @@ class ne {
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: o } = await Promise.resolve().then(() => H), a = 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: [a] }),
965
1294
  compute: {
966
1295
  module: t.createShaderModule({ code: o }),
967
1296
  entryPoint: "main"
968
1297
  }
969
1298
  }), this._gpuSkinningBindGroup = t.createBindGroup({
970
- layout: s,
1299
+ layout: a,
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
  /**
@@ -1034,41 +1363,41 @@ class ne {
1034
1363
  for (const o of n.children)
1035
1364
  i(o);
1036
1365
  e.push(r);
1037
- }, a = /* @__PURE__ */ new Set();
1366
+ }, s = /* @__PURE__ */ new Set();
1038
1367
  for (const r of this.nodes)
1039
1368
  for (const n of r.children)
1040
- a.add(n);
1369
+ s.add(n);
1041
1370
  for (let r = 0; r < this.nodes.length; r++)
1042
- a.has(r) || i(r);
1371
+ s.has(r) || i(r);
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: r, targetPath: n } = t;
1050
1379
  if (e <= i[0])
1051
- return this._extractValue(a, 0, n);
1380
+ return this._extractValue(s, 0, n);
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, n);
1383
+ let o = 0, a = i.length - 1;
1384
+ for (; a - o > 1; ) {
1385
+ const p = Math.floor((o + a) / 2);
1386
+ i[p] <= e ? o = p : a = p;
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[o], d = i[a], u = (e - l) / (d - l), f = this._extractValue(s, o, n), h = this._extractValue(s, a, n);
1389
+ return r === "STEP" ? f : n === "rotation" ? V(f, h, u) : G(f, h, u);
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 r = s.translation, n = s.rotation, o = s.scale;
1411
+ for (const a of e.channels)
1412
+ if (a.targetNode === i) {
1413
+ const l = this._sampleChannel(a, t);
1414
+ a.targetPath === "translation" ? r = l : a.targetPath === "rotation" ? n = l : a.targetPath === "scale" && (o = l);
1086
1415
  }
1087
- this.jointLocalTransforms[i] = re(r, n, o);
1416
+ this.jointLocalTransforms[i] = pe(r, n, o);
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] = L(
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, r = this.inverseBindMatrices.slice(s, s + 16);
1443
+ this.jointFinalMatrices[t] = L(i, r);
1115
1444
  }
1116
1445
  }
1117
1446
  /**
@@ -1119,28 +1448,28 @@ 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, r = this.skinnedNormals, n = this.jointWeights, o = this.jointIndices, a = 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 d = l * 3, u = l * 4, f = e[d], h = e[d + 1], p = e[d + 2], m = i[d], b = i[d + 1], S = i[d + 2];
1454
+ let y = 0, _ = 0, g = 0, x = 0, P = 0, M = 0;
1455
+ for (let B = 0; B < 4; B++) {
1456
+ const R = n[u + B];
1457
+ if (R === 0) continue;
1458
+ const v = a[o[u + B]];
1459
+ y += (v[0] * f + v[4] * h + v[8] * p + v[12]) * R, _ += (v[1] * f + v[5] * h + v[9] * p + v[13]) * R, g += (v[2] * f + v[6] * h + v[10] * p + v[14]) * R, x += (v[0] * m + v[4] * b + v[8] * S) * R, P += (v[1] * m + v[5] * b + v[9] * S) * R, M += (v[2] * m + v[6] * b + v[10] * S) * R;
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 w = Math.sqrt(x * x + P * P + M * M);
1462
+ w > 1e-4 && (r[d] = x / w, r[d + 1] = P / w, r[d + 2] = M / w), s[d] = y, s[d + 1] = _, s[d + 2] = g;
1134
1463
  }
1135
1464
  }
1136
1465
  }
1137
- function V(c) {
1466
+ function O(c) {
1138
1467
  const t = atob(c), 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 _ {
1472
+ class A {
1144
1473
  constructor(t, e) {
1145
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.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,
@@ -1166,7 +1495,7 @@ class _ {
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.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.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.emissionRotationX === void 0 && (e.emissionRotationX = 0), e.emissionRotationY === void 0 && (e.emissionRotationY = 0), e.emissionRotationZ === void 0 && (e.emissionRotationZ = 0), e.emissionTranslationX === void 0 && (e.emissionTranslationX = 0), e.emissionTranslationY === void 0 && (e.emissionTranslationY = 0), e.emissionTranslationZ === void 0 && (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.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 W(e), this.physics = new J(t, this.MAX_PARTICLES), this.textureManager = new K(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,11 +1508,18 @@ class _ {
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 z(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 z(t, this.config, this.MAX_PARTICLES), this._particleScript.snapshotConfig(this.config)) : delete this.config.script;
1522
+ }
1187
1523
  async setTexture(t) {
1188
1524
  this.textureManager.destroyTexture(this.particleTexture), this.particleTexture = await this.textureManager.loadTexture(t), this.config.textureEnabled = !0, this.updateAppearanceUniform(), this.updateBuffers();
1189
1525
  }
@@ -1193,11 +1529,11 @@ class _ {
1193
1529
  async setGLBModel(t) {
1194
1530
  try {
1195
1531
  this.glbRawArrayBuffer = t;
1196
- const e = await O(t);
1532
+ const e = await X(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;
1535
+ for (let s = 0; s < e.vertexCount; s++) {
1536
+ const r = s * 8, n = s * 3, o = s * 2;
1201
1537
  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);
1202
1538
  }
1203
1539
  if (this.glbVertexBuffer && this.glbVertexBuffer.destroy(), this.glbIndexBuffer && this.glbIndexBuffer.destroy(), this.glbVertexBuffer = this.device.createBuffer({
@@ -1209,11 +1545,11 @@ class _ {
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 me(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
@@ -1237,14 +1573,14 @@ class _ {
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
1575
  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);
1576
+ const e = Math.cos(this._simRotX), i = Math.sin(this._simRotX), s = Math.cos(this._simRotZ), r = Math.sin(this._simRotZ);
1241
1577
  this._simRotMatrix = [
1242
- a,
1578
+ s,
1243
1579
  -r * e,
1244
1580
  r * i,
1245
1581
  r,
1246
- a * e,
1247
- -a * i,
1582
+ s * e,
1583
+ -s * i,
1248
1584
  0,
1249
1585
  i,
1250
1586
  e
@@ -1261,8 +1597,8 @@ class _ {
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;
1600
+ for (let s = 0; s < this.glbMeshData.vertexCount; s++) {
1601
+ const r = s * 8, n = s * 3, o = s * 2;
1266
1602
  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);
1267
1603
  }
1268
1604
  return this.device.queue.writeBuffer(this.glbVertexBuffer, 0, this._glbInterleavedData), !0;
@@ -1270,8 +1606,10 @@ class _ {
1270
1606
  updateAppearanceUniform() {
1271
1607
  let t = 0;
1272
1608
  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]}`), a[36] = this._simPosition[0], a[37] = this._simPosition[1], a[38] = this._simPosition[2], 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);
1609
+ 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;
1610
+ 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] = this.config.particleShapeRotation || 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]}`);
1611
+ const r = this.config.followSystemTranslation ?? !0;
1612
+ s[36] = r ? this._simPosition[0] : 0, s[37] = r ? this._simPosition[1] : 0, s[38] = r ? 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, this.device.queue.writeBuffer(this.appearanceUniformBuffer, 0, s);
1275
1613
  }
1276
1614
  updateBloomIntensity() {
1277
1615
  const t = this._bloomIntensityData;
@@ -1280,7 +1618,7 @@ class _ {
1280
1618
  t[4] = e[0], t[5] = e[1], t[6] = e[2], this.device.queue.writeBuffer(this.bloomIntensityBuffer, 0, t);
1281
1619
  }
1282
1620
  spawnParticles() {
1283
- 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) {
1621
+ 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) {
1284
1622
  this.emitting = !0, this.particleCount = this.MAX_PARTICLES;
1285
1623
  return;
1286
1624
  }
@@ -1289,9 +1627,9 @@ class _ {
1289
1627
  this.particleCount = t;
1290
1628
  let e = 0;
1291
1629
  const i = 500;
1292
- for (let a = 0; a < t; a++)
1293
- if (this.emitParticle(), e++, e >= i || a === t - 1) {
1294
- const r = a - e + 1, n = r * 8, o = r * 4;
1630
+ for (let s = 0; s < t; s++)
1631
+ if (this.emitParticle(), e++, e >= i || s === t - 1) {
1632
+ const r = s - e + 1, n = r * 8, o = r * 4;
1295
1633
  this.device.queue.writeBuffer(
1296
1634
  this.instanceBuffer,
1297
1635
  n * 4,
@@ -1320,11 +1658,11 @@ class _ {
1320
1658
  this.emitter.emitParticle(this.particleData, this.activeParticles, this.particleVelocities);
1321
1659
  const t = this.activeParticles * 8, e = this.activeParticles * 4;
1322
1660
  if (this._simRotMatrix) {
1323
- 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];
1661
+ let i = this.particleData[t], s = this.particleData[t + 1], r = this.particleData[t + 2], n = this.particleVelocities[e], o = this.particleVelocities[e + 1], a = this.particleVelocities[e + 2];
1324
1662
  const l = this._simRotMatrix;
1325
- 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;
1663
+ this.particleData[t] = l[0] * i + l[1] * s + l[2] * r, this.particleData[t + 1] = l[3] * i + l[4] * s + l[5] * r, this.particleData[t + 2] = l[6] * i + l[7] * s + l[8] * r, this.particleVelocities[e] = l[0] * n + l[1] * o + l[2] * a, this.particleVelocities[e + 1] = l[3] * n + l[4] * o + l[5] * a, this.particleVelocities[e + 2] = l[6] * n + l[7] * o + l[8] * a;
1326
1664
  }
1327
- return this._newEmissions.push(
1665
+ 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(
1328
1666
  this.particleData[t],
1329
1667
  this.particleData[t + 1],
1330
1668
  this.particleData[t + 2],
@@ -1339,29 +1677,59 @@ class _ {
1339
1677
  */
1340
1678
  emitFollowerParticle(t, e, i) {
1341
1679
  if (this.activeParticles >= this.particleCount) return !1;
1342
- const a = this.activeParticles * 8, r = t + (this.config.shapeTranslationX || 0), n = e + (this.config.shapeTranslationY || 0), o = i + (this.config.shapeTranslationZ || 0);
1343
- this.particleData[a] = r, this.particleData[a + 1] = n, this.particleData[a + 2] = o;
1344
- const s = this.activeParticles * 4;
1345
- 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;
1680
+ const s = this.activeParticles * 8, r = t + (this.config.emissionTranslationX || 0), n = e + (this.config.emissionTranslationY || 0), o = i + (this.config.emissionTranslationZ || 0);
1681
+ this.particleData[s] = r, this.particleData[s + 1] = n, this.particleData[s + 2] = o;
1682
+ const a = this.activeParticles * 4;
1683
+ return this.emitter.calculateVelocity(r, n, o, this.particleVelocities, a), this.emitter.setParticleColor(this.particleData, s), this.emitter.setParticleLifetime(this.particleData, s), this.activeParticles++, !0;
1346
1684
  }
1347
1685
  updateParticles(t, e) {
1686
+ if (this._particleScript && this._scriptReadbackReady) {
1687
+ this._scriptReadbackReady = !1, this._scriptTime += t, this._scriptFrame++;
1688
+ const o = (this.config.emissionDuration || 0) + (this.config.lifetime || 0);
1689
+ if (o > 0 && this._scriptTime >= o && !this._scriptConfigRestored)
1690
+ 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));
1691
+ else if (!this._scriptConfigRestored) {
1692
+ const a = o > 0 ? Math.ceil(o / 0.016666666666666666) : 0, { configDirty: l, particlesDirty: d } = this._particleScript.execute(
1693
+ t,
1694
+ this._scriptTime,
1695
+ this._scriptFrame,
1696
+ a,
1697
+ this._scriptParticleData,
1698
+ this._scriptVelocityData,
1699
+ this.activeParticles
1700
+ );
1701
+ d && this.activeParticles > 0 && (this.device.queue.writeBuffer(
1702
+ this.instanceBuffer,
1703
+ 0,
1704
+ this._scriptParticleData,
1705
+ 0,
1706
+ this.activeParticles * 8
1707
+ ), this.device.queue.writeBuffer(
1708
+ this.velocityBuffer,
1709
+ 0,
1710
+ this._scriptVelocityData,
1711
+ 0,
1712
+ this.activeParticles * 4
1713
+ )), 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));
1714
+ }
1715
+ }
1348
1716
  this.physics.physicsAccumulator += t;
1349
1717
  const i = performance.now() / 1e3, r = i - this.physics.lastUpdateTime > 1 / this.physics.minUpdatesPerSecond, n = this.activeParticles;
1350
1718
  if (this.emitting)
1351
1719
  if (this.currentEmissionTime += t, this.currentEmissionTime < this.config.emissionDuration) {
1352
1720
  const o = this.activeParticles;
1353
- let s = !1;
1721
+ let a = !1;
1354
1722
  if (this.config.followSystemId) {
1355
1723
  if (this._pendingFollowEmissions.length > 0) {
1356
1724
  const l = this._pendingFollowEmissions.length / 6;
1357
- for (let u = 0; u < l; u++) {
1358
- const d = u * 6;
1725
+ for (let d = 0; d < l; d++) {
1726
+ const u = d * 6;
1359
1727
  if (this.emitFollowerParticle(
1360
- this._pendingFollowEmissions[d],
1361
- this._pendingFollowEmissions[d + 1],
1362
- this._pendingFollowEmissions[d + 2]
1728
+ this._pendingFollowEmissions[u],
1729
+ this._pendingFollowEmissions[u + 1],
1730
+ this._pendingFollowEmissions[u + 2]
1363
1731
  ))
1364
- s = !0;
1732
+ a = !0;
1365
1733
  else
1366
1734
  break;
1367
1735
  }
@@ -1370,31 +1738,31 @@ class _ {
1370
1738
  let l = 0;
1371
1739
  if (this.config.emissionRate >= 1) {
1372
1740
  l = Math.floor(this.config.emissionRate * t);
1373
- const u = this.config.emissionRate * t - l;
1374
- Math.random() < u && (l += 1);
1741
+ const d = this.config.emissionRate * t - l;
1742
+ Math.random() < d && (l += 1);
1375
1743
  } else {
1376
- const u = this.config.emissionRate * t;
1377
- Math.random() < u && (l = 1);
1744
+ const d = this.config.emissionRate * t;
1745
+ Math.random() < d && (l = 1);
1378
1746
  }
1379
1747
  l === 0 && r && this.config.emissionRate > 0 && this.activeParticles < this.particleCount && (l = 1);
1380
- for (let u = 0; u < l && this.emitParticle(); u++)
1381
- s = !0;
1748
+ for (let d = 0; d < l && this.emitParticle(); d++)
1749
+ a = !0;
1382
1750
  }
1383
- if (s) {
1384
- const l = this.activeParticles - o, u = o * 8, d = o * 4;
1751
+ if (a) {
1752
+ const l = this.activeParticles - o, d = o * 8, u = o * 4;
1385
1753
  this.device.queue.writeBuffer(
1386
1754
  this.instanceBuffer,
1387
- u * 4,
1755
+ d * 4,
1388
1756
  // Offset in bytes (float32 = 4 bytes)
1389
1757
  this.particleData,
1390
- u,
1758
+ d,
1391
1759
  l * 8
1392
1760
  ), this.device.queue.writeBuffer(
1393
1761
  this.velocityBuffer,
1394
- d * 4,
1762
+ u * 4,
1395
1763
  // Offset in bytes (float32 = 4 bytes)
1396
1764
  this.particleVelocities,
1397
- d,
1765
+ u,
1398
1766
  l * 4
1399
1767
  );
1400
1768
  }
@@ -1416,7 +1784,17 @@ class _ {
1416
1784
  this.instanceBuffer,
1417
1785
  this.velocityBuffer,
1418
1786
  e
1419
- ), this.physics.lastUpdateTime = i), this.frameCount++ % 300 === 0 && this.readbackAndProcessParticles();
1787
+ ), this.physics.lastUpdateTime = i), this.frameCount++ % 300 === 0 && this.readbackAndProcessParticles(), this._particleScript && this.activeParticles > 0 && !this._scriptReadbackPending && (this._scriptReadbackPending = !0, this.physics.readbackForScript(
1788
+ this.activeParticles,
1789
+ this._scriptParticleData,
1790
+ this._scriptVelocityData,
1791
+ this.instanceBuffer,
1792
+ this.velocityBuffer
1793
+ ).then((o) => {
1794
+ this._scriptReadbackPending = !1, o.shouldUpdate && (this._scriptReadbackReady = !0);
1795
+ }).catch(() => {
1796
+ this._scriptReadbackPending = !1;
1797
+ }));
1420
1798
  }
1421
1799
  async readbackAndProcessParticles() {
1422
1800
  if (!(this.activeParticles <= 0))
@@ -1430,8 +1808,8 @@ class _ {
1430
1808
  )).shouldUpdate) return;
1431
1809
  let e = 0;
1432
1810
  for (let i = 0; i < this.activeParticles; i++) {
1433
- const a = this.particleData[i * 8 + 6], r = this.particleData[i * 8 + 7];
1434
- if (a >= r) {
1811
+ const s = this.particleData[i * 8 + 6], r = this.particleData[i * 8 + 7];
1812
+ if (s >= r) {
1435
1813
  if (this.emitting && this.currentEmissionTime < this.config.emissionDuration && e < this.particleCount) {
1436
1814
  this.respawnParticle(i, e), e++;
1437
1815
  continue;
@@ -1441,8 +1819,8 @@ class _ {
1441
1819
  if (e !== i) {
1442
1820
  const n = i * 8, o = e * 8;
1443
1821
  this.particleData.copyWithin(o, n, n + 8);
1444
- const s = i * 4, l = e * 4;
1445
- this.particleVelocities.copyWithin(l, s, s + 4);
1822
+ const a = i * 4, l = e * 4;
1823
+ this.particleVelocities.copyWithin(l, a, a + 4);
1446
1824
  }
1447
1825
  e++;
1448
1826
  }
@@ -1461,25 +1839,25 @@ class _ {
1461
1839
  for (let t = 0; t < this.activeParticles; t++) {
1462
1840
  const e = t * 8;
1463
1841
  if (this.config.randomColorEnabled && this.config.randomColors.length > 0) {
1464
- const i = this.config.randomColors, a = i[Math.floor(Math.random() * i.length)];
1465
- this.particleData[e + 3] = a[0], this.particleData[e + 4] = a[1], this.particleData[e + 5] = a[2];
1842
+ const i = this.config.randomColors, s = i[Math.floor(Math.random() * i.length)];
1843
+ this.particleData[e + 3] = s[0], this.particleData[e + 4] = s[1], this.particleData[e + 5] = s[2];
1466
1844
  } 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]);
1467
1845
  }
1468
1846
  this.activeParticles > 0 && this.device.queue.writeBuffer(this.instanceBuffer, 0, this.particleData, 0, this.activeParticles * 8);
1469
1847
  }
1470
1848
  updateParticleVelocities() {
1471
1849
  for (let t = 0; t < this.activeParticles; t++) {
1472
- 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(
1473
- o * o + s * s + l * l
1850
+ const e = t * 8, i = t * 4, s = this.particleData[e], r = this.particleData[e + 1], n = this.particleData[e + 2], o = this.particleVelocities[i], a = this.particleVelocities[i + 1], l = this.particleVelocities[i + 2], d = Math.sqrt(
1851
+ o * o + a * a + l * l
1474
1852
  );
1475
- if (u > 1e-3) {
1476
- const d = this.config.particleSpeed * 2;
1477
- this.particleVelocities[i] = o / u * d, this.particleVelocities[i + 1] = s / u * d, this.particleVelocities[i + 2] = l / u * d;
1853
+ if (d > 1e-3) {
1854
+ const u = this.config.particleSpeed * 2;
1855
+ this.particleVelocities[i] = o / d * u, this.particleVelocities[i + 1] = a / d * u, this.particleVelocities[i + 2] = l / d * u;
1478
1856
  } else {
1479
- const d = Math.sqrt(a * a + r * r + n * n);
1480
- if (d > 1e-3) {
1857
+ const u = Math.sqrt(s * s + r * r + n * n);
1858
+ if (u > 1e-3) {
1481
1859
  const f = this.config.particleSpeed * 2;
1482
- this.particleVelocities[i] = a / d * f, this.particleVelocities[i + 1] = r / d * f, this.particleVelocities[i + 2] = n / d * f;
1860
+ this.particleVelocities[i] = s / u * f, this.particleVelocities[i + 1] = r / u * f, this.particleVelocities[i + 2] = n / u * f;
1483
1861
  } else
1484
1862
  this.particleVelocities[i] = 0, this.particleVelocities[i + 1] = this.config.particleSpeed * 2, this.particleVelocities[i + 2] = 0;
1485
1863
  }
@@ -1508,7 +1886,7 @@ class _ {
1508
1886
  * Call this when the system is no longer needed.
1509
1887
  */
1510
1888
  destroy() {
1511
- 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;
1889
+ 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;
1512
1890
  }
1513
1891
  setGravity(t) {
1514
1892
  this.physics.setGravity(t);
@@ -1517,27 +1895,27 @@ class _ {
1517
1895
  this.physics.setAttractor(t, e);
1518
1896
  }
1519
1897
  setConfinement(t) {
1520
- const e = t.space === "local" ? [this.config.shapeTranslationX || 0, this.config.shapeTranslationY || 0, this.config.shapeTranslationZ || 0] : [0, 0, 0];
1898
+ const e = t.space === "local" ? [this.config.emissionTranslationX || 0, this.config.emissionTranslationY || 0, this.config.emissionTranslationZ || 0] : [0, 0, 0];
1521
1899
  this.physics.setConfinement({ ...t, center: e });
1522
1900
  }
1523
1901
  setSoftBoundary(t) {
1524
1902
  this.physics.setSoftBoundary(t);
1525
1903
  }
1526
1904
  }
1527
- class me {
1905
+ class Me {
1528
1906
  constructor(t) {
1529
1907
  this.device = t, this.particleSystems = [], this.activeSystemIndex = 0, this.systemCounter = 1, this.onSystemCreated = null;
1530
1908
  }
1531
1909
  createParticleSystem(t = {}) {
1532
- const e = this.systemCounter++, i = t.name || `System ${e + 1}`, a = {
1910
+ const e = this.systemCounter++, i = t.name || `System ${e + 1}`, s = {
1533
1911
  ...t,
1534
1912
  name: i,
1535
1913
  id: e
1536
- }, r = new _(this.device, a);
1914
+ }, r = new A(this.device, s);
1537
1915
  return this.particleSystems.push({
1538
1916
  system: r,
1539
- config: a
1540
- }), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e, a), e;
1917
+ config: s
1918
+ }), this.particleSystems.length === 1 && (this.activeSystemIndex = 0), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(e, s), e;
1541
1919
  }
1542
1920
  getActiveSystem() {
1543
1921
  return this.particleSystems.length === 0 ? null : this.particleSystems[this.activeSystemIndex].system;
@@ -1564,8 +1942,8 @@ class me {
1564
1942
  const e = this.particleSystems[t].config;
1565
1943
  this.particleSystems[t].system.destroy(), this.particleSystems.splice(t, 1);
1566
1944
  const i = e.id;
1567
- for (const { config: a } of this.particleSystems)
1568
- a.followSystemId === i && (a.followSystemId = null);
1945
+ for (const { config: s } of this.particleSystems)
1946
+ s.followSystemId === i && (s.followSystemId = null);
1569
1947
  return this.particleSystems.length === 0 ? this.activeSystemIndex = 0 : t <= this.activeSystemIndex && (this.activeSystemIndex = Math.max(0, this.activeSystemIndex - 1)), !0;
1570
1948
  }
1571
1949
  return !1;
@@ -1577,21 +1955,21 @@ class me {
1577
1955
  updateAllSystems(t) {
1578
1956
  const e = this.device.createCommandEncoder({ label: "BatchedPhysicsEncoder" });
1579
1957
  let i = !1;
1580
- for (const { system: a, config: r } of this.particleSystems) {
1958
+ for (const { system: s, config: r } of this.particleSystems) {
1581
1959
  if (r.hidden || r.followSystemId) continue;
1582
- const n = a.activeParticles > 0;
1583
- a.updateParticles(t, e), (n || a.activeParticles > 0) && (i = !0);
1960
+ const n = s.activeParticles > 0;
1961
+ s.updateParticles(t, e), (n || s.activeParticles > 0) && (i = !0);
1584
1962
  }
1585
- for (const { system: a, config: r } of this.particleSystems) {
1963
+ for (const { system: s, config: r } of this.particleSystems) {
1586
1964
  if (r.hidden || !r.followSystemId) continue;
1587
1965
  const n = this.getSystemById(r.followSystemId);
1588
- n && (a._pendingFollowEmissions = n.system._newEmissions);
1589
- const o = a.activeParticles > 0;
1590
- a.updateParticles(t, e), (o || a.activeParticles > 0) && (i = !0);
1966
+ n && (s._pendingFollowEmissions = n.system._newEmissions);
1967
+ const o = s.activeParticles > 0;
1968
+ s.updateParticles(t, e), (o || s.activeParticles > 0) && (i = !0);
1591
1969
  }
1592
1970
  i && this.device.queue.submit([e.finish()]);
1593
- for (const { system: a } of this.particleSystems)
1594
- a._newEmissions.length = 0, a._pendingFollowEmissions = a._emptyEmissions;
1971
+ for (const { system: s } of this.particleSystems)
1972
+ s._newEmissions.length = 0, s._pendingFollowEmissions = s._emptyEmissions;
1595
1973
  }
1596
1974
  getSystemsList() {
1597
1975
  return this.particleSystems.map(({ config: t }, e) => ({
@@ -1618,40 +1996,40 @@ class me {
1618
1996
  return console.error("Invalid scene data provided"), !1;
1619
1997
  try {
1620
1998
  this.particleSystems = [], this.systemCounter = 1;
1621
- for (const a of t.systems) {
1999
+ for (const s of t.systems) {
1622
2000
  const r = this.systemCounter++, n = {
1623
- ...a,
2001
+ ...s,
1624
2002
  id: r
1625
- }, o = new _(this.device, n);
2003
+ }, o = new A(this.device, n);
1626
2004
  this.particleSystems.push({
1627
2005
  system: o,
1628
2006
  config: n
1629
2007
  });
1630
2008
  }
1631
2009
  const i = {};
1632
- t.systems.forEach((a, r) => {
1633
- i[a.id] = this.particleSystems[r].config.id;
2010
+ t.systems.forEach((s, r) => {
2011
+ i[s.id] = this.particleSystems[r].config.id;
1634
2012
  });
1635
- for (const { config: a } of this.particleSystems)
1636
- a.followSystemId && i[a.followSystemId] !== void 0 && (a.followSystemId = i[a.followSystemId]);
2013
+ for (const { config: s } of this.particleSystems)
2014
+ s.followSystemId && i[s.followSystemId] !== void 0 && (s.followSystemId = i[s.followSystemId]);
1637
2015
  t.activeSystemIndex !== void 0 && t.activeSystemIndex >= 0 && t.activeSystemIndex < this.particleSystems.length ? this.activeSystemIndex = t.activeSystemIndex : this.activeSystemIndex = 0;
1638
- for (const { system: a, config: r } of this.particleSystems)
2016
+ for (const { system: s, config: r } of this.particleSystems)
1639
2017
  if (r.glbModelEnabled)
1640
2018
  try {
1641
2019
  let n = null;
1642
2020
  if (r.glbModelData)
1643
- n = V(r.glbModelData);
2021
+ n = O(r.glbModelData);
1644
2022
  else if (r.glbFileName) {
1645
2023
  const o = await fetch(`/${r.glbFileName}`);
1646
2024
  o.ok ? n = await o.arrayBuffer() : console.warn(`GLB file not found: ${r.glbFileName}`);
1647
2025
  }
1648
2026
  if (n) {
1649
- 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))
2027
+ if (await s.setGLBModel(n), r.animationIndex !== void 0 && s.glbAnimator && s.glbAnimator.setAnimation(r.animationIndex), r.animationSpeed !== void 0 && s.glbAnimator && (s.glbAnimator.speed = r.animationSpeed), r.animationLoop !== void 0 && s.glbAnimator && (s.glbAnimator.loop = r.animationLoop), r.useGlbTexture && (r.textureEnabled = !0), r.useGlbTexture && ((e = s.glbMeshData) != null && e.hasBaseColorTexture))
1650
2028
  try {
1651
- const { extractGLBTexture: o } = await Promise.resolve().then(() => U), s = await o(n);
1652
- if (s) {
1653
- const l = await createImageBitmap(s.imageBlob);
1654
- await a.setTexture(l), console.log(`GLB embedded texture restored for ${r.name}`);
2029
+ const { extractGLBTexture: o } = await Promise.resolve().then(() => D), a = await o(n);
2030
+ if (a) {
2031
+ const l = await createImageBitmap(a.imageBlob);
2032
+ await s.setTexture(l), console.log(`GLB embedded texture restored for ${r.name}`);
1655
2033
  }
1656
2034
  } catch (o) {
1657
2035
  console.warn(`Failed to restore GLB texture for ${r.name}:`, o), r.useGlbTexture = !1;
@@ -1661,20 +2039,20 @@ class me {
1661
2039
  } catch (n) {
1662
2040
  console.warn(`Failed to load GLB for ${r.name}:`, n), r.glbModelEnabled = !1;
1663
2041
  }
1664
- for (const { system: a, config: r } of this.particleSystems)
2042
+ for (const { system: s, config: r } of this.particleSystems)
1665
2043
  if (r.textureEnabled && !r.glbModelEnabled && r.textureImageData)
1666
2044
  try {
1667
2045
  const n = new Image();
1668
- await new Promise((s, l) => {
1669
- n.onload = s, n.onerror = l, n.src = r.textureImageData;
2046
+ await new Promise((a, l) => {
2047
+ n.onload = a, n.onerror = l, n.src = r.textureImageData;
1670
2048
  });
1671
2049
  const o = await createImageBitmap(n);
1672
- await a.setTexture(o);
2050
+ await s.setTexture(o);
1673
2051
  } catch (n) {
1674
2052
  console.warn(`Failed to restore texture for ${r.name}:`, n), r.textureEnabled = !1;
1675
2053
  }
1676
- for (const { system: a, config: r } of this.particleSystems)
1677
- 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}`);
2054
+ for (const { system: s, config: r } of this.particleSystems)
2055
+ s.updateAppearanceUniform(), (r.particleShapeRotationX || r.particleShapeRotationY || r.particleShapeRotationZ) && console.log(`[replaceSystems] ${r.name}: glbRotation XYZ = ${r.particleShapeRotationX}, ${r.particleShapeRotationY}, ${r.particleShapeRotationZ} | glbModelEnabled=${r.glbModelEnabled} | glbMeshData=${!!s.glbMeshData}`);
1678
2056
  return this.respawnAllSystems(), !0;
1679
2057
  } catch (i) {
1680
2058
  return console.error("Error replacing systems:", i), !1;
@@ -1693,91 +2071,91 @@ class me {
1693
2071
  return console.error("Invalid scene data provided"), !1;
1694
2072
  try {
1695
2073
  for (const n of t.systems) {
1696
- const o = this.systemCounter++, s = {
2074
+ const o = this.systemCounter++, a = {
1697
2075
  ...n,
1698
2076
  id: o,
1699
- // Apply world-space offset to shape translation
1700
- shapeTranslationX: (n.shapeTranslationX || 0) + e[0],
1701
- shapeTranslationY: (n.shapeTranslationY || 0) + e[1],
1702
- shapeTranslationZ: (n.shapeTranslationZ || 0) + e[2]
2077
+ // Apply world-space offset to emission translation
2078
+ emissionTranslationX: (n.emissionTranslationX || 0) + e[0],
2079
+ emissionTranslationY: (n.emissionTranslationY || 0) + e[1],
2080
+ emissionTranslationZ: (n.emissionTranslationZ || 0) + e[2]
1703
2081
  };
1704
- n.attractorEnabled && n.attractorPosition && (s.attractorPosition = [
2082
+ n.attractorEnabled && n.attractorPosition && (a.attractorPosition = [
1705
2083
  n.attractorPosition[0] + e[0],
1706
2084
  n.attractorPosition[1] + e[1],
1707
2085
  n.attractorPosition[2] + e[2]
1708
2086
  ]);
1709
- const l = new _(this.device, s);
2087
+ const l = new A(this.device, a);
1710
2088
  this.particleSystems.push({
1711
2089
  system: l,
1712
- config: s
1713
- }), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(o, s);
2090
+ config: a
2091
+ }), this.onSystemCreated && typeof this.onSystemCreated == "function" && this.onSystemCreated(o, a);
1714
2092
  }
1715
- const a = this.particleSystems.length - t.systems.length, r = {};
2093
+ const s = this.particleSystems.length - t.systems.length, r = {};
1716
2094
  t.systems.forEach((n, o) => {
1717
- r[n.id] = this.particleSystems[a + o].config.id;
2095
+ r[n.id] = this.particleSystems[s + o].config.id;
1718
2096
  });
1719
- for (let n = a; n < this.particleSystems.length; n++) {
2097
+ for (let n = s; n < this.particleSystems.length; n++) {
1720
2098
  const { config: o } = this.particleSystems[n];
1721
2099
  o.followSystemId && r[o.followSystemId] !== void 0 && (o.followSystemId = r[o.followSystemId]);
1722
2100
  }
1723
2101
  for (const { system: n, config: o } of this.particleSystems)
1724
2102
  if (o.glbModelEnabled && !n.glbMeshData)
1725
2103
  try {
1726
- let s = null;
2104
+ let a = null;
1727
2105
  if (o.glbModelData)
1728
- s = V(o.glbModelData);
2106
+ a = O(o.glbModelData);
1729
2107
  else if (o.glbFileName) {
1730
2108
  const l = await fetch(`/${o.glbFileName}`);
1731
- l.ok ? s = await l.arrayBuffer() : console.warn(`GLB file not found: ${o.glbFileName}`);
2109
+ l.ok ? a = await l.arrayBuffer() : console.warn(`GLB file not found: ${o.glbFileName}`);
1732
2110
  }
1733
- if (s) {
1734
- 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))
2111
+ if (a) {
2112
+ if (await n.setGLBModel(a), 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))
1735
2113
  try {
1736
- const { extractGLBTexture: l } = await Promise.resolve().then(() => U), u = await l(s);
1737
- if (u) {
1738
- const d = await createImageBitmap(u.imageBlob);
1739
- await n.setTexture(d), console.log(`GLB embedded texture restored for ${o.name}`);
2114
+ const { extractGLBTexture: l } = await Promise.resolve().then(() => D), d = await l(a);
2115
+ if (d) {
2116
+ const u = await createImageBitmap(d.imageBlob);
2117
+ await n.setTexture(u), console.log(`GLB embedded texture restored for ${o.name}`);
1740
2118
  }
1741
2119
  } catch (l) {
1742
2120
  console.warn(`Failed to restore GLB texture for ${o.name}:`, l), o.useGlbTexture = !1;
1743
2121
  }
1744
2122
  } else
1745
2123
  o.glbModelEnabled = !1;
1746
- } catch (s) {
1747
- console.warn(`Failed to load GLB for ${o.name}:`, s), o.glbModelEnabled = !1;
2124
+ } catch (a) {
2125
+ console.warn(`Failed to load GLB for ${o.name}:`, a), o.glbModelEnabled = !1;
1748
2126
  }
1749
2127
  for (const { system: n, config: o } of this.particleSystems)
1750
2128
  if (o.textureEnabled && !o.glbModelEnabled && o.textureImageData && !n._textureRestored)
1751
2129
  try {
1752
- const s = new Image();
1753
- await new Promise((u, d) => {
1754
- s.onload = u, s.onerror = d, s.src = o.textureImageData;
2130
+ const a = new Image();
2131
+ await new Promise((d, u) => {
2132
+ a.onload = d, a.onerror = u, a.src = o.textureImageData;
1755
2133
  });
1756
- const l = await createImageBitmap(s);
2134
+ const l = await createImageBitmap(a);
1757
2135
  await n.setTexture(l), n._textureRestored = !0;
1758
- } catch (s) {
1759
- console.warn(`Failed to restore texture for ${o.name}:`, s), o.textureEnabled = !1;
2136
+ } catch (a) {
2137
+ console.warn(`Failed to restore texture for ${o.name}:`, a), o.textureEnabled = !1;
1760
2138
  }
1761
2139
  return !0;
1762
- } catch (a) {
1763
- return console.error("Error adding systems:", a), !1;
2140
+ } catch (s) {
2141
+ return console.error("Error adding systems:", s), !1;
1764
2142
  }
1765
2143
  }
1766
2144
  }
1767
- async function ye(c) {
2145
+ async function Re(c) {
1768
2146
  if (!c)
1769
2147
  throw new Error("canvas is required for initWebGPU()");
1770
2148
  if (!navigator.gpu)
1771
2149
  throw new Error("WebGPU not supported on this browser.");
1772
- const t = c.getContext("webgpu"), i = await (await navigator.gpu.requestAdapter()).requestDevice(), a = navigator.gpu.getPreferredCanvasFormat();
2150
+ const t = c.getContext("webgpu"), i = await (await navigator.gpu.requestAdapter()).requestDevice(), s = navigator.gpu.getPreferredCanvasFormat();
1773
2151
  return t.configure({
1774
2152
  device: i,
1775
- format: a,
2153
+ format: s,
1776
2154
  alphaMode: "premultiplied"
1777
- }), { device: i, context: t, format: a, canvas: c };
2155
+ }), { device: i, context: t, format: s, canvas: c };
1778
2156
  }
1779
- function ge(c, t, e, i) {
1780
- const a = c.createTexture({
2157
+ function we(c, t, e, i) {
2158
+ const s = c.createTexture({
1781
2159
  size: [e, i],
1782
2160
  format: t,
1783
2161
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
@@ -1796,16 +2174,16 @@ function ge(c, t, e, i) {
1796
2174
  mipLevelCount: 1,
1797
2175
  sampleCount: 1
1798
2176
  });
1799
- return { sceneTexture: a, bloomTexA: r, bloomTexB: n };
2177
+ return { sceneTexture: s, bloomTexA: r, bloomTexB: n };
1800
2178
  }
1801
- function be(c, t, e) {
2179
+ function Be(c, t, e) {
1802
2180
  return c.createTexture({
1803
2181
  size: [t, e],
1804
2182
  format: "depth24plus",
1805
2183
  usage: GPUTextureUsage.RENDER_ATTACHMENT
1806
2184
  });
1807
2185
  }
1808
- function E(c, t, e) {
2186
+ function C(c, t, e) {
1809
2187
  const i = c.createBuffer({
1810
2188
  size: t.byteLength,
1811
2189
  usage: e,
@@ -1813,7 +2191,7 @@ function E(c, t, e) {
1813
2191
  });
1814
2192
  return new t.constructor(i.getMappedRange()).set(t), i.unmap(), i;
1815
2193
  }
1816
- const j = `
2194
+ const Y = `
1817
2195
  struct Uniforms {
1818
2196
  transform: mat4x4<f32>,
1819
2197
  cameraPosition: vec3<f32>,
@@ -2143,7 +2521,7 @@ const j = `
2143
2521
  return vec4<f32>(input.color, alpha);
2144
2522
  }
2145
2523
  }
2146
- `, N = `
2524
+ `, q = `
2147
2525
  struct BloomUniforms {
2148
2526
  direction: vec2<f32>,
2149
2527
  resolution: vec2<f32>,
@@ -2203,7 +2581,7 @@ const j = `
2203
2581
 
2204
2582
  return result / totalWeight * 1.1;
2205
2583
  }
2206
- `, X = `
2584
+ `, Z = `
2207
2585
  struct BloomIntensityUniforms {
2208
2586
  intensity: f32,
2209
2587
  color: vec3<f32>,
@@ -2249,7 +2627,7 @@ const j = `
2249
2627
 
2250
2628
  return vec4<f32>(originalColor.rgb + (mappedBloom * bloomUniforms.intensity), originalColor.a);
2251
2629
  }
2252
- `, k = `
2630
+ `, $ = `
2253
2631
  struct BloomIntensityUniforms {
2254
2632
  intensity: f32,
2255
2633
  color: vec3<f32>,
@@ -2290,7 +2668,7 @@ const j = `
2290
2668
  fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
2291
2669
  return textureSample(originalTexture, texSampler, input.texCoord);
2292
2670
  }
2293
- `, oe = `
2671
+ `, ye = `
2294
2672
  struct PhysicsUniforms {
2295
2673
  deltaTime: f32,
2296
2674
  particleSpeed: f32,
@@ -2500,7 +2878,7 @@ const j = `
2500
2878
  particleBuffer[baseIndex + 1u] = newPos.y;
2501
2879
  particleBuffer[baseIndex + 2u] = newPos.z;
2502
2880
  }
2503
- `, le = `
2881
+ `, ge = `
2504
2882
  @group(0) @binding(0) var<storage, read> restData: array<f32>;
2505
2883
  @group(0) @binding(1) var<storage, read> jointWeightsData: array<f32>;
2506
2884
  @group(0) @binding(2) var<storage, read> jointIndicesData: array<u32>;
@@ -2556,15 +2934,15 @@ const j = `
2556
2934
  outputData[outBase + 6u] = uv_u;
2557
2935
  outputData[outBase + 7u] = uv_v;
2558
2936
  }
2559
- `, Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2937
+ `, H = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2560
2938
  __proto__: null,
2561
- blurShader: N,
2562
- compositeShader: X,
2563
- directRenderShader: k,
2564
- particlePhysicsShader: oe,
2565
- particleShader: j,
2566
- skinningComputeShader: le
2567
- }, Symbol.toStringTag, { value: "Module" })), ce = `
2939
+ blurShader: q,
2940
+ compositeShader: Z,
2941
+ directRenderShader: $,
2942
+ particlePhysicsShader: ye,
2943
+ particleShader: Y,
2944
+ skinningComputeShader: ge
2945
+ }, Symbol.toStringTag, { value: "Module" })), be = `
2568
2946
  struct Uniforms {
2569
2947
  transform: mat4x4<f32>,
2570
2948
  cameraPosition: vec3<f32>,
@@ -2626,7 +3004,7 @@ const j = `
2626
3004
 
2627
3005
  return finalColor;
2628
3006
  }
2629
- `, ue = `
3007
+ `, Se = `
2630
3008
  struct Uniforms {
2631
3009
  transform: mat4x4<f32>,
2632
3010
  cameraPosition: vec3<f32>,
@@ -2711,9 +3089,14 @@ const j = `
2711
3089
 
2712
3090
  // Determine particle color
2713
3091
  var finalColor = input.particleColor;
2714
- if (appearance.colorTransitionEnabled > 0.5) {
3092
+ if (appearance.colorTransitionEnabled > 1.5) {
3093
+ // Random color mode: use per-particle color from instance data
3094
+ finalColor = input.particleColor;
3095
+ } else if (appearance.colorTransitionEnabled > 0.5) {
3096
+ // Color transition mode: interpolate from start to end color over lifetime
2715
3097
  finalColor = mix(appearance.startColor, appearance.endColor, lifeRatio);
2716
3098
  } else {
3099
+ // Single color mode
2717
3100
  finalColor = appearance.singleColor;
2718
3101
  }
2719
3102
 
@@ -2857,7 +3240,7 @@ const j = `
2857
3240
  return finalColor;
2858
3241
  }
2859
3242
  `;
2860
- function Se(c) {
3243
+ function Te(c) {
2861
3244
  const t = c.createBindGroupLayout({
2862
3245
  entries: [
2863
3246
  {
@@ -2922,7 +3305,7 @@ function Se(c) {
2922
3305
  buffer: { type: "uniform" }
2923
3306
  }
2924
3307
  ]
2925
- }), a = c.createBindGroupLayout({
3308
+ }), s = c.createBindGroupLayout({
2926
3309
  entries: [
2927
3310
  {
2928
3311
  binding: 0,
@@ -2940,35 +3323,35 @@ function Se(c) {
2940
3323
  particleBindGroupLayout: t,
2941
3324
  bloomBindGroupLayout: e,
2942
3325
  compositeBindGroupLayout: i,
2943
- object3dBindGroupLayout: a
3326
+ object3dBindGroupLayout: s
2944
3327
  };
2945
3328
  }
2946
- function xe(c, t, e, i = {}) {
2947
- const { depthCompare: a } = i, r = a || "less", {
3329
+ function Ce(c, t, e, i = {}) {
3330
+ const { depthCompare: s } = i, r = s || "less", {
2948
3331
  particleBindGroupLayout: n,
2949
3332
  bloomBindGroupLayout: o,
2950
- compositeBindGroupLayout: s,
3333
+ compositeBindGroupLayout: a,
2951
3334
  object3dBindGroupLayout: l
2952
- } = e, u = c.createPipelineLayout({
3335
+ } = e, d = c.createPipelineLayout({
2953
3336
  bindGroupLayouts: [n]
2954
- }), d = c.createPipelineLayout({
3337
+ }), u = c.createPipelineLayout({
2955
3338
  bindGroupLayouts: [o]
2956
3339
  }), f = c.createPipelineLayout({
2957
- bindGroupLayouts: [s]
3340
+ bindGroupLayouts: [a]
2958
3341
  }), h = c.createShaderModule({
2959
- code: j
3342
+ code: Y
2960
3343
  }), p = c.createShaderModule({
2961
- code: N
3344
+ code: q
2962
3345
  }), m = c.createShaderModule({
2963
- code: X
3346
+ code: Z
2964
3347
  }), b = c.createShaderModule({
2965
- code: k
3348
+ code: $
2966
3349
  }), S = c.createShaderModule({
2967
- code: ce
3350
+ code: be
2968
3351
  }), y = c.createShaderModule({
2969
- code: ue
2970
- }), P = c.createRenderPipeline({
2971
- layout: u,
3352
+ code: Se
3353
+ }), _ = c.createRenderPipeline({
3354
+ layout: d,
2972
3355
  vertex: {
2973
3356
  module: h,
2974
3357
  entryPoint: "vs_main",
@@ -3059,7 +3442,7 @@ function xe(c, t, e, i = {}) {
3059
3442
  format: "depth24plus"
3060
3443
  }
3061
3444
  }), g = c.createRenderPipeline({
3062
- layout: u,
3445
+ layout: d,
3063
3446
  vertex: {
3064
3447
  module: h,
3065
3448
  entryPoint: "vs_main",
@@ -3141,7 +3524,7 @@ function xe(c, t, e, i = {}) {
3141
3524
  format: "depth24plus"
3142
3525
  }
3143
3526
  }), x = c.createRenderPipeline({
3144
- layout: d,
3527
+ layout: u,
3145
3528
  vertex: {
3146
3529
  module: p,
3147
3530
  entryPoint: "vs_main"
@@ -3156,7 +3539,7 @@ function xe(c, t, e, i = {}) {
3156
3539
  primitive: {
3157
3540
  topology: "triangle-list"
3158
3541
  }
3159
- }), M = c.createRenderPipeline({
3542
+ }), P = c.createRenderPipeline({
3160
3543
  layout: f,
3161
3544
  vertex: {
3162
3545
  module: m,
@@ -3184,7 +3567,7 @@ function xe(c, t, e, i = {}) {
3184
3567
  primitive: {
3185
3568
  topology: "triangle-list"
3186
3569
  }
3187
- }), R = c.createRenderPipeline({
3570
+ }), M = c.createRenderPipeline({
3188
3571
  layout: f,
3189
3572
  vertex: {
3190
3573
  module: b,
@@ -3212,10 +3595,10 @@ function xe(c, t, e, i = {}) {
3212
3595
  primitive: {
3213
3596
  topology: "triangle-list"
3214
3597
  }
3215
- }), B = c.createPipelineLayout({
3598
+ }), w = c.createPipelineLayout({
3216
3599
  bindGroupLayouts: [l]
3217
- }), T = c.createRenderPipeline({
3218
- layout: B,
3600
+ }), B = c.createRenderPipeline({
3601
+ layout: w,
3219
3602
  vertex: {
3220
3603
  module: S,
3221
3604
  entryPoint: "vs_main",
@@ -3269,8 +3652,8 @@ function xe(c, t, e, i = {}) {
3269
3652
  depthCompare: r,
3270
3653
  format: "depth24plus"
3271
3654
  }
3272
- }), w = c.createRenderPipeline({
3273
- layout: u,
3655
+ }), R = c.createRenderPipeline({
3656
+ layout: d,
3274
3657
  vertex: {
3275
3658
  module: y,
3276
3659
  entryPoint: "vs_main",
@@ -3373,26 +3756,26 @@ function xe(c, t, e, i = {}) {
3373
3756
  }
3374
3757
  });
3375
3758
  return {
3376
- particlePipeline: P,
3759
+ particlePipeline: _,
3377
3760
  particleDepthWritePipeline: g,
3378
3761
  blurPipeline: x,
3379
- compositePipeline: M,
3380
- directRenderPipeline: R,
3381
- object3dPipeline: T,
3382
- glbMeshPipeline: w
3762
+ compositePipeline: P,
3763
+ directRenderPipeline: M,
3764
+ object3dPipeline: B,
3765
+ glbMeshPipeline: R
3383
3766
  };
3384
3767
  }
3385
- function ve(c, t, e, i) {
3768
+ function Ee(c, t, e, i) {
3386
3769
  const {
3387
- uniformBuffer: a,
3770
+ uniformBuffer: s,
3388
3771
  appearanceUniformBuffer: r,
3389
3772
  horizontalBlurUniformBuffer: n,
3390
3773
  verticalBlurUniformBuffer: o,
3391
- bloomIntensityBuffer: s
3774
+ bloomIntensityBuffer: a
3392
3775
  } = e, {
3393
3776
  sceneTexture: l,
3394
- bloomTexA: u,
3395
- bloomTexB: d
3777
+ bloomTexA: d,
3778
+ bloomTexB: u
3396
3779
  } = i, f = c.createBindGroup({
3397
3780
  layout: c.createBindGroupLayout({
3398
3781
  entries: [
@@ -3411,7 +3794,7 @@ function ve(c, t, e, i) {
3411
3794
  entries: [
3412
3795
  {
3413
3796
  binding: 0,
3414
- resource: { buffer: a }
3797
+ resource: { buffer: s }
3415
3798
  },
3416
3799
  {
3417
3800
  binding: 1,
@@ -3479,7 +3862,7 @@ function ve(c, t, e, i) {
3479
3862
  },
3480
3863
  {
3481
3864
  binding: 1,
3482
- resource: u.createView()
3865
+ resource: d.createView()
3483
3866
  },
3484
3867
  {
3485
3868
  binding: 2,
@@ -3522,11 +3905,11 @@ function ve(c, t, e, i) {
3522
3905
  },
3523
3906
  {
3524
3907
  binding: 2,
3525
- resource: d.createView()
3908
+ resource: u.createView()
3526
3909
  },
3527
3910
  {
3528
3911
  binding: 3,
3529
- resource: { buffer: s }
3912
+ resource: { buffer: a }
3530
3913
  }
3531
3914
  ]
3532
3915
  }), b = c.createBindGroup({
@@ -3565,11 +3948,11 @@ function ve(c, t, e, i) {
3565
3948
  },
3566
3949
  {
3567
3950
  binding: 2,
3568
- resource: d.createView()
3951
+ resource: u.createView()
3569
3952
  },
3570
3953
  {
3571
3954
  binding: 3,
3572
- resource: { buffer: s }
3955
+ resource: { buffer: a }
3573
3956
  }
3574
3957
  ]
3575
3958
  });
@@ -3581,7 +3964,7 @@ function ve(c, t, e, i) {
3581
3964
  directRenderBindGroup: b
3582
3965
  };
3583
3966
  }
3584
- function Pe(c) {
3967
+ function Ae(c) {
3585
3968
  return c.createSampler({
3586
3969
  magFilter: "linear",
3587
3970
  minFilter: "linear",
@@ -3591,7 +3974,7 @@ function Pe(c) {
3591
3974
  maxAnisotropy: 16
3592
3975
  });
3593
3976
  }
3594
- function de() {
3977
+ function xe() {
3595
3978
  const c = new Float32Array([
3596
3979
  // Front face (z = 0.5)
3597
3980
  -0.5,
@@ -3789,18 +4172,18 @@ function de() {
3789
4172
  ]);
3790
4173
  return { vertices: c, indices: t };
3791
4174
  }
3792
- function fe(c = 16, t = 16) {
4175
+ function ve(c = 16, t = 16) {
3793
4176
  const e = [], i = [];
3794
- for (let a = 0; a <= c; a++) {
3795
- const r = a * Math.PI / c, n = Math.sin(r), o = Math.cos(r);
3796
- for (let s = 0; s <= t; s++) {
3797
- const l = s * 2 * Math.PI / t, u = Math.sin(l), f = Math.cos(l) * n, h = o, p = u * n;
4177
+ for (let s = 0; s <= c; s++) {
4178
+ const r = s * Math.PI / c, n = Math.sin(r), o = Math.cos(r);
4179
+ for (let a = 0; a <= t; a++) {
4180
+ const l = a * 2 * Math.PI / t, d = Math.sin(l), f = Math.cos(l) * n, h = o, p = d * n;
3798
4181
  e.push(f * 0.5, h * 0.5, p * 0.5), e.push(f, h, p);
3799
4182
  }
3800
4183
  }
3801
- for (let a = 0; a < c; a++)
4184
+ for (let s = 0; s < c; s++)
3802
4185
  for (let r = 0; r < t; r++) {
3803
- const n = a * (t + 1) + r, o = n + t + 1;
4186
+ const n = s * (t + 1) + r, o = n + t + 1;
3804
4187
  i.push(n), i.push(o), i.push(n + 1), i.push(o), i.push(o + 1), i.push(n + 1);
3805
4188
  }
3806
4189
  return {
@@ -3808,17 +4191,17 @@ function fe(c = 16, t = 16) {
3808
4191
  indices: new Uint16Array(i)
3809
4192
  };
3810
4193
  }
3811
- class he {
3812
- constructor(t, e, i, a, r) {
3813
- this.id = t, this.type = e, this.position = i, this.scale = a, this.color = r, this.rotation = [0, 0, 0];
4194
+ class _e {
4195
+ constructor(t, e, i, s, r) {
4196
+ this.id = t, this.type = e, this.position = i, this.scale = s, this.color = r, this.rotation = [0, 0, 0];
3814
4197
  }
3815
4198
  /**
3816
4199
  * Get the model matrix for this object
3817
4200
  */
3818
4201
  getModelMatrix() {
3819
- 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);
3820
- let l = a;
3821
- return l = this.multiplyMatrices(l, o), l = this.multiplyMatrices(l, n), l = this.multiplyMatrices(l, r), l = this.multiplyMatrices(l, s), l;
4202
+ const { position: t, scale: e, rotation: i } = this, s = this.createTranslationMatrix(t), r = this.createRotationMatrixX(i[0]), n = this.createRotationMatrixY(i[1]), o = this.createRotationMatrixZ(i[2]), a = this.createScaleMatrix(e);
4203
+ let l = s;
4204
+ return l = this.multiplyMatrices(l, o), l = this.multiplyMatrices(l, n), l = this.multiplyMatrices(l, r), l = this.multiplyMatrices(l, a), l;
3822
4205
  }
3823
4206
  /**
3824
4207
  * Get the normal matrix (inverse transpose of model matrix)
@@ -3932,17 +4315,17 @@ class he {
3932
4315
  }
3933
4316
  multiplyMatrices(t, e) {
3934
4317
  const i = new Float32Array(16);
3935
- for (let a = 0; a < 4; a++)
4318
+ for (let s = 0; s < 4; s++)
3936
4319
  for (let r = 0; r < 4; r++) {
3937
4320
  let n = 0;
3938
4321
  for (let o = 0; o < 4; o++)
3939
- n += t[a * 4 + o] * e[o * 4 + r];
3940
- i[a * 4 + r] = n;
4322
+ n += t[s * 4 + o] * e[o * 4 + r];
4323
+ i[s * 4 + r] = n;
3941
4324
  }
3942
4325
  return i;
3943
4326
  }
3944
4327
  }
3945
- class Me {
4328
+ class Ie {
3946
4329
  constructor(t) {
3947
4330
  this.device = t, this.objects = [], this.nextId = 0, this.initializeGeometry(), this.onObjectAdded = null, this.onObjectRemoved = null, this.onObjectUpdated = null;
3948
4331
  }
@@ -3950,20 +4333,20 @@ class Me {
3950
4333
  * Initialize geometry buffers for cube and sphere
3951
4334
  */
3952
4335
  initializeGeometry() {
3953
- const t = de(), e = fe(16, 16);
3954
- this.cubeVertexBuffer = E(
4336
+ const t = xe(), e = ve(16, 16);
4337
+ this.cubeVertexBuffer = C(
3955
4338
  this.device,
3956
4339
  t.vertices,
3957
4340
  GPUBufferUsage.VERTEX
3958
- ), this.cubeIndexBuffer = E(
4341
+ ), this.cubeIndexBuffer = C(
3959
4342
  this.device,
3960
4343
  t.indices,
3961
4344
  GPUBufferUsage.INDEX
3962
- ), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer = E(
4345
+ ), this.cubeIndexCount = t.indices.length, this.sphereVertexBuffer = C(
3963
4346
  this.device,
3964
4347
  e.vertices,
3965
4348
  GPUBufferUsage.VERTEX
3966
- ), this.sphereIndexBuffer = E(
4349
+ ), this.sphereIndexBuffer = C(
3967
4350
  this.device,
3968
4351
  e.indices,
3969
4352
  GPUBufferUsage.INDEX
@@ -3977,8 +4360,8 @@ class Me {
3977
4360
  * @param {Array} color - [r, g, b, a] (optional, defaults to white)
3978
4361
  * @returns {Object3D} The created object
3979
4362
  */
3980
- addObject(t, e = [0, 0, 0], i = [1, 1, 1], a = [1, 1, 1, 1]) {
3981
- const r = new he(this.nextId++, t, e, i, a);
4363
+ addObject(t, e = [0, 0, 0], i = [1, 1, 1], s = [1, 1, 1, 1]) {
4364
+ const r = new _e(this.nextId++, t, e, i, s);
3982
4365
  return r.uniformBuffer = this.device.createBuffer({
3983
4366
  size: 192,
3984
4367
  // modelMatrix (64) + normalMatrix (64) + color (16) + padding (48)
@@ -3999,7 +4382,7 @@ class Me {
3999
4382
  * @param {Array} position - [x, y, z]
4000
4383
  */
4001
4384
  updateObjectPosition(t, e) {
4002
- const i = this.objects.find((a) => a.id === t);
4385
+ const i = this.objects.find((s) => s.id === t);
4003
4386
  i && (i.position = e, this.onObjectUpdated && this.onObjectUpdated(i));
4004
4387
  }
4005
4388
  /**
@@ -4008,7 +4391,7 @@ class Me {
4008
4391
  * @param {Array} scale - [sx, sy, sz]
4009
4392
  */
4010
4393
  updateObjectScale(t, e) {
4011
- const i = this.objects.find((a) => a.id === t);
4394
+ const i = this.objects.find((s) => s.id === t);
4012
4395
  i && (i.scale = e, this.onObjectUpdated && this.onObjectUpdated(i));
4013
4396
  }
4014
4397
  /**
@@ -4017,7 +4400,7 @@ class Me {
4017
4400
  * @param {Array} color - [r, g, b, a]
4018
4401
  */
4019
4402
  updateObjectColor(t, e) {
4020
- const i = this.objects.find((a) => a.id === t);
4403
+ const i = this.objects.find((s) => s.id === t);
4021
4404
  i && (i.color = e, this.onObjectUpdated && this.onObjectUpdated(i));
4022
4405
  }
4023
4406
  /**
@@ -4038,78 +4421,78 @@ class Me {
4038
4421
  * @param {Object3D} object
4039
4422
  */
4040
4423
  updateObjectUniforms(t) {
4041
- const e = t.getModelMatrix(), i = t.getNormalMatrix(), a = new Float32Array(t.color);
4042
- this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128, a);
4424
+ const e = t.getModelMatrix(), i = t.getNormalMatrix(), s = new Float32Array(t.color);
4425
+ this.device.queue.writeBuffer(t.uniformBuffer, 0, e), this.device.queue.writeBuffer(t.uniformBuffer, 64, i), this.device.queue.writeBuffer(t.uniformBuffer, 128, s);
4043
4426
  }
4044
4427
  /**
4045
4428
  * Render all objects
4046
4429
  * @param {GPURenderPassEncoder} passEncoder
4047
4430
  * @param {GPUBindGroup} cameraBindGroup - Bind group with camera uniforms
4048
4431
  */
4049
- renderObjects(t, e, i, a) {
4432
+ renderObjects(t, e, i, s) {
4050
4433
  for (const r of this.objects) {
4051
4434
  this.updateObjectUniforms(r);
4052
4435
  const n = this.device.createBindGroup({
4053
4436
  layout: i,
4054
4437
  entries: [
4055
- { binding: 0, resource: { buffer: a } },
4438
+ { binding: 0, resource: { buffer: s } },
4056
4439
  { binding: 1, resource: { buffer: r.uniformBuffer } }
4057
4440
  ]
4058
4441
  });
4059
- let o, s, l;
4442
+ let o, a, l;
4060
4443
  if (r.type === "cube")
4061
- o = this.cubeVertexBuffer, s = this.cubeIndexBuffer, l = this.cubeIndexCount;
4444
+ o = this.cubeVertexBuffer, a = this.cubeIndexBuffer, l = this.cubeIndexCount;
4062
4445
  else if (r.type === "sphere")
4063
- o = this.sphereVertexBuffer, s = this.sphereIndexBuffer, l = this.sphereIndexCount;
4446
+ o = this.sphereVertexBuffer, a = this.sphereIndexBuffer, l = this.sphereIndexCount;
4064
4447
  else
4065
4448
  continue;
4066
- t.setPipeline(e), t.setBindGroup(0, n), t.setVertexBuffer(0, o), t.setIndexBuffer(s, "uint16"), t.drawIndexed(l);
4449
+ t.setPipeline(e), t.setBindGroup(0, n), t.setVertexBuffer(0, o), t.setIndexBuffer(a, "uint16"), t.drawIndexed(l);
4067
4450
  }
4068
4451
  }
4069
4452
  }
4070
- function Re(c) {
4453
+ function Ue(c) {
4071
4454
  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;
4072
4455
  return [t, e, i];
4073
4456
  }
4074
- function we(c) {
4457
+ function ze(c) {
4075
4458
  if (!c) return "#ffffff";
4076
4459
  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");
4077
4460
  return `#${t}${e}${i}`;
4078
4461
  }
4079
- function Be(c, t, e) {
4080
- const i = D([
4462
+ function Fe(c, t, e) {
4463
+ const i = k([
4081
4464
  c[0] - t[0],
4082
4465
  c[1] - t[1],
4083
4466
  c[2] - t[2]
4084
- ]), a = D(L(e, i)), r = L(i, a);
4467
+ ]), s = k(j(e, i)), r = j(i, s);
4085
4468
  return new Float32Array([
4086
- a[0],
4469
+ s[0],
4087
4470
  r[0],
4088
4471
  i[0],
4089
4472
  0,
4090
- a[1],
4473
+ s[1],
4091
4474
  r[1],
4092
4475
  i[1],
4093
4476
  0,
4094
- a[2],
4477
+ s[2],
4095
4478
  r[2],
4096
4479
  i[2],
4097
4480
  0,
4098
- -A(a, c),
4099
- -A(r, c),
4100
- -A(i, c),
4481
+ -I(s, c),
4482
+ -I(r, c),
4483
+ -I(i, c),
4101
4484
  1
4102
4485
  ]);
4103
4486
  }
4104
- function Te(c, t = Math.PI / 4) {
4105
- const a = 1 / Math.tan(t / 2);
4487
+ function De(c, t = Math.PI / 4) {
4488
+ const s = 1 / Math.tan(t / 2);
4106
4489
  return new Float32Array([
4107
- a * c,
4490
+ s * c,
4108
4491
  0,
4109
4492
  0,
4110
4493
  0,
4111
4494
  0,
4112
- a,
4495
+ s,
4113
4496
  0,
4114
4497
  0,
4115
4498
  0,
@@ -4122,39 +4505,39 @@ function Te(c, t = Math.PI / 4) {
4122
4505
  0
4123
4506
  ]);
4124
4507
  }
4125
- function D(c) {
4508
+ function k(c) {
4126
4509
  const t = Math.sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
4127
4510
  return [c[0] / t, c[1] / t, c[2] / t];
4128
4511
  }
4129
- function L(c, t) {
4512
+ function j(c, t) {
4130
4513
  return [
4131
4514
  c[1] * t[2] - c[2] * t[1],
4132
4515
  c[2] * t[0] - c[0] * t[2],
4133
4516
  c[0] * t[1] - c[1] * t[0]
4134
4517
  ];
4135
4518
  }
4136
- function A(c, t) {
4519
+ function I(c, t) {
4137
4520
  return c[0] * t[0] + c[1] * t[1] + c[2] * t[2];
4138
4521
  }
4139
- function Ee(c, t) {
4522
+ function Ge(c, t) {
4140
4523
  const e = new Float32Array(16);
4141
4524
  for (let i = 0; i < 4; i++)
4142
- for (let a = 0; a < 4; a++) {
4525
+ for (let s = 0; s < 4; s++) {
4143
4526
  let r = 0;
4144
4527
  for (let n = 0; n < 4; n++)
4145
- r += c[i + n * 4] * t[n + a * 4];
4146
- e[i + a * 4] = r;
4528
+ r += c[i + n * 4] * t[n + s * 4];
4529
+ e[i + s * 4] = r;
4147
4530
  }
4148
4531
  return e;
4149
4532
  }
4150
- function pe(c) {
4533
+ function Pe(c) {
4151
4534
  const t = new Uint8Array(c);
4152
4535
  let e = "";
4153
4536
  for (let i = 0; i < t.byteLength; i++)
4154
4537
  e += String.fromCharCode(t[i]);
4155
4538
  return btoa(e);
4156
4539
  }
4157
- function Ce(c, t) {
4540
+ function Ve(c, t) {
4158
4541
  if (!c || !c.particleSystems || c.particleSystems.length === 0) {
4159
4542
  alert("No particle systems to save.");
4160
4543
  return;
@@ -4163,134 +4546,142 @@ function Ce(c, t) {
4163
4546
  const e = {
4164
4547
  version: "1.0",
4165
4548
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4166
- systems: c.particleSystems.map(({ config: s, system: l }) => ({
4549
+ systems: c.particleSystems.map(({ config: a, system: l }) => ({
4167
4550
  // Include only the serializable properties of each system
4168
- name: s.name,
4169
- id: s.id,
4170
- particleCount: s.particleCount,
4171
- lifetime: s.lifetime,
4172
- emissionRate: s.emissionRate,
4173
- emissionDuration: s.emissionDuration,
4174
- particleSize: s.particleSize,
4175
- particleSpeed: s.particleSpeed,
4176
- emissionShape: s.emissionShape,
4177
- cubeLength: s.outerLength || s.cubeLength,
4551
+ name: a.name,
4552
+ id: a.id,
4553
+ particleCount: a.particleCount,
4554
+ lifetime: a.lifetime,
4555
+ emissionRate: a.emissionRate,
4556
+ emissionDuration: a.emissionDuration,
4557
+ particleSize: a.particleSize,
4558
+ particleSpeed: a.particleSpeed,
4559
+ emissionShape: a.emissionShape,
4560
+ cubeLength: a.outerLength || a.cubeLength,
4178
4561
  // Always use outerLength if available
4179
- outerLength: s.outerLength || s.cubeLength,
4562
+ outerLength: a.outerLength || a.cubeLength,
4180
4563
  // Keep them synchronized
4181
- innerLength: s.innerLength,
4182
- outerRadius: s.outerRadius,
4183
- innerRadius: s.innerRadius,
4184
- squareSize: s.squareSize,
4185
- squareInnerSize: s.squareInnerSize,
4186
- circleInnerRadius: s.circleInnerRadius,
4187
- circleOuterRadius: s.circleOuterRadius,
4188
- fadeEnabled: s.fadeEnabled,
4189
- colorTransitionEnabled: s.colorTransitionEnabled,
4190
- particleColor: s.particleColor,
4191
- startColor: s.startColor,
4192
- endColor: s.endColor,
4193
- randomColorEnabled: s.randomColorEnabled || !1,
4194
- randomColors: s.randomColors || [],
4195
- particleShape: s.particleShape || "square",
4196
- particleShapeRotation: s.particleShapeRotation || 0,
4197
- particleShapeRotationX: s.particleShapeRotationX || 0,
4198
- particleShapeRotationY: s.particleShapeRotationY || 0,
4199
- particleShapeRotationZ: s.particleShapeRotationZ || 0,
4200
- pulseEnabled: s.pulseEnabled || !1,
4201
- pulseAmplitude: s.pulseAmplitude ?? 0.5,
4202
- pulseFrequency: s.pulseFrequency ?? 1,
4203
- pulsePhaseRandom: s.pulsePhaseRandom ?? 0,
4204
- pulseOpacity: s.pulseOpacity || !1,
4205
- bloomEnabled: s.bloomEnabled,
4206
- bloomIntensity: s.bloomIntensity,
4207
- burstMode: s.burstMode,
4208
- gravityEnabled: s.gravityEnabled,
4209
- gravityStrength: s.gravityStrength,
4210
- dampingEnabled: s.dampingEnabled,
4211
- dampingStrength: s.dampingStrength,
4212
- attractorEnabled: s.attractorEnabled,
4213
- attractorStrength: s.attractorStrength,
4214
- attractorPosition: s.attractorPosition,
4215
- shapeRotationX: s.shapeRotationX,
4216
- shapeRotationY: s.shapeRotationY,
4217
- shapeRotationZ: s.shapeRotationZ,
4218
- shapeTranslationX: s.shapeTranslationX,
4219
- shapeTranslationY: s.shapeTranslationY,
4220
- shapeTranslationZ: s.shapeTranslationZ,
4221
- rotation: s.rotation,
4222
- rotationMode: s.rotationMode,
4223
- minRotation: s.minRotation,
4224
- maxRotation: s.maxRotation,
4225
- overrideXVelocity: s.overrideXVelocity,
4226
- overrideYVelocity: s.overrideYVelocity,
4227
- overrideZVelocity: s.overrideZVelocity,
4228
- xVelocity: s.xVelocity,
4229
- yVelocity: s.yVelocity,
4230
- zVelocity: s.zVelocity,
4231
- circleVelocityDirection: s.circleVelocityDirection,
4232
- cylinderVelocityDirection: s.cylinderVelocityDirection,
4233
- cylinderInnerRadius: s.cylinderInnerRadius,
4234
- cylinderOuterRadius: s.cylinderOuterRadius,
4235
- cylinderHeight: s.cylinderHeight,
4236
- aspectRatio: s.aspectRatio,
4237
- randomSize: s.randomSize,
4238
- minSize: s.minSize,
4239
- maxSize: s.maxSize,
4240
- fadeSizeEnabled: s.fadeSizeEnabled,
4241
- increaseSizeEnabled: s.increaseSizeEnabled,
4242
- sizeLifetimeSpeed: s.sizeLifetimeSpeed,
4243
- opacity: s.opacity,
4244
- randomSpeed: s.randomSpeed,
4245
- minSpeed: s.minSpeed,
4246
- maxSpeed: s.maxSpeed,
4247
- textureEnabled: s.textureEnabled,
4248
- textureType: s.textureType,
4249
- glbModelEnabled: s.glbModelEnabled,
4250
- glbFileName: s.glbFileName,
4251
- glbAnimated: s.glbAnimated,
4252
- animationIndex: s.animationIndex,
4253
- animationSpeed: s.animationSpeed,
4254
- animationLoop: s.animationLoop,
4255
- useGlbTexture: s.useGlbTexture,
4256
- oneOnlyMode: s.oneOnlyMode,
4257
- confinementEnabled: s.confinementEnabled || !1,
4258
- confinementShape: s.confinementShape || "box",
4259
- confinementMode: s.confinementMode || "bounce",
4260
- confinementSpace: s.confinementSpace || "world",
4261
- confinementBoxHalfSize: s.confinementBoxHalfSize || [2, 2, 2],
4262
- confinementSphereRadius: s.confinementSphereRadius ?? 3,
4263
- confinementRestitution: s.confinementRestitution ?? 0.8,
4264
- confinementFriction: s.confinementFriction ?? 0.1,
4265
- softBoundaryEnabled: s.softBoundaryEnabled || !1,
4266
- softBoundaryStrength: s.softBoundaryStrength ?? 5,
4267
- softBoundaryFalloff: s.softBoundaryFalloff ?? 0.5,
4268
- followSystemId: s.followSystemId || null,
4269
- hidden: s.hidden || !1,
4270
- emissionTrailEnabled: s.emissionTrailEnabled || !1,
4271
- emissionTrailDuration: s.emissionTrailDuration ?? 1,
4272
- emissionTrailWidth: s.emissionTrailWidth ?? 0.5,
4273
- emissionTrailMinDistance: s.emissionTrailMinDistance ?? 0.05,
4274
- emissionTrailMaxPoints: s.emissionTrailMaxPoints ?? 100,
4275
- textureImageData: s.textureEnabled && !s.glbModelEnabled && s.textureImageData ? s.textureImageData : void 0,
4276
- glbModelData: s.glbModelEnabled && l.glbRawArrayBuffer ? pe(l.glbRawArrayBuffer) : void 0
4564
+ innerLength: a.innerLength,
4565
+ outerRadius: a.outerRadius,
4566
+ innerRadius: a.innerRadius,
4567
+ squareSize: a.squareSize,
4568
+ squareInnerSize: a.squareInnerSize,
4569
+ circleInnerRadius: a.circleInnerRadius,
4570
+ circleOuterRadius: a.circleOuterRadius,
4571
+ fadeEnabled: a.fadeEnabled,
4572
+ colorTransitionEnabled: a.colorTransitionEnabled,
4573
+ particleColor: a.particleColor,
4574
+ startColor: a.startColor,
4575
+ endColor: a.endColor,
4576
+ randomColorEnabled: a.randomColorEnabled || !1,
4577
+ randomColors: a.randomColors || [],
4578
+ particleShape: a.particleShape || "square",
4579
+ particleShapeRotation: a.particleShapeRotation || 0,
4580
+ particleShapeRotationX: a.particleShapeRotationX || 0,
4581
+ particleShapeRotationY: a.particleShapeRotationY || 0,
4582
+ particleShapeRotationZ: a.particleShapeRotationZ || 0,
4583
+ pulseEnabled: a.pulseEnabled || !1,
4584
+ pulseAmplitude: a.pulseAmplitude ?? 0.5,
4585
+ pulseFrequency: a.pulseFrequency ?? 1,
4586
+ pulsePhaseRandom: a.pulsePhaseRandom ?? 0,
4587
+ pulseOpacity: a.pulseOpacity || !1,
4588
+ bloomEnabled: a.bloomEnabled,
4589
+ bloomIntensity: a.bloomIntensity,
4590
+ burstMode: a.burstMode,
4591
+ gravityEnabled: a.gravityEnabled,
4592
+ gravityStrength: a.gravityStrength,
4593
+ dampingEnabled: a.dampingEnabled,
4594
+ dampingStrength: a.dampingStrength,
4595
+ attractorEnabled: a.attractorEnabled,
4596
+ attractorStrength: a.attractorStrength,
4597
+ attractorPosition: a.attractorPosition,
4598
+ emissionRotationX: a.emissionRotationX,
4599
+ emissionRotationY: a.emissionRotationY,
4600
+ emissionRotationZ: a.emissionRotationZ,
4601
+ emissionTranslationX: a.emissionTranslationX,
4602
+ emissionTranslationY: a.emissionTranslationY,
4603
+ emissionTranslationZ: a.emissionTranslationZ,
4604
+ rotation: a.rotation,
4605
+ rotationMode: a.rotationMode,
4606
+ minRotation: a.minRotation,
4607
+ maxRotation: a.maxRotation,
4608
+ overrideXVelocity: a.overrideXVelocity,
4609
+ overrideYVelocity: a.overrideYVelocity,
4610
+ overrideZVelocity: a.overrideZVelocity,
4611
+ xVelocity: a.xVelocity,
4612
+ yVelocity: a.yVelocity,
4613
+ zVelocity: a.zVelocity,
4614
+ circleVelocityDirection: a.circleVelocityDirection,
4615
+ cylinderVelocityDirection: a.cylinderVelocityDirection,
4616
+ cylinderInnerRadius: a.cylinderInnerRadius,
4617
+ cylinderOuterRadius: a.cylinderOuterRadius,
4618
+ cylinderHeight: a.cylinderHeight,
4619
+ aspectRatio: a.aspectRatio,
4620
+ randomSize: a.randomSize,
4621
+ minSize: a.minSize,
4622
+ maxSize: a.maxSize,
4623
+ fadeSizeEnabled: a.fadeSizeEnabled,
4624
+ increaseSizeEnabled: a.increaseSizeEnabled,
4625
+ sizeLifetimeSpeed: a.sizeLifetimeSpeed,
4626
+ opacity: a.opacity,
4627
+ randomSpeed: a.randomSpeed,
4628
+ minSpeed: a.minSpeed,
4629
+ maxSpeed: a.maxSpeed,
4630
+ textureEnabled: a.textureEnabled,
4631
+ textureType: a.textureType,
4632
+ glbModelEnabled: a.glbModelEnabled,
4633
+ glbFileName: a.glbFileName,
4634
+ glbAnimated: a.glbAnimated,
4635
+ animationIndex: a.animationIndex,
4636
+ animationSpeed: a.animationSpeed,
4637
+ animationLoop: a.animationLoop,
4638
+ useGlbTexture: a.useGlbTexture,
4639
+ oneOnlyMode: a.oneOnlyMode,
4640
+ confinementEnabled: a.confinementEnabled || !1,
4641
+ confinementShape: a.confinementShape || "box",
4642
+ confinementMode: a.confinementMode || "bounce",
4643
+ confinementSpace: a.confinementSpace || "world",
4644
+ confinementBoxHalfSize: a.confinementBoxHalfSize || [2, 2, 2],
4645
+ confinementSphereRadius: a.confinementSphereRadius ?? 3,
4646
+ confinementRestitution: a.confinementRestitution ?? 0.8,
4647
+ confinementFriction: a.confinementFriction ?? 0.1,
4648
+ softBoundaryEnabled: a.softBoundaryEnabled || !1,
4649
+ softBoundaryStrength: a.softBoundaryStrength ?? 5,
4650
+ softBoundaryFalloff: a.softBoundaryFalloff ?? 0.5,
4651
+ followSystemId: a.followSystemId || null,
4652
+ hidden: a.hidden || !1,
4653
+ emissionTrailEnabled: a.emissionTrailEnabled || !1,
4654
+ emissionTrailDuration: a.emissionTrailDuration ?? 1,
4655
+ emissionTrailWidth: a.emissionTrailWidth ?? 0.5,
4656
+ emissionTrailMinDistance: a.emissionTrailMinDistance ?? 0.05,
4657
+ emissionTrailMaxPoints: a.emissionTrailMaxPoints ?? 100,
4658
+ emissionTrailSegments: a.emissionTrailSegments ?? 8,
4659
+ emissionTrailShape: a.emissionTrailShape ?? "straight",
4660
+ emissionTrailShapeAmplitude: a.emissionTrailShapeAmplitude ?? 0.1,
4661
+ emissionTrailShapeFrequency: a.emissionTrailShapeFrequency ?? 4,
4662
+ emissionTrailShapeSpeed: a.emissionTrailShapeSpeed ?? 0,
4663
+ shapeDisplay: a.shapeDisplay ?? !0,
4664
+ followSystemTranslation: a.followSystemTranslation ?? !0,
4665
+ script: a.script || void 0,
4666
+ textureImageData: a.textureEnabled && !a.glbModelEnabled && a.textureImageData ? a.textureImageData : void 0,
4667
+ glbModelData: a.glbModelEnabled && l.glbRawArrayBuffer ? Pe(l.glbRawArrayBuffer) : void 0
4277
4668
  })),
4278
4669
  activeSystemIndex: c.activeSystemIndex
4279
4670
  }, i = JSON.stringify(e, null, 2);
4280
- let a;
4671
+ let s;
4281
4672
  if (t)
4282
- a = `${t}.json`;
4673
+ s = `${t}.json`;
4283
4674
  else {
4284
- const s = /* @__PURE__ */ new Date();
4285
- 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`;
4675
+ const a = /* @__PURE__ */ new Date();
4676
+ s = `particle-scene_${`${a.getFullYear()}-${(a.getMonth() + 1).toString().padStart(2, "0")}-${a.getDate().toString().padStart(2, "0")}_${a.getHours().toString().padStart(2, "0")}${a.getMinutes().toString().padStart(2, "0")}`}.json`;
4286
4677
  }
4287
4678
  const r = new Blob([i], { type: "application/json" }), n = URL.createObjectURL(r), o = document.createElement("a");
4288
- o.href = n, o.download = a, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(n);
4679
+ o.href = n, o.download = s, document.body.appendChild(o), o.click(), document.body.removeChild(o), URL.revokeObjectURL(n);
4289
4680
  } catch (e) {
4290
4681
  console.error("Error saving scene:", e), alert("Error saving scene. See console for details.");
4291
4682
  }
4292
4683
  }
4293
- function _e(c) {
4684
+ function Le(c) {
4294
4685
  return new Promise((t, e) => {
4295
4686
  try {
4296
4687
  const i = c.target.files[0];
@@ -4298,8 +4689,8 @@ function _e(c) {
4298
4689
  e(new Error("No file selected"));
4299
4690
  return;
4300
4691
  }
4301
- const a = new FileReader();
4302
- a.onload = (r) => {
4692
+ const s = new FileReader();
4693
+ s.onload = (r) => {
4303
4694
  try {
4304
4695
  const n = JSON.parse(r.target.result);
4305
4696
  if (!n.version)
@@ -4307,8 +4698,8 @@ function _e(c) {
4307
4698
  if (!Array.isArray(n.systems) || n.systems.length === 0)
4308
4699
  throw new Error("No valid particle systems found in the file");
4309
4700
  const o = [];
4310
- for (const s of n.systems)
4311
- o.push(s);
4701
+ for (const a of n.systems)
4702
+ o.push(a);
4312
4703
  t({
4313
4704
  systems: o,
4314
4705
  activeSystemIndex: n.activeSystemIndex || 0
@@ -4317,15 +4708,15 @@ function _e(c) {
4317
4708
  console.error("Error loading scene:", n), alert("Error loading scene: " + n.message), e(n);
4318
4709
  }
4319
4710
  c.target.value = "";
4320
- }, a.onerror = () => {
4711
+ }, s.onerror = () => {
4321
4712
  alert("Failed to read the file"), e(new Error("Failed to read the file")), c.target.value = "";
4322
- }, a.readAsText(i);
4713
+ }, s.readAsText(i);
4323
4714
  } catch (i) {
4324
4715
  console.error("Error in loadScene:", i), e(i);
4325
4716
  }
4326
4717
  });
4327
4718
  }
4328
- async function Ae(c) {
4719
+ async function Oe(c) {
4329
4720
  if (!c || typeof c != "string")
4330
4721
  throw new Error("[fetchPreset] url must be a non-empty string");
4331
4722
  const t = await fetch(c);
@@ -4341,38 +4732,39 @@ async function Ae(c) {
4341
4732
  };
4342
4733
  }
4343
4734
  export {
4344
- ne as GLBAnimator,
4345
- Me as Objects3DManager,
4346
- Z as ParticleEmitter,
4347
- q as ParticlePhysics,
4348
- _ as ParticleSystem,
4349
- me as ParticleSystemManager,
4350
- $ as ParticleTextureManager,
4351
- N as blurShader,
4352
- X as compositeShader,
4353
- Se as createBindGroupLayouts,
4354
- ve as createBindGroups,
4355
- E as createBuffer,
4356
- de as createCubeGeometry,
4357
- be as createDepthTexture,
4358
- Be as createLookAtMatrix,
4359
- Te as createProjectionMatrix,
4360
- xe as createRenderPipelines,
4361
- ge as createRenderTextures,
4362
- Pe as createSampler,
4363
- fe as createSphereGeometry,
4364
- k as directRenderShader,
4365
- ie as extractGLBTexture,
4366
- Ae as fetchPreset,
4367
- ue as glbMeshParticleShader,
4368
- Re as hexToRgb,
4369
- ye as initWebGPU,
4370
- _e as loadScene,
4371
- Ee as multiplyMatrices,
4372
- ce as object3dShader,
4373
- O as parseGLB,
4374
- oe as particlePhysicsShader,
4375
- j as particleShader,
4376
- we as rgbToHex,
4377
- Ce as saveScene
4735
+ me as GLBAnimator,
4736
+ Ie as Objects3DManager,
4737
+ W as ParticleEmitter,
4738
+ J as ParticlePhysics,
4739
+ z as ParticleScript,
4740
+ A as ParticleSystem,
4741
+ Me as ParticleSystemManager,
4742
+ K as ParticleTextureManager,
4743
+ q as blurShader,
4744
+ Z as compositeShader,
4745
+ Te as createBindGroupLayouts,
4746
+ Ee as createBindGroups,
4747
+ C as createBuffer,
4748
+ xe as createCubeGeometry,
4749
+ Be as createDepthTexture,
4750
+ Fe as createLookAtMatrix,
4751
+ De as createProjectionMatrix,
4752
+ Ce as createRenderPipelines,
4753
+ we as createRenderTextures,
4754
+ Ae as createSampler,
4755
+ ve as createSphereGeometry,
4756
+ $ as directRenderShader,
4757
+ ue as extractGLBTexture,
4758
+ Oe as fetchPreset,
4759
+ Se as glbMeshParticleShader,
4760
+ Ue as hexToRgb,
4761
+ Re as initWebGPU,
4762
+ Le as loadScene,
4763
+ Ge as multiplyMatrices,
4764
+ be as object3dShader,
4765
+ X as parseGLB,
4766
+ ye as particlePhysicsShader,
4767
+ Y as particleShader,
4768
+ ze as rgbToHex,
4769
+ Ve as saveScene
4378
4770
  };