phoria2 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +71 -13
  2. package/dist/bloom.js +1 -1
  3. package/dist/charts.js +397 -384
  4. package/dist/charts.js.map +1 -1
  5. package/dist/core.js +4451 -3568
  6. package/dist/core.js.map +1 -1
  7. package/dist/edit.js +67 -67
  8. package/dist/edit.js.map +1 -1
  9. package/dist/explain.js +6 -2
  10. package/dist/explain.js.map +1 -1
  11. package/dist/gltf.js +211 -166
  12. package/dist/gltf.js.map +1 -1
  13. package/dist/motion.js +26 -26
  14. package/dist/motion.js.map +1 -1
  15. package/dist/particles.js +49 -49
  16. package/dist/particles.js.map +1 -1
  17. package/dist/passes.js +188 -86
  18. package/dist/passes.js.map +1 -1
  19. package/dist/phoria2.js +1 -1
  20. package/dist/picking.js +8 -13
  21. package/dist/picking.js.map +1 -1
  22. package/dist/snapshot.js +1 -1
  23. package/dist/tooltip.js +3 -3
  24. package/dist/tooltip.js.map +1 -1
  25. package/dist/types/OrbitControl.d.ts +6 -2
  26. package/dist/types/Raycaster.d.ts +10 -0
  27. package/dist/types/View.d.ts +64 -1
  28. package/dist/types/charts/Chart.d.ts +7 -0
  29. package/dist/types/explain.d.ts +3 -0
  30. package/dist/types/frame.d.ts +7 -0
  31. package/dist/types/geometry/Geometry.d.ts +14 -2
  32. package/dist/types/keyboard.d.ts +48 -0
  33. package/dist/types/labels.d.ts +4 -0
  34. package/dist/types/material/Material.d.ts +125 -0
  35. package/dist/types/material/Texture.d.ts +37 -5
  36. package/dist/types/scene/Node.d.ts +19 -14
  37. package/dist/types/scene/drawables.d.ts +32 -14
  38. package/dist/types/scene/lights.d.ts +16 -2
  39. package/dist/types/shadow.d.ts +2 -1
  40. package/dist/types/types.d.ts +14 -0
  41. package/dist/types/value/Color.d.ts +0 -4
  42. package/dist/types/value/Quat.d.ts +4 -2
  43. package/dist/types/webgl/WebGLRenderer.d.ts +6 -0
  44. package/dist/types/webgl/passes.d.ts +37 -13
  45. package/dist/types/webgl/resources.d.ts +24 -2
  46. package/dist/types/webgl/shaders.d.ts +4 -2
  47. package/llms-full.txt +153 -15
  48. package/package.json +4 -1
  49. package/schema/scene.schema.json +146 -1
  50. package/src/OrbitControl.js +7 -3
  51. package/src/Raycaster.js +58 -0
  52. package/src/View.js +207 -42
  53. package/src/charts/Chart.js +20 -2
  54. package/src/explain.js +6 -2
  55. package/src/frame.js +29 -9
  56. package/src/geometry/Geometry.js +24 -4
  57. package/src/gltf/load.js +50 -6
  58. package/src/keyboard.js +298 -0
  59. package/src/labels.js +4 -1
  60. package/src/material/Material.js +104 -19
  61. package/src/material/Texture.js +116 -11
  62. package/src/scene/Node.js +20 -9
  63. package/src/scene/Scene.js +2 -0
  64. package/src/scene/cameras.js +4 -1
  65. package/src/scene/drawables.js +48 -12
  66. package/src/scene/lights.js +40 -6
  67. package/src/shadow.js +27 -4
  68. package/src/types.js +6 -0
  69. package/src/value/Color.js +21 -0
  70. package/src/value/Quat.js +15 -6
  71. package/src/watch.js +25 -1
  72. package/src/webgl/WebGLRenderer.js +51 -12
  73. package/src/webgl/passes.js +190 -32
  74. package/src/webgl/picking.js +0 -1
  75. package/src/webgl/resources.js +89 -8
  76. package/src/webgl/shaders.js +350 -48
package/dist/passes.js CHANGED
@@ -1,6 +1,6 @@
1
- import { A as e, D as t, F as n, Ft as r, Mt as i, N as a, O as o, Pt as s, _t as c, j as l, k as u, vt as d, yt as f } from "./core.js";
1
+ import { A as e, C as t, E as n, Ft as r, It as i, Nt as a, O as o, S as s, T as c, bt as l, vt as u, w as d, x as f, yt as p } from "./core.js";
2
2
  // src/irradiance.js
3
- function p({ data: e, width: t, height: n }) {
3
+ function m({ data: e, width: t, height: n }) {
4
4
  let r = /* @__PURE__ */ new Float64Array(27), i = Math.max(1, Math.floor(t / 128)), a = Math.max(1, Math.floor(n / 64)), o = 2 * Math.PI * i / t, s = Math.PI * a / n;
5
5
  for (let c = 0; c < n; c += a) {
6
6
  let l = (c + .5 * a) / n * Math.PI, u = Math.sin(l), d = Math.cos(l), f = o * s * u;
@@ -47,7 +47,7 @@ function p({ data: e, width: t, height: n }) {
47
47
  return u;
48
48
  }
49
49
  // src/webgl/passes.js
50
- var m = `precision highp float;
50
+ var h = `precision highp float;
51
51
  in vec2 vUv;
52
52
  uniform mat4 uInverseViewProjection;
53
53
  uniform vec3 uCameraPosition;
@@ -56,9 +56,9 @@ uniform float uLod;
56
56
  uniform float uIntensity;
57
57
  uniform int uHdr;
58
58
  out vec4 fragColor;
59
- ${u}
59
+ ${d}
60
+ ${c}
60
61
  ${e}
61
- ${n}
62
62
  void main() {
63
63
  vec4 far = uInverseViewProjection * vec4(vUv * 2.0 - 1.0, 1.0, 1.0);
64
64
  vec3 d = normalize(far.xyz / far.w - uCameraPosition);
@@ -66,14 +66,14 @@ vec3 c = textureLod(uBackground, equirectUv(d), uLod).rgb * uIntensity;
66
66
  if (uHdr == 1) c = toneMap(c);
67
67
  fragColor = vec4(linearToSrgb(c), 1.0);
68
68
  }
69
- `, h = `precision highp float;
69
+ `, g = `precision highp float;
70
70
  in vec2 vUv;
71
71
  uniform sampler2D uSource;
72
72
  uniform float uRoughness;
73
73
  uniform float uSourceTexels;
74
74
  uniform float uCopyLod;
75
75
  out vec4 fragColor;
76
- ${e}
76
+ ${c}
77
77
  const float PI = 3.14159265359;
78
78
  const uint SAMPLES = 192u;
79
79
  vec2 hammersley(uint i) {
@@ -114,52 +114,122 @@ weight += NoL;
114
114
  }
115
115
  fragColor = vec4(sum / max(weight, 1e-4), 1.0);
116
116
  }
117
- `, g = `precision highp float;
117
+ `, _ = `precision highp float;
118
118
  in vec3 vWorldPosition;
119
119
  uniform vec4 uMask;
120
120
  out vec4 fragColor;
121
- ${t}
121
+ ${s}
122
122
  void main() {
123
123
  clipAway(vWorldPosition);
124
124
  fragColor = uMask;
125
125
  }
126
- `, _ = 16, v = `uniform sampler2D uSource;
126
+ `, v = 16, y = `uniform sampler2D uSource;
127
127
  uniform vec2 uStep;
128
128
  uniform int uRadius;
129
129
  vec4 widened(vec2 uv) {
130
130
  vec4 best = vec4(0.0);
131
131
  float nearest = 1e9;
132
- for (int i = -${_}; i <= ${_}; i++) {
132
+ for (int i = -${v}; i <= ${v}; i++) {
133
133
  float d = abs(float(i));
134
134
  if (d > float(uRadius)) continue;
135
135
  vec4 s = texture(uSource, uv + uStep * float(i));
136
- if (s.a > 0.0 && d <= s.a * ${_}.0 && d < nearest) {
136
+ if (s.a > 0.0 && d <= s.a * ${v}.0 && d < nearest) {
137
137
  best = s;
138
138
  nearest = d;
139
139
  }
140
140
  }
141
141
  return best;
142
142
  }
143
- `, y = `precision highp float;
143
+ `, b = `precision highp float;
144
144
  in vec2 vUv;
145
145
  out vec4 fragColor;
146
- ${v}
146
+ ${y}
147
147
  void main() {
148
148
  fragColor = widened(vUv);
149
149
  }
150
- `, b = `precision highp float;
150
+ `, x = `precision highp float;
151
151
  in vec2 vUv;
152
152
  uniform sampler2D uMask;
153
153
  out vec4 fragColor;
154
- ${u}
155
- ${v}
154
+ ${d}
155
+ ${y}
156
156
  void main() {
157
157
  if (texture(uMask, vUv).a > 0.0) discard;
158
158
  vec4 ring = widened(vUv);
159
159
  if (ring.a <= 0.0) discard;
160
160
  fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
161
161
  }
162
- `, x = [a, g], S = [l, y], C = [l, b], w = [a, o], T = [l, m], E = [l, h], D = 512, O = 6, k = class {
162
+ `, S = `precision highp float;
163
+ in vec3 vWorldPosition;
164
+ uniform vec4 uMask;
165
+ layout(location = 0) out vec4 fragColor;
166
+ layout(location = 1) out vec4 fragCoverage;
167
+ ${s}
168
+ void main() {
169
+ clipAway(vWorldPosition);
170
+ fragColor = uMask;
171
+ fragCoverage = vec4(1.0);
172
+ }
173
+ `, C = `uniform sampler2D uMask;
174
+ uniform sampler2D uCoverage;
175
+ uniform vec2 uTexel;
176
+ uniform int uRadius;
177
+ vec4 masked(vec2 uv, float coverage) {
178
+ vec4 m = texture(uMask, uv) / coverage;
179
+ return vec4(m.rgb, m.a * ${v}.0);
180
+ }
181
+ `, w = `precision highp float;
182
+ in vec2 vUv;
183
+ out vec4 fragColor;
184
+ ${C}
185
+ void main() {
186
+ float nearest = 1e9;
187
+ int at = 0;
188
+ bool found = false;
189
+ for (int i = -17; i <= 17; i++) {
190
+ if (abs(i) > uRadius + 1) continue;
191
+ vec2 uv = vUv + vec2(float(i) * uTexel.x, 0.0);
192
+ float c = texture(uCoverage, uv).r;
193
+ if (c <= 0.0) continue;
194
+ float d = abs(float(i)) - (c - 0.5);
195
+ if (d < masked(uv, c).a + 0.5 && d < nearest) {
196
+ nearest = d;
197
+ at = i;
198
+ found = true;
199
+ }
200
+ }
201
+ fragColor = found ? vec4(float(at + 32) / 255.0, 0.0, 0.0, 1.0) : vec4(0.0);
202
+ }
203
+ `, T = `precision highp float;
204
+ in vec2 vUv;
205
+ uniform sampler2D uNearest;
206
+ out vec4 fragColor;
207
+ ${d}
208
+ ${C}
209
+ void main() {
210
+ float here = texture(uCoverage, vUv).r;
211
+ if (here >= 1.0) discard;
212
+ float nearest = 1e9;
213
+ vec4 ring = vec4(0.0);
214
+ for (int j = -17; j <= 17; j++) {
215
+ if (abs(j) > uRadius + 1) continue;
216
+ vec2 row = vUv + vec2(0.0, float(j) * uTexel.y);
217
+ vec4 n = texture(uNearest, row);
218
+ if (n.a <= 0.0) continue;
219
+ int i = int(n.r * 255.0 + 0.5) - 32;
220
+ vec2 uv = row + vec2(float(i) * uTexel.x, 0.0);
221
+ float c = texture(uCoverage, uv).r;
222
+ float d = length(vec2(float(i), float(j))) - (c - 0.5);
223
+ if (d < nearest) {
224
+ nearest = d;
225
+ ring = masked(uv, c);
226
+ }
227
+ }
228
+ float alpha = clamp(ring.a - nearest + 0.5, 0.0, 1.0) * (1.0 - here);
229
+ if (alpha <= 0.0) discard;
230
+ fragColor = vec4(linearToSrgb(ring.rgb) * alpha, alpha);
231
+ }
232
+ `, E = [o, _], D = [n, b], O = [n, x], k = [o, S], A = [n, w], j = [n, T], M = [o, t], N = [n, h], P = [n, g], F = 512, I = 6, L = class {
163
233
  #e = /* @__PURE__ */ new WeakMap();
164
234
  #t = null;
165
235
  #n = null;
@@ -183,33 +253,33 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
183
253
  });
184
254
  let r = e.image, i = this.#d(r.width, r.height, Math.floor(Math.log2(Math.max(r.width, r.height))) + 1);
185
255
  n.texSubImage2D(n.TEXTURE_2D, 0, 0, 0, r.width, r.height, n.RGBA, n.FLOAT, r.data), n.generateMipmap(n.TEXTURE_2D);
186
- let a = this.#d(D, D / 2, O), o = this.programs.ready("prefilter", [], E);
256
+ let a = this.#d(F, F / 2, I), o = this.programs.ready("prefilter", [], P);
187
257
  n.useProgram(o.program), o.set("uSource", i), o.set("uSourceTexels", r.width * r.height);
188
258
  let s = n.createFramebuffer();
189
259
  n.bindFramebuffer(n.FRAMEBUFFER, s), n.disable(n.DEPTH_TEST), n.disable(n.BLEND), n.disable(n.CULL_FACE);
190
- for (let e = 0; e < O; e++) {
191
- let t = D >> e;
260
+ for (let e = 0; e < I; e++) {
261
+ let t = F >> e;
192
262
  n.framebufferTexture2D(n.FRAMEBUFFER, n.COLOR_ATTACHMENT0, n.TEXTURE_2D, a, e), n.viewport(0, 0, t, t / 2), o.set("uRoughness", e / 5), o.set("uCopyLod", Math.max(0, Math.log2(r.width / t))), this.programs.drawFullscreen();
193
263
  }
194
264
  return n.bindFramebuffer(n.FRAMEBUFFER, null), n.deleteFramebuffer(s), n.enable(n.DEPTH_TEST), t = {
195
265
  source: i,
196
266
  prefiltered: a,
197
267
  maxLod: 5,
198
- sh: p(r),
268
+ sh: m(r),
199
269
  version: e.version
200
270
  }, this.#e.set(e, t), t;
201
271
  }
202
272
  background(e, t, n) {
203
- let r = this.gl, a = t.isHDR, o = a ? this.environment(t) : null;
204
- if (a && !o) return;
205
- let c = this.programs.ready("background", [], T);
206
- r.useProgram(c.program);
273
+ let i = this.gl, o = t.isHDR, s = o ? this.environment(t) : null;
274
+ if (o && !s) return;
275
+ let c = this.programs.ready("background", [], N);
276
+ i.useProgram(c.program);
207
277
  let l = Math.min(Math.max(e.backgroundBlur, 0), 1);
208
- o ? (c.set("uBackground", l > 0 ? o.prefiltered : o.source), c.set("uLod", l * o.maxLod), c.set("uIntensity", e.environment === t ? e.environmentIntensity : 1)) : (c.set("uBackground", this.resources.texture(t)), c.set("uLod", l * 6), c.set("uIntensity", 1)), c.set("uHdr", +!!a), c.set("uExposure", n.exposure), c.set("uToneMapping", n.toneMapping), c.set("uInverseViewProjection", s(i(), e.camera.viewProjection)), c.set("uCameraPosition", e.camera.position), r.disable(r.DEPTH_TEST), r.disable(r.BLEND), r.disable(r.CULL_FACE), r.depthMask(!1), this.programs.drawFullscreen(), r.depthMask(!0), r.enable(r.DEPTH_TEST);
278
+ s ? (c.set("uBackground", l > 0 ? s.prefiltered : s.source), c.set("uLod", l * s.maxLod), c.set("uIntensity", e.environment === t ? e.environmentIntensity : 1)) : (c.set("uBackground", this.resources.texture(t)), c.set("uLod", l * 6), c.set("uIntensity", 1)), c.set("uHdr", +!!o), c.set("uExposure", n.exposure), c.set("uToneMapping", n.toneMapping), c.set("uInverseViewProjection", r(a(), e.camera.viewProjection)), c.set("uCameraPosition", e.camera.position), i.disable(i.DEPTH_TEST), i.disable(i.BLEND), i.disable(i.CULL_FACE), i.depthMask(!1), this.programs.drawFullscreen(), i.depthMask(!0), i.enable(i.DEPTH_TEST);
209
279
  }
210
280
  shadowMap(e) {
211
281
  let t = this.gl;
212
- this.#t ??= this.#l(d), t.bindFramebuffer(t.FRAMEBUFFER, this.#t.framebuffer), t.viewport(0, 0, d, d), this.#a(), this.#s(e.casters, e.viewProjection), this.#o();
282
+ this.#t ??= this.#l(p), t.bindFramebuffer(t.FRAMEBUFFER, this.#t.framebuffer), t.viewport(0, 0, p, p), this.#a(), this.#s(e.casters, e.viewProjection), this.#o();
213
283
  let n = new Float32Array([
214
284
  .5,
215
285
  0,
@@ -233,16 +303,16 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
233
303
  sampler: "uShadowMap",
234
304
  texture: this.#t.texture,
235
305
  uniforms: {
236
- uShadowMatrix: r(/* @__PURE__ */ new Float32Array(16), n, e.viewProjection),
237
- uShadowTexel: 1 / d,
306
+ uShadowMatrix: i(/* @__PURE__ */ new Float32Array(16), n, e.viewProjection),
307
+ uShadowTexel: 1 / p,
238
308
  uShadowBias: e.texelSize * 1.5
239
309
  }
240
310
  };
241
311
  }
242
312
  spotShadowMaps(e) {
243
313
  let t = this.gl;
244
- this.#n ??= this.#l(f), t.bindFramebuffer(t.FRAMEBUFFER, this.#n.framebuffer), t.viewport(0, 0, f, f), this.#a();
245
- let n = /* @__PURE__ */ new Float32Array(64), i = /* @__PURE__ */ new Float32Array(16), a = /* @__PURE__ */ new Float32Array(4), o = f / 2;
314
+ this.#n ??= this.#l(l), t.bindFramebuffer(t.FRAMEBUFFER, this.#n.framebuffer), t.viewport(0, 0, l, l), this.#a();
315
+ let n = /* @__PURE__ */ new Float32Array(64), r = /* @__PURE__ */ new Float32Array(16), a = /* @__PURE__ */ new Float32Array(4), o = l / 2;
246
316
  for (let s of e) {
247
317
  let e = s.tile % 2, c = Math.floor(s.tile / 2);
248
318
  t.viewport(e * o, c * o, o, o), this.#s(s.casters, s.viewProjection);
@@ -264,7 +334,7 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
264
334
  .5,
265
335
  1
266
336
  ]);
267
- n.set(r(/* @__PURE__ */ new Float32Array(16), l, s.viewProjection), s.tile * 16), i.set([
337
+ n.set(i(/* @__PURE__ */ new Float32Array(16), l, s.viewProjection), s.tile * 16), r.set([
268
338
  e * .5,
269
339
  c * .5,
270
340
  e * .5 + .5,
@@ -277,16 +347,16 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
277
347
  texture: this.#n.texture,
278
348
  uniforms: {
279
349
  uSpotShadowMatrix: n,
280
- uSpotShadowTile: i,
350
+ uSpotShadowTile: r,
281
351
  uSpotShadowBias: a,
282
- uSpotShadowTexel: 1 / f
352
+ uSpotShadowTexel: 1 / l
283
353
  }
284
354
  };
285
355
  }
286
356
  pointShadowMap(e) {
287
357
  let t = this.gl;
288
- return this.#r ??= this.#u(c), e.faces.forEach((e, n) => {
289
- t.bindFramebuffer(t.FRAMEBUFFER, this.#r.framebuffers[n]), t.viewport(0, 0, c, c), this.#a(), this.#s(e.casters, e.viewProjection);
358
+ return this.#r ??= this.#u(u), e.faces.forEach((e, n) => {
359
+ t.bindFramebuffer(t.FRAMEBUFFER, this.#r.framebuffers[n]), t.viewport(0, 0, u, u), this.#a(), this.#s(e.casters, e.viewProjection);
290
360
  }), this.#o(), {
291
361
  define: "POINT_SHADOW",
292
362
  sampler: "uPointShadowMap",
@@ -312,77 +382,109 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
312
382
  let e = r.instances, i = e ? ["INSTANCED"] : [];
313
383
  r.clip && i.push("CLIP");
314
384
  let a = r.material, o = a.alphaTest > 0, s = o && !!a.map && a.triplanar > 0;
315
- o && i.push("ALPHA_TEST", ...a.map ? ["MAP"] : [], ...s ? ["TRIPLANAR"] : []);
316
- let c = this.programs.ready("depth", i, w);
385
+ o && i.push("ALPHA_TEST", ...a.map ? ["MAP"] : [], ...s ? ["TRIPLANAR"] : []), o && a.map?.uvSet === 1 && r.geometry.uvs2 && i.push("UV2", "uMapSet vUv2");
386
+ let c = this.programs.ready("depth", i, M);
317
387
  if (n.useProgram(c.program), c.set("uViewProjection", t), c.set("uModel", r.worldMatrix), r.clip && c.set("uClipPlane", r.clip.plane), o) {
318
388
  c.set("uOpacity", a.opacity), c.set("uAlphaTest", a.alphaTest);
319
389
  let e = a.map;
320
- c.set("uUvTransform", e ? [
321
- e.repeat[0],
322
- e.repeat[1],
323
- e.offset[0],
324
- e.offset[1]
325
- ] : [
326
- 1,
327
- 1,
328
- 0,
329
- 0
330
- ]), e && c.set("uMap", this.resources.texture(e)), s && c.set("uTriplanar", a.triplanar);
390
+ e && (c.set("uMapUv", f(e)), c.set("uMap", this.resources.texture(e))), s && c.set("uTriplanar", a.triplanar);
331
391
  }
332
392
  this.resources.drawTriangles(r.geometry, e);
333
393
  }
334
394
  }
335
- outlineMask(e, t, n, r, i) {
336
- let a = this.gl, o = this.#c(n, r);
337
- a.bindFramebuffer(a.FRAMEBUFFER, o.mask.framebuffer), a.viewport(0, 0, n, r), a.clearColor(0, 0, 0, 0), a.clear(a.COLOR_BUFFER_BIT), a.disable(a.DEPTH_TEST), a.disable(a.BLEND), a.disable(a.CULL_FACE), a.depthMask(!1);
338
- let s = 1;
395
+ outlineMask(e, t, n, r, i, a) {
396
+ let o = this.gl, s = this.#c(n, r, a);
397
+ o.bindFramebuffer(o.FRAMEBUFFER, s.msaa ? s.msaa.framebuffer : s.mask.framebuffer), s.msaa && o.drawBuffers([o.COLOR_ATTACHMENT0, o.COLOR_ATTACHMENT1]), o.viewport(0, 0, n, r), o.clearColor(0, 0, 0, 0), o.clear(o.COLOR_BUFFER_BIT), o.disable(o.DEPTH_TEST), o.disable(o.BLEND), o.disable(o.CULL_FACE), o.depthMask(!1);
398
+ let c = 1;
339
399
  for (let n of e) {
340
- let e = Math.min(_, Math.max(1, Math.round(n.width * i)));
341
- s = Math.max(s, e);
400
+ let e = Math.min(v, Math.max(1, Math.round(n.width * i)));
401
+ c = Math.max(c, e);
342
402
  for (let r of n.items) {
343
403
  let i = r.instances ? ["INSTANCED"] : [];
344
404
  r.clip && i.push("CLIP");
345
- let o = this.programs.ready("outline-mask", i, x);
346
- a.useProgram(o.program), o.set("uViewProjection", t.camera.viewProjection), o.set("uModel", r.worldMatrix), o.set("uMask", [
405
+ let s = a ? this.programs.ready("outline-cover", i, k) : this.programs.ready("outline-mask", i, E);
406
+ o.useProgram(s.program), s.set("uViewProjection", t.camera.viewProjection), s.set("uModel", r.worldMatrix), s.set("uMask", [
347
407
  n.color[0],
348
408
  n.color[1],
349
409
  n.color[2],
350
- e / _
351
- ]), r.clip && o.set("uClipPlane", r.clip.plane), this.resources.drawTriangles(r.geometry, r.instances);
410
+ e / v
411
+ ]), r.clip && s.set("uClipPlane", r.clip.plane), this.resources.drawTriangles(r.geometry, r.instances);
352
412
  }
353
413
  }
354
- a.bindFramebuffer(a.FRAMEBUFFER, o.wide.framebuffer), a.clear(a.COLOR_BUFFER_BIT);
355
- let c = this.programs.ready("outline-widen", [], S);
356
- return a.useProgram(c.program), c.set("uSource", o.mask.texture), c.set("uStep", [1 / n, 0]), c.set("uRadius", s), this.programs.drawFullscreen(), a.depthMask(!0), a.enable(a.DEPTH_TEST), a.bindFramebuffer(a.FRAMEBUFFER, null), {
357
- mask: o.mask.texture,
358
- wide: o.wide.texture,
359
- radius: s
414
+ if (s.msaa && s.coverage) {
415
+ o.bindFramebuffer(o.READ_FRAMEBUFFER, s.msaa.framebuffer);
416
+ for (let [e, t] of [[o.COLOR_ATTACHMENT0, s.mask], [o.COLOR_ATTACHMENT1, s.coverage]]) o.readBuffer(e), o.bindFramebuffer(o.DRAW_FRAMEBUFFER, t.framebuffer), o.blitFramebuffer(0, 0, n, r, 0, 0, n, r, o.COLOR_BUFFER_BIT, o.NEAREST);
417
+ }
418
+ if (o.bindFramebuffer(o.FRAMEBUFFER, s.wide.framebuffer), o.clear(o.COLOR_BUFFER_BIT), s.coverage) {
419
+ let e = this.programs.ready("outline-smooth-widen", [], A);
420
+ o.useProgram(e.program), e.set("uMask", s.mask.texture), e.set("uCoverage", s.coverage.texture), e.set("uTexel", [1 / n, 1 / r]), e.set("uRadius", c);
421
+ } else {
422
+ let e = this.programs.ready("outline-widen", [], D);
423
+ o.useProgram(e.program), e.set("uSource", s.mask.texture), e.set("uStep", [1 / n, 0]), e.set("uRadius", c);
424
+ }
425
+ return this.programs.drawFullscreen(), o.depthMask(!0), o.enable(o.DEPTH_TEST), o.bindFramebuffer(o.FRAMEBUFFER, null), {
426
+ mask: s.mask.texture,
427
+ wide: s.wide.texture,
428
+ coverage: s.coverage?.texture ?? null,
429
+ radius: c,
430
+ width: n,
431
+ height: r
360
432
  };
361
433
  }
362
- outlineComposite(e, t) {
363
- let n = this.gl, r = this.programs.ready("outline-composite", [], C);
364
- n.useProgram(r.program), r.set("uSource", e.wide), r.set("uMask", e.mask), r.set("uStep", [0, 1 / t]), r.set("uRadius", e.radius), n.disable(n.DEPTH_TEST), n.disable(n.CULL_FACE), n.depthMask(!1), n.enable(n.BLEND), n.blendFunc(n.ONE, n.ONE_MINUS_SRC_ALPHA), this.programs.drawFullscreen(), n.depthMask(!0), n.enable(n.DEPTH_TEST);
434
+ outlineComposite(e) {
435
+ let t = this.gl;
436
+ if (e.coverage) {
437
+ let n = this.programs.ready("outline-smooth-composite", [], j);
438
+ t.useProgram(n.program), n.set("uNearest", e.wide), n.set("uMask", e.mask), n.set("uCoverage", e.coverage), n.set("uTexel", [1 / e.width, 1 / e.height]), n.set("uRadius", e.radius);
439
+ } else {
440
+ let n = this.programs.ready("outline-composite", [], O);
441
+ t.useProgram(n.program), n.set("uSource", e.wide), n.set("uMask", e.mask), n.set("uStep", [0, 1 / e.height]), n.set("uRadius", e.radius);
442
+ }
443
+ t.disable(t.DEPTH_TEST), t.disable(t.CULL_FACE), t.depthMask(!1), t.enable(t.BLEND), t.blendFunc(t.ONE, t.ONE_MINUS_SRC_ALPHA), this.programs.drawFullscreen(), t.depthMask(!0), t.enable(t.DEPTH_TEST);
365
444
  }
366
- #c(e, t) {
367
- let n = this.#i;
368
- if (n && n.width === e && n.height === t) return n;
369
- let r = this.gl;
370
- if (n) for (let { texture: e, framebuffer: t } of [n.mask, n.wide]) r.deleteTexture(e), r.deleteFramebuffer(t);
371
- let i = () => {
372
- let n = r.createTexture();
373
- r.activeTexture(r.TEXTURE15), r.bindTexture(r.TEXTURE_2D, n), r.texStorage2D(r.TEXTURE_2D, 1, r.RGBA8, e, t), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.NEAREST), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MAG_FILTER, r.NEAREST), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, r.CLAMP_TO_EDGE), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, r.CLAMP_TO_EDGE);
374
- let i = r.createFramebuffer();
375
- return r.bindFramebuffer(r.FRAMEBUFFER, i), r.framebufferTexture2D(r.FRAMEBUFFER, r.COLOR_ATTACHMENT0, r.TEXTURE_2D, n, 0), {
376
- texture: n,
377
- framebuffer: i
445
+ #c(e, t, n) {
446
+ let r = this.#i;
447
+ if (r && r.width === e && r.height === t && r.smooth === n) return r;
448
+ let i = this.gl;
449
+ if (r) {
450
+ for (let e of [
451
+ r.mask,
452
+ r.wide,
453
+ r.coverage
454
+ ]) e && (i.deleteTexture(e.texture), i.deleteFramebuffer(e.framebuffer));
455
+ if (r.msaa) {
456
+ i.deleteFramebuffer(r.msaa.framebuffer);
457
+ for (let e of r.msaa.renderbuffers) i.deleteRenderbuffer(e);
458
+ }
459
+ }
460
+ let a = (n = i.RGBA8) => {
461
+ let r = i.createTexture();
462
+ i.activeTexture(i.TEXTURE15), i.bindTexture(i.TEXTURE_2D, r), i.texStorage2D(i.TEXTURE_2D, 1, n, e, t), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MIN_FILTER, i.NEAREST), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MAG_FILTER, i.NEAREST), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_S, i.CLAMP_TO_EDGE), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_WRAP_T, i.CLAMP_TO_EDGE);
463
+ let a = i.createFramebuffer();
464
+ return i.bindFramebuffer(i.FRAMEBUFFER, a), i.framebufferTexture2D(i.FRAMEBUFFER, i.COLOR_ATTACHMENT0, i.TEXTURE_2D, r, 0), {
465
+ texture: r,
466
+ framebuffer: a
378
467
  };
379
- };
468
+ }, o = null;
469
+ if (n) {
470
+ let n = Math.min(4, i.getParameter(i.MAX_SAMPLES)), r = i.createFramebuffer();
471
+ i.bindFramebuffer(i.FRAMEBUFFER, r), o = {
472
+ framebuffer: r,
473
+ renderbuffers: [i.RGBA8, i.R8].map((r, a) => {
474
+ let o = i.createRenderbuffer();
475
+ return i.bindRenderbuffer(i.RENDERBUFFER, o), i.renderbufferStorageMultisample(i.RENDERBUFFER, n, r, e, t), i.framebufferRenderbuffer(i.FRAMEBUFFER, i.COLOR_ATTACHMENT0 + a, i.RENDERBUFFER, o), o;
476
+ })
477
+ };
478
+ }
380
479
  return this.#i = {
381
480
  width: e,
382
481
  height: t,
383
- mask: i(),
384
- wide: i()
385
- }, r.bindFramebuffer(r.FRAMEBUFFER, null), this.#i;
482
+ smooth: n,
483
+ mask: a(),
484
+ wide: a(),
485
+ coverage: n ? a(i.R8) : null,
486
+ msaa: o
487
+ }, i.bindFramebuffer(i.FRAMEBUFFER, null), this.#i;
386
488
  }
387
489
  #l(e) {
388
490
  let t = this.gl, n = t.createTexture();
@@ -417,6 +519,6 @@ fragColor = vec4(linearToSrgb(ring.rgb), 1.0);
417
519
  return r.activeTexture(r.TEXTURE15), r.bindTexture(r.TEXTURE_2D, i), r.texStorage2D(r.TEXTURE_2D, n, r.RGBA16F, e, t), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, r.REPEAT), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, r.CLAMP_TO_EDGE), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, r.LINEAR_MIPMAP_LINEAR), r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MAG_FILTER, r.LINEAR), r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL, !1), i;
418
520
  }
419
521
  };
420
- export { k as Passes };
522
+ export { L as Passes };
421
523
 
422
524
  //# sourceMappingURL=passes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"passes.js","names":["mat4.invert","mat4.create","mat4.multiply","EQUIRECT","CLIP","TONE_MAP","multiply","create","MESH_VERTEX","CLIP_ONLY_FRAGMENT","invert","POINT_SHADOW_SIZE","FULLSCREEN_VERTEX","COMMON","SHADOW_MAP_SIZE","SPOT_ATLAS_SIZE","irradianceSH","sh","sx","width","sy","height","dPhi","dTheta","y","theta","sinT","dy","weight","x","phi","dx","dz","basis","i","k","w","data","norm","band","out","c","BACKGROUND_FRAGMENT","PREFILTER_FRAGMENT","OUTLINE_MASK_FRAGMENT","OUTLINE_MAX","WIDEN","OUTLINE_WIDEN_FRAGMENT","OUTLINE_COMPOSITE_FRAGMENT","OUTLINE_MASK","OUTLINE_WIDEN","OUTLINE_COMPOSITE","DEPTH","BACKGROUND","PREFILTER","ENV_WIDTH","ENV_LEVELS","Passes","gl","programs","resources","#environments","#shadow","#spotShadow","#pointShadow","#outline","texture","env","e","image","source","#floatTexture","prefiltered","program","framebuffer","level","hdr","blur","frame","tone","#depthTarget","#beginDepth","#drawDepth","shadow","#endDepth","toTexture","matrices","tiles","bias","half","spot","spots","toTile","#depthCube","point","face","item","casters","instances","defines","material","cutout","triplanar","viewProjection","map","targets","#outlineTargets","radius","outline","outlines","px","pixelRatio","widen","t","make","size","framebuffers","levels"],"sources":["../src/irradiance.js"],"sourcesContent":["// Diffuse light from an environment image, for the renderer: computed once per environment.\n\n/** @import { DataImage } from './material/Texture.js' */\n\n/**\n * Diffuse light from an equirectangular environment, as nine spherical harmonic coefficients (RGB\n * each, flattened), scaled so the shader evaluates them with plain polynomial terms and gets\n * irradiance divided by PI - the light a white matte surface facing that way reflects.\n * @param {DataImage} image linear RGBA floats\n * @returns {Float32Array} 27 numbers\n */\nexport function irradianceSH({ data, width, height }) {\n const sh = new Float64Array(27)\n // sample a grid of at most 128 x 64 - plenty for the lowest frequencies\n const sx = Math.max(1, Math.floor(width / 128)), sy = Math.max(1, Math.floor(height / 64))\n const dPhi = (2 * Math.PI * sx) / width, dTheta = (Math.PI * sy) / height\n for (let y = 0; y < height; y += sy) {\n const theta = ((y + 0.5 * sy) / height) * Math.PI\n const sinT = Math.sin(theta), dy = Math.cos(theta)\n const weight = dPhi * dTheta * sinT\n for (let x = 0; x < width; x += sx) {\n const phi = ((x + 0.5 * sx) / width - 0.5) * 2 * Math.PI\n const dx = Math.cos(phi) * sinT, dz = Math.sin(phi) * sinT\n const basis = [1, dy, dz, dx, dx * dy, dy * dz, 3 * dz * dz - 1, dx * dz, dx * dx - dy * dy]\n const i = (y * width + x) * 4\n for (let k = 0; k < 9; k++) {\n const w = basis[k] * weight\n sh[k * 3] += data[i] * w\n sh[k * 3 + 1] += data[i + 1] * w\n sh[k * 3 + 2] += data[i + 2] * w\n }\n }\n }\n // projection uses the normalised basis Y = norm * polynomial, and evaluation multiplies by the\n // cosine lobe's band factors (PI, 2PI/3, PI/4) and norm again; then divide by PI\n const norm = [0.282095, 0.488603, 0.488603, 0.488603, 1.092548, 1.092548, 0.315392, 1.092548, 0.546274]\n const band = [1, 2 / 3, 2 / 3, 2 / 3, 1 / 4, 1 / 4, 1 / 4, 1 / 4, 1 / 4]\n const out = new Float32Array(27)\n for (let k = 0; k < 9; k++) {\n for (let c = 0; c < 3; c++) out[k * 3 + c] = sh[k * 3 + c] * norm[k] * norm[k] * band[k]\n }\n return out\n}\n"],"mappings":";;AAWA,SAAgBgB,EAAa,EAAE,SAAM,UAAO,aAAU;CACpD,IAAMC,oBAAK,IAAI,aAAa,EAAE,GAExBC,IAAK,KAAK,IAAI,GAAG,KAAK,MAAMC,IAAQ,GAAG,CAAC,GAAGC,IAAK,KAAK,IAAI,GAAG,KAAK,MAAMC,IAAS,EAAE,CAAC,GACnFC,IAAQ,IAAI,KAAK,KAAKJ,IAAMC,GAAOI,IAAU,KAAK,KAAKH,IAAMC;CACnE,KAAK,IAAIG,IAAI,GAAGA,IAAIH,GAAQ,KAAKD,GAAI;EACnC,IAAMK,KAAUD,IAAI,KAAMJ,KAAMC,IAAU,KAAK,IACzCK,IAAO,KAAK,IAAID,CAAK,GAAGE,IAAK,KAAK,IAAIF,CAAK,GAC3CG,IAASN,IAAOC,IAASG;EAC/B,KAAK,IAAIG,IAAI,GAAGA,IAAIV,GAAO,KAAKD,GAAI;GAClC,IAAMY,MAAQD,IAAI,KAAMX,KAAMC,IAAQ,MAAO,IAAI,KAAK,IAChDY,IAAK,KAAK,IAAID,CAAG,IAAIJ,GAAMM,IAAK,KAAK,IAAIF,CAAG,IAAIJ,GAChDO,IAAQ;IAAC;IAAGN;IAAIK;IAAID;IAAIA,IAAKJ;IAAIA,IAAKK;IAAI,IAAIA,IAAKA,IAAK;IAAGD,IAAKC;IAAID,IAAKA,IAAKJ,IAAKA;GAAE,GACrFO,KAAKV,IAAIL,IAAQU,KAAK;GAC5B,KAAK,IAAIM,IAAI,GAAGA,IAAI,GAAG,KAAK;IAC1B,IAAMC,IAAIH,EAAME,KAAKP;IAGrB,AAFA,EAAGO,IAAI,MAAME,EAAKH,KAAKE,GACvB,EAAGD,IAAI,IAAI,MAAME,EAAKH,IAAI,KAAKE,GAC/B,EAAGD,IAAI,IAAI,MAAME,EAAKH,IAAI,KAAKE;GACjC;EACF;CACF;CAGA,IAAME,IAAO;EAAC;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;CAAQ,GAChGC,IAAO;EAAC;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;CAAC,GACjEC,oBAAM,IAAI,aAAa,EAAE;CAC/B,KAAK,IAAIL,IAAI,GAAGA,IAAI,GAAG,KACrB,KAAK,IAAIM,IAAI,GAAGA,IAAI,GAAG,KAAK,EAAIN,IAAI,IAAIM,KAAKxB,EAAGkB,IAAI,IAAIM,KAAKH,EAAKH,KAAKG,EAAKH,KAAKI,EAAKJ;CAExF,OAAOK;AACT"}
1
+ {"version":3,"file":"passes.js","names":["mat4.invert","mat4.create","mat4.multiply","TONE_MAP","CLIP_ONLY_FRAGMENT","FULLSCREEN_VERTEX","invert","multiply","create","MESH_VERTEX","CLIP","EQUIRECT","SPOT_ATLAS_SIZE","POINT_SHADOW_SIZE","COMMON","uvMatrix","SHADOW_MAP_SIZE","irradianceSH","sh","sx","width","sy","height","dPhi","dTheta","y","theta","sinT","dy","weight","x","phi","dx","dz","basis","i","k","w","data","norm","band","out","c","BACKGROUND_FRAGMENT","PREFILTER_FRAGMENT","OUTLINE_MASK_FRAGMENT","OUTLINE_MAX","WIDEN","OUTLINE_WIDEN_FRAGMENT","OUTLINE_COMPOSITE_FRAGMENT","OUTLINE_COVER_FRAGMENT","SMOOTH","OUTLINE_SMOOTH_WIDEN_FRAGMENT","OUTLINE_SMOOTH_COMPOSITE_FRAGMENT","OUTLINE_MASK","OUTLINE_WIDEN","OUTLINE_COMPOSITE","OUTLINE_COVER","OUTLINE_SMOOTH_WIDEN","OUTLINE_SMOOTH_COMPOSITE","DEPTH","BACKGROUND","PREFILTER","ENV_WIDTH","ENV_LEVELS","Passes","gl","programs","resources","#environments","#shadow","#spotShadow","#pointShadow","#outline","texture","env","e","image","source","#floatTexture","prefiltered","program","framebuffer","level","hdr","blur","frame","tone","#depthTarget","#beginDepth","#drawDepth","shadow","#endDepth","toTexture","matrices","tiles","bias","half","spot","spots","toTile","#depthCube","point","face","item","casters","instances","defines","material","cutout","triplanar","viewProjection","map","targets","#outlineTargets","smooth","radius","outline","outlines","px","pixelRatio","attachment","target","widen","t","buffer","make","format","msaa","samples","size","framebuffers","levels"],"sources":["../src/irradiance.js"],"sourcesContent":["// Diffuse light from an environment image, for the renderer: computed once per environment.\n\n/** @import { DataImage } from './material/Texture.js' */\n\n/**\n * Diffuse light from an equirectangular environment, as nine spherical harmonic coefficients (RGB\n * each, flattened), scaled so the shader evaluates them with plain polynomial terms and gets\n * irradiance divided by PI - the light a white matte surface facing that way reflects.\n * @param {DataImage} image linear RGBA floats\n * @returns {Float32Array} 27 numbers\n */\nexport function irradianceSH({ data, width, height }) {\n const sh = new Float64Array(27)\n // sample a grid of at most 128 x 64 - plenty for the lowest frequencies\n const sx = Math.max(1, Math.floor(width / 128)), sy = Math.max(1, Math.floor(height / 64))\n const dPhi = (2 * Math.PI * sx) / width, dTheta = (Math.PI * sy) / height\n for (let y = 0; y < height; y += sy) {\n const theta = ((y + 0.5 * sy) / height) * Math.PI\n const sinT = Math.sin(theta), dy = Math.cos(theta)\n const weight = dPhi * dTheta * sinT\n for (let x = 0; x < width; x += sx) {\n const phi = ((x + 0.5 * sx) / width - 0.5) * 2 * Math.PI\n const dx = Math.cos(phi) * sinT, dz = Math.sin(phi) * sinT\n const basis = [1, dy, dz, dx, dx * dy, dy * dz, 3 * dz * dz - 1, dx * dz, dx * dx - dy * dy]\n const i = (y * width + x) * 4\n for (let k = 0; k < 9; k++) {\n const w = basis[k] * weight\n sh[k * 3] += data[i] * w\n sh[k * 3 + 1] += data[i + 1] * w\n sh[k * 3 + 2] += data[i + 2] * w\n }\n }\n }\n // projection uses the normalised basis Y = norm * polynomial, and evaluation multiplies by the\n // cosine lobe's band factors (PI, 2PI/3, PI/4) and norm again; then divide by PI\n const norm = [0.282095, 0.488603, 0.488603, 0.488603, 1.092548, 1.092548, 0.315392, 1.092548, 0.546274]\n const band = [1, 2 / 3, 2 / 3, 2 / 3, 1 / 4, 1 / 4, 1 / 4, 1 / 4, 1 / 4]\n const out = new Float32Array(27)\n for (let k = 0; k < 9; k++) {\n for (let c = 0; c < 3; c++) out[k * 3 + c] = sh[k * 3 + c] * norm[k] * norm[k] * band[k]\n }\n return out\n}\n"],"mappings":";;AAWA,SAAgBiB,EAAa,EAAE,SAAM,UAAO,aAAU;CACpD,IAAMC,oBAAK,IAAI,aAAa,EAAE,GAExBC,IAAK,KAAK,IAAI,GAAG,KAAK,MAAMC,IAAQ,GAAG,CAAC,GAAGC,IAAK,KAAK,IAAI,GAAG,KAAK,MAAMC,IAAS,EAAE,CAAC,GACnFC,IAAQ,IAAI,KAAK,KAAKJ,IAAMC,GAAOI,IAAU,KAAK,KAAKH,IAAMC;CACnE,KAAK,IAAIG,IAAI,GAAGA,IAAIH,GAAQ,KAAKD,GAAI;EACnC,IAAMK,KAAUD,IAAI,KAAMJ,KAAMC,IAAU,KAAK,IACzCK,IAAO,KAAK,IAAID,CAAK,GAAGE,IAAK,KAAK,IAAIF,CAAK,GAC3CG,IAASN,IAAOC,IAASG;EAC/B,KAAK,IAAIG,IAAI,GAAGA,IAAIV,GAAO,KAAKD,GAAI;GAClC,IAAMY,MAAQD,IAAI,KAAMX,KAAMC,IAAQ,MAAO,IAAI,KAAK,IAChDY,IAAK,KAAK,IAAID,CAAG,IAAIJ,GAAMM,IAAK,KAAK,IAAIF,CAAG,IAAIJ,GAChDO,IAAQ;IAAC;IAAGN;IAAIK;IAAID;IAAIA,IAAKJ;IAAIA,IAAKK;IAAI,IAAIA,IAAKA,IAAK;IAAGD,IAAKC;IAAID,IAAKA,IAAKJ,IAAKA;GAAE,GACrFO,KAAKV,IAAIL,IAAQU,KAAK;GAC5B,KAAK,IAAIM,IAAI,GAAGA,IAAI,GAAG,KAAK;IAC1B,IAAMC,IAAIH,EAAME,KAAKP;IAGrB,AAFA,EAAGO,IAAI,MAAME,EAAKH,KAAKE,GACvB,EAAGD,IAAI,IAAI,MAAME,EAAKH,IAAI,KAAKE,GAC/B,EAAGD,IAAI,IAAI,MAAME,EAAKH,IAAI,KAAKE;GACjC;EACF;CACF;CAGA,IAAME,IAAO;EAAC;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;CAAQ,GAChGC,IAAO;EAAC;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;EAAG,IAAI;CAAC,GACjEC,oBAAM,IAAI,aAAa,EAAE;CAC/B,KAAK,IAAIL,IAAI,GAAGA,IAAI,GAAG,KACrB,KAAK,IAAIM,IAAI,GAAGA,IAAI,GAAG,KAAK,EAAIN,IAAI,IAAIM,KAAKxB,EAAGkB,IAAI,IAAIM,KAAKH,EAAKH,KAAKG,EAAKH,KAAKI,EAAKJ;CAExF,OAAOK;AACT"}
package/dist/phoria2.js CHANGED
@@ -1 +1 @@
1
- export { R as AmbientLight, bt as Box3, Z as CAMERA_PRESETS, $ as Camera, ht as Clip, gt as Color, r as Curve, z as DirectionalLight, y as Drawable, ot as Euler, G as Fog, L as Geometry, nt as Group, B as HemisphereLight, b as InstancedMesh, pt as LIGHT_LIMITS, x as Label, V as Light, S as Lines, xt as Mat4, I as Material, C as Mesh, it as Node, mt as NullRenderer, ft as OrbitControl, et as OrthographicCamera, tt as PerspectiveCamera, Ct as PhoriaError, H as PointLight, w as Points, at as Quat, Y as Ray, J as Raycaster, W as Scene, U as SpotLight, K as Texture, St as Vec3, T as View, E as WebGLRenderer, c as axes, l as box, Q as cameraPreset, t as create, i as curve, u as cylinder, d as edges, a as ellipse, f as extrude, o as fromPolygons, p as grid, m as icosphere, h as lathe, q as loadTexture, s as outline, g as plane, n as registerType, _ as sphere, v as torus } from "./core.js";
1
+ export { j as AmbientLight, xt as Box3, H as CAMERA_PRESETS, W as Camera, gt as Clip, _t as Color, r as Curve, M as DirectionalLight, X as Drawable, ht as Euler, R as Fog, ct as Geometry, nt as Group, N as HemisphereLight, Z as InstancedMesh, J as LIGHT_LIMITS, Q as Label, P as Light, $ as Lines, St as Mat4, at as Material, et as Mesh, it as Node, Y as NullRenderer, q as OrbitControl, G as OrthographicCamera, K as PerspectiveCamera, wt as PhoriaError, F as PointLight, tt as Points, lt as Quat, B as Ray, z as Raycaster, L as Scene, I as SpotLight, ot as Texture, Ct as Vec3, y as View, b as WebGLRenderer, c as axes, l as box, U as cameraPreset, t as create, i as curve, u as cylinder, d as edges, a as ellipse, f as extrude, o as fromPolygons, p as grid, m as icosphere, h as lathe, st as loadTexture, s as outline, g as plane, n as registerType, _ as sphere, v as torus } from "./core.js";
package/dist/picking.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as e, Ft as t, M as n, N as r, Nt as i, P as a, k as o } from "./core.js";
1
+ import { D as e, It as t, O as n, Pt as r, S as i, k as a, w as o } from "./core.js";
2
2
  // src/webgl/picking.js
3
3
  var s = 33, c = 4, l = `precision highp float;
4
4
  precision highp int;
@@ -9,7 +9,7 @@ in vec3 vWorldPosition;
9
9
  uniform uint uPickId;
10
10
  layout(location = 0) out uvec4 pickOut;
11
11
  ${o}
12
- ${e}
12
+ ${i}
13
13
  void main() {
14
14
  #ifdef CLIP
15
15
  clipAway(vWorldPosition);
@@ -21,9 +21,9 @@ if (dot(p, p) > 1.0) discard;
21
21
  pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
22
22
  }
23
23
  `, u = {
24
- mesh: [r, l],
24
+ mesh: [n, l],
25
25
  points: [a, l],
26
- lines: [n, l]
26
+ lines: [e, l]
27
27
  }, d = class {
28
28
  #e = null;
29
29
  #t = /* @__PURE__ */ new Uint32Array(4356);
@@ -120,24 +120,19 @@ pickOut = uvec4(uPickId, vPickElement, floatBitsToUint(gl_FragCoord.z), 1u);
120
120
  let e = this.gl;
121
121
  return this.#a = e.createBuffer(), e.bindBuffer(e.PIXEL_PACK_BUFFER, this.#a), e.bufferData(e.PIXEL_PACK_BUFFER, this.#t.byteLength, e.STREAM_READ), e.bindBuffer(e.PIXEL_PACK_BUFFER, null), this.#a;
122
122
  }
123
- #u(e, t, n, r, a) {
123
+ #u(e, t, n, i, a) {
124
124
  let o = this.gl, { node: c, geometry: l, material: d, worldMatrix: f, instances: p } = e, m = c.drawMode, h = m === "points" ? "points" : m === "lines" ? "lines" : "mesh", g = ["PICK"];
125
125
  p && g.push("INSTANCED"), h === "points" && (d.sizeAttenuation && g.push("SIZE_ATTENUATION"), d.map || g.push("ROUND")), h === "mesh" && e.clip && g.push("CLIP");
126
126
  let _ = this.programs.ready(`pick-${h}`, g, u[h]);
127
- if (o.useProgram(_.program), _.set("uView", n.camera.view), _.set("uProjection", this.#n), _.set("uViewProjection", this.#r), _.set("uModel", f), _.set("uPickId", t), _.set("uHighlightIndex", -2), _.set("uUvTransform", [
128
- 1,
129
- 1,
130
- 0,
131
- 0
132
- ]), e.clip && _.set("uClipPlane", e.clip.plane), h === "lines") {
127
+ if (o.useProgram(_.program), _.set("uView", n.camera.view), _.set("uProjection", this.#n), _.set("uViewProjection", this.#r), _.set("uModel", f), _.set("uPickId", t), _.set("uHighlightIndex", -2), e.clip && _.set("uClipPlane", e.clip.plane), h === "lines") {
133
128
  o.disable(o.CULL_FACE), _.set("uResolution", [s, s]), _.set("uWidth", d.width * a), _.set("uNear", n.camera.near);
134
129
  let e = this.resources.lines(l);
135
130
  o.bindVertexArray(e.vao), o.drawArraysInstanced(o.TRIANGLE_STRIP, 0, 4, Math.min(e.count, Math.floor(l.drawnCount / 2)));
136
131
  } else if (h === "points") {
137
- o.disable(o.CULL_FACE), _.set("uSize", d.sizeAttenuation ? d.size : d.size * a), _.set("uScale", n.camera.projection[5] * r / 2);
132
+ o.disable(o.CULL_FACE), _.set("uSize", d.sizeAttenuation ? d.size : d.size * a), _.set("uScale", n.camera.projection[5] * i / 2);
138
133
  let e = this.resources.mesh(l, null, !1);
139
134
  o.bindVertexArray(e.vao), o.drawArrays(o.POINTS, 0, l.drawnVertices);
140
- } else _.set("uNormalMatrix", this.#i), d.depthTest ? o.enable(o.DEPTH_TEST) : o.disable(o.DEPTH_TEST), d.doubleSided || e.clip?.cap ? o.disable(o.CULL_FACE) : (o.enable(o.CULL_FACE), o.cullFace(o.BACK), o.frontFace(i(f) < 0 ? o.CW : o.CCW)), this.resources.drawTriangles(l, p);
135
+ } else _.set("uNormalMatrix", this.#i), d.depthTest ? o.enable(o.DEPTH_TEST) : o.disable(o.DEPTH_TEST), d.doubleSided || e.clip?.cap ? o.disable(o.CULL_FACE) : (o.enable(o.CULL_FACE), o.cullFace(o.BACK), o.frontFace(r(f) < 0 ? o.CW : o.CCW)), this.resources.drawTriangles(l, p);
141
136
  }
142
137
  #d() {
143
138
  if (this.#e) return this.#e;
@@ -1 +1 @@
1
- {"version":3,"file":"picking.js","names":["mat4.determinant","CLIP","multiply","LINES_VERTEX","MESH_VERTEX","determinant","POINTS_VERTEX","COMMON","REGION","TOLERANCE","PICK_FRAGMENT","SOURCES","Picker","gl","programs","resources","#target","#pack","#waiting","region","#drawRegion","frame","x","y","width","height","pixelRatio","#pixels","#decode","buffer","#readBuffer","fence","poll","resolve","items","pickable","target","#ensureTarget","s","cx","cy","zoom","#projection","#viewProjection","#draw","item","i","p","at","py","px","best","bestX","bestY","bestD","dy","dx","d","o","id","depth","ndc","mode","node","kind","defines","instances","material","program","worldMatrix","buffers","geometry","#normal","color","framebuffer","seen","ok","n","v"],"sources":[],"mappings":""}
1
+ {"version":3,"file":"picking.js","names":["mat4.determinant","LINES_VERTEX","multiply","MESH_VERTEX","determinant","CLIP","POINTS_VERTEX","COMMON","REGION","TOLERANCE","PICK_FRAGMENT","SOURCES","Picker","gl","programs","resources","#target","#pack","#waiting","region","#drawRegion","frame","x","y","width","height","pixelRatio","#pixels","#decode","buffer","#readBuffer","fence","poll","resolve","items","pickable","target","#ensureTarget","s","cx","cy","zoom","#projection","#viewProjection","#draw","item","i","p","at","py","px","best","bestX","bestY","bestD","dy","dx","d","o","id","depth","ndc","mode","node","kind","defines","instances","material","program","worldMatrix","buffers","geometry","#normal","color","framebuffer","seen","ok","n","v"],"sources":[],"mappings":""}
package/dist/snapshot.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Ct as e } from "./core.js";
1
+ import { wt as e } from "./core.js";
2
2
  // src/snapshot.js
3
3
  function t(t, n, { type: a = "image/png", quality: o, labels: s = !0 } = {}, c = []) {
4
4
  let l = t;
package/dist/tooltip.js CHANGED
@@ -1,10 +1,10 @@
1
- import { Dt as e, kt as t } from "./core.js";
1
+ import { At as e, Ot as t } from "./core.js";
2
2
  // src/tooltip.js
3
3
  var n = "\n:where(.phoria-tooltip) { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; max-width: 320px;\n padding: 6px 10px; border-radius: 6px; background: rgba(20, 20, 24, 0.92); color: #fff;\n font: 12px/1.45 system-ui, sans-serif; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); white-space: pre-line; }\n:where(.phoria-tooltip-title) { font-weight: 600; }\n:where(.phoria-tooltip-rows) { display: grid; grid-template-columns: auto auto; column-gap: 12px; }\n:where(.phoria-tooltip-rows > :nth-child(odd)) { opacity: 0.7; }\n:where(.phoria-tooltip-rows > :nth-child(even)) { text-align: right; font-variant-numeric: tabular-nums; }\n", r = 14, i = class {
4
4
  el;
5
5
  content;
6
6
  constructor(r, i = "") {
7
- if (typeof r != "function" && t("View", `tooltip() takes a function (hit) => text, got ${e(r)}`), this.content = r, !document.getElementById("phoria-tooltip-style")) {
7
+ if (typeof r != "function" && e("View", `tooltip() takes a function (hit) => text, got ${t(r)}`), this.content = r, !document.getElementById("phoria-tooltip-style")) {
8
8
  let e = document.createElement("style");
9
9
  e.id = "phoria-tooltip-style", e.textContent = n, document.head.prepend(e);
10
10
  }
@@ -48,7 +48,7 @@ function a(n) {
48
48
  }
49
49
  return e;
50
50
  }
51
- return t("View", `a tooltip function returns text, an element or { title, rows }, got ${e(n)}`);
51
+ return e("View", `a tooltip function returns text, an element or { title, rows }, got ${t(n)}`);
52
52
  }
53
53
  export { i as Tooltip };
54
54
 
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":["describe","fail","STYLE","GAP","Tooltip","content","style","className","hit","render","x","y","w","h","left","top","box","title","rows","entries","name","value","n","v"],"sources":["../src/tooltip.js"],"sourcesContent":["// The hover tooltip: one element that follows the pointer and shows what the app says about the\n// thing under it. Its default look is in a :where() rule, which has no specificity, so any CSS for\n// .phoria-tooltip overrides it.\nimport { describe, fail } from './validate.js'\n\n/** @import { Hit } from './Raycaster.js' */\n\n/**\n * What a tooltip function returns: text (new lines kept), an element, or a title with rows of\n * name/value pairs. null (or '') shows nothing.\n * @typedef {string | number | Node | { title?: string, rows?: Record<string, unknown> | Array<[string, unknown]> } | null | undefined | false} TooltipContent\n */\n\nconst STYLE = `\n:where(.phoria-tooltip) { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; max-width: 320px;\n padding: 6px 10px; border-radius: 6px; background: rgba(20, 20, 24, 0.92); color: #fff;\n font: 12px/1.45 system-ui, sans-serif; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); white-space: pre-line; }\n:where(.phoria-tooltip-title) { font-weight: 600; }\n:where(.phoria-tooltip-rows) { display: grid; grid-template-columns: auto auto; column-gap: 12px; }\n:where(.phoria-tooltip-rows > :nth-child(odd)) { opacity: 0.7; }\n:where(.phoria-tooltip-rows > :nth-child(even)) { text-align: right; font-variant-numeric: tabular-nums; }\n`\n// space between the pointer and the tooltip, in CSS pixels\nconst GAP = 14\n\nexport class Tooltip {\n /** @type {HTMLDivElement} */ el\n /** @type {(hit: Hit) => TooltipContent} */ content\n\n /** @param {(hit: Hit) => TooltipContent} content @param {string} [className] */\n constructor(content, className = '') {\n if (typeof content !== 'function') fail('View', `tooltip() takes a function (hit) => text, got ${describe(content)}`)\n this.content = content\n if (!document.getElementById('phoria-tooltip-style')) {\n const style = document.createElement('style')\n style.id = 'phoria-tooltip-style'\n style.textContent = STYLE\n document.head.prepend(style)\n }\n this.el = document.createElement('div')\n this.el.className = `phoria-tooltip${className ? ` ${className}` : ''}`\n this.el.setAttribute('role', 'tooltip')\n this.el.hidden = true\n document.body.append(this.el)\n }\n\n /** Show what the content function says about a hit, near the pointer. @param {Hit} hit @param {number} x @param {number} y */\n show(hit, x, y) {\n const content = this.content(hit)\n if (content === null || content === undefined || content === false || content === '') return this.hide()\n this.el.replaceChildren(render(content))\n this.el.hidden = false\n this.move(x, y)\n }\n\n /** Follow the pointer, staying inside the window. @param {number} x @param {number} y client pixels */\n move(x, y) {\n if (this.el.hidden) return\n const w = this.el.offsetWidth, h = this.el.offsetHeight\n const left = x + GAP + w > window.innerWidth ? x - GAP - w : x + GAP\n const top = y + GAP + h > window.innerHeight ? y - GAP - h : y + GAP\n this.el.style.transform = `translate(${Math.round(Math.max(0, left))}px, ${Math.round(Math.max(0, top))}px)`\n }\n\n hide() {\n this.el.hidden = true\n }\n\n dispose() {\n this.el.remove()\n }\n}\n\n/** @param {TooltipContent} content @returns {Node} */\nfunction render(content) {\n if (typeof content === 'string' || typeof content === 'number') return document.createTextNode(String(content))\n if (content instanceof Node) return content\n if (typeof content === 'object' && content && ('title' in content || 'rows' in content)) {\n const box = document.createDocumentFragment()\n if (content.title !== undefined) {\n const title = document.createElement('div')\n title.className = 'phoria-tooltip-title'\n title.textContent = String(content.title)\n box.append(title)\n }\n if (content.rows) {\n const rows = document.createElement('div')\n rows.className = 'phoria-tooltip-rows'\n const entries = Array.isArray(content.rows) ? content.rows : Object.entries(content.rows)\n for (const [name, value] of entries) {\n const n = document.createElement('span'), v = document.createElement('span')\n n.textContent = String(name)\n v.textContent = typeof value === 'number' ? value.toLocaleString() : String(value)\n rows.append(n, v)\n }\n box.append(rows)\n }\n return box\n }\n return fail('View', `a tooltip function returns text, an element or { title, rows }, got ${describe(content)}`)\n}\n"],"mappings":";;AAaA,IAAME,IAAQ,2oBAURC,IAAM,IAECC,IAAb,MAAqB;CACW;CACc;CAG5C,YAAY,GAAS,IAAY,IAAI;EAGnC,IAFI,OAAOC,KAAY,cAAYJ,EAAK,QAAQ,iDAAiDD,EAASK,CAAO,GAAG,GACpH,KAAK,UAAUA,GACX,CAAC,SAAS,eAAe,sBAAsB,GAAG;GACpD,IAAMC,IAAQ,SAAS,cAAc,OAAO;GAG5C,AAFA,EAAM,KAAK,wBACX,EAAM,cAAcJ,GACpB,SAAS,KAAK,QAAQI,CAAK;EAC7B;EAKA,AAJA,KAAK,KAAK,SAAS,cAAc,KAAK,GACtC,KAAK,GAAG,YAAY,iBAAiBC,IAAY,IAAIA,MAAc,MACnE,KAAK,GAAG,aAAa,QAAQ,SAAS,GACtC,KAAK,GAAG,SAAS,IACjB,SAAS,KAAK,OAAO,KAAK,EAAE;CAC9B;CAGA,KAAK,GAAK,GAAG,GAAG;EACd,IAAMF,IAAU,KAAK,QAAQG,CAAG;EAChC,IAAIH,KAAY,QAAiCA,MAAY,MAASA,MAAY,IAAI,OAAO,KAAK,KAAK;EAGvG,AAFA,KAAK,GAAG,gBAAgBI,EAAOJ,CAAO,CAAC,GACvC,KAAK,GAAG,SAAS,IACjB,KAAK,KAAKK,GAAGC,CAAC;CAChB;CAGA,KAAK,GAAG,GAAG;EACT,IAAI,KAAK,GAAG,QAAQ;EACpB,IAAMC,IAAI,KAAK,GAAG,aAAaC,IAAI,KAAK,GAAG,cACrCC,IAAOJ,IAAIP,IAAMS,IAAI,OAAO,aAAaF,IAAIP,IAAMS,IAAIF,IAAIP,GAC3DY,IAAMJ,IAAIR,IAAMU,IAAI,OAAO,cAAcF,IAAIR,IAAMU,IAAIF,IAAIR;EACjE,KAAK,GAAG,MAAM,YAAY,aAAa,KAAK,MAAM,KAAK,IAAI,GAAGW,CAAI,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,IAAI,GAAGC,CAAG,CAAC,EAAE;CAC1G;CAEA,OAAO;EACL,KAAK,GAAG,SAAS;CACnB;CAEA,UAAU;EACR,KAAK,GAAG,OAAO;CACjB;AACF;AAGA,SAASN,EAAO,GAAS;CACvB,IAAI,OAAOJ,KAAY,YAAY,OAAOA,KAAY,UAAU,OAAO,SAAS,eAAe,OAAOA,CAAO,CAAC;CAC9G,IAAIA,aAAmB,MAAM,OAAOA;CACpC,IAAI,OAAOA,KAAY,YAAYA,MAAY,WAAWA,KAAW,UAAUA,IAAU;EACvF,IAAMW,IAAM,SAAS,uBAAuB;EAC5C,IAAIX,EAAQ,UAAU,KAAA,GAAW;GAC/B,IAAMY,IAAQ,SAAS,cAAc,KAAK;GAG1C,AAFA,EAAM,YAAY,wBAClB,EAAM,cAAc,OAAOZ,EAAQ,KAAK,GACxCW,EAAI,OAAOC,CAAK;EAClB;EACA,IAAIZ,EAAQ,MAAM;GAChB,IAAMa,IAAO,SAAS,cAAc,KAAK;GACzC,EAAK,YAAY;GACjB,IAAMC,IAAU,MAAM,QAAQd,EAAQ,IAAI,IAAIA,EAAQ,OAAO,OAAO,QAAQA,EAAQ,IAAI;GACxF,KAAK,IAAM,CAACe,GAAMC,MAAUF,GAAS;IACnC,IAAMG,IAAI,SAAS,cAAc,MAAM,GAAGC,IAAI,SAAS,cAAc,MAAM;IAG3E,AAFA,EAAE,cAAc,OAAOH,CAAI,GAC3B,EAAE,cAAc,OAAOC,KAAU,WAAWA,EAAM,eAAe,IAAI,OAAOA,CAAK,GACjFH,EAAK,OAAOI,GAAGC,CAAC;GAClB;GACA,EAAI,OAAOL,CAAI;EACjB;EACA,OAAOF;CACT;CACA,OAAOf,EAAK,QAAQ,uEAAuED,EAASK,CAAO,GAAG;AAChH"}
1
+ {"version":3,"file":"tooltip.js","names":["fail","describe","STYLE","GAP","Tooltip","content","style","className","hit","render","x","y","w","h","left","top","box","title","rows","entries","name","value","n","v"],"sources":["../src/tooltip.js"],"sourcesContent":["// The hover tooltip: one element that follows the pointer and shows what the app says about the\n// thing under it. Its default look is in a :where() rule, which has no specificity, so any CSS for\n// .phoria-tooltip overrides it.\nimport { describe, fail } from './validate.js'\n\n/** @import { Hit } from './Raycaster.js' */\n\n/**\n * What a tooltip function returns: text (new lines kept), an element, or a title with rows of\n * name/value pairs. null (or '') shows nothing.\n * @typedef {string | number | Node | { title?: string, rows?: Record<string, unknown> | Array<[string, unknown]> } | null | undefined | false} TooltipContent\n */\n\nconst STYLE = `\n:where(.phoria-tooltip) { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; max-width: 320px;\n padding: 6px 10px; border-radius: 6px; background: rgba(20, 20, 24, 0.92); color: #fff;\n font: 12px/1.45 system-ui, sans-serif; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); white-space: pre-line; }\n:where(.phoria-tooltip-title) { font-weight: 600; }\n:where(.phoria-tooltip-rows) { display: grid; grid-template-columns: auto auto; column-gap: 12px; }\n:where(.phoria-tooltip-rows > :nth-child(odd)) { opacity: 0.7; }\n:where(.phoria-tooltip-rows > :nth-child(even)) { text-align: right; font-variant-numeric: tabular-nums; }\n`\n// space between the pointer and the tooltip, in CSS pixels\nconst GAP = 14\n\nexport class Tooltip {\n /** @type {HTMLDivElement} */ el\n /** @type {(hit: Hit) => TooltipContent} */ content\n\n /** @param {(hit: Hit) => TooltipContent} content @param {string} [className] */\n constructor(content, className = '') {\n if (typeof content !== 'function') fail('View', `tooltip() takes a function (hit) => text, got ${describe(content)}`)\n this.content = content\n if (!document.getElementById('phoria-tooltip-style')) {\n const style = document.createElement('style')\n style.id = 'phoria-tooltip-style'\n style.textContent = STYLE\n document.head.prepend(style)\n }\n this.el = document.createElement('div')\n this.el.className = `phoria-tooltip${className ? ` ${className}` : ''}`\n this.el.setAttribute('role', 'tooltip')\n this.el.hidden = true\n document.body.append(this.el)\n }\n\n /** Show what the content function says about a hit, near the pointer. @param {Hit} hit @param {number} x @param {number} y */\n show(hit, x, y) {\n const content = this.content(hit)\n if (content === null || content === undefined || content === false || content === '') return this.hide()\n this.el.replaceChildren(render(content))\n this.el.hidden = false\n this.move(x, y)\n }\n\n /** Follow the pointer, staying inside the window. @param {number} x @param {number} y client pixels */\n move(x, y) {\n if (this.el.hidden) return\n const w = this.el.offsetWidth, h = this.el.offsetHeight\n const left = x + GAP + w > window.innerWidth ? x - GAP - w : x + GAP\n const top = y + GAP + h > window.innerHeight ? y - GAP - h : y + GAP\n this.el.style.transform = `translate(${Math.round(Math.max(0, left))}px, ${Math.round(Math.max(0, top))}px)`\n }\n\n hide() {\n this.el.hidden = true\n }\n\n dispose() {\n this.el.remove()\n }\n}\n\n/** @param {TooltipContent} content @returns {Node} */\nfunction render(content) {\n if (typeof content === 'string' || typeof content === 'number') return document.createTextNode(String(content))\n if (content instanceof Node) return content\n if (typeof content === 'object' && content && ('title' in content || 'rows' in content)) {\n const box = document.createDocumentFragment()\n if (content.title !== undefined) {\n const title = document.createElement('div')\n title.className = 'phoria-tooltip-title'\n title.textContent = String(content.title)\n box.append(title)\n }\n if (content.rows) {\n const rows = document.createElement('div')\n rows.className = 'phoria-tooltip-rows'\n const entries = Array.isArray(content.rows) ? content.rows : Object.entries(content.rows)\n for (const [name, value] of entries) {\n const n = document.createElement('span'), v = document.createElement('span')\n n.textContent = String(name)\n v.textContent = typeof value === 'number' ? value.toLocaleString() : String(value)\n rows.append(n, v)\n }\n box.append(rows)\n }\n return box\n }\n return fail('View', `a tooltip function returns text, an element or { title, rows }, got ${describe(content)}`)\n}\n"],"mappings":";;AAaA,IAAME,IAAQ,2oBAURC,IAAM,IAECC,IAAb,MAAqB;CACW;CACc;CAG5C,YAAY,GAAS,IAAY,IAAI;EAGnC,IAFI,OAAOC,KAAY,cAAYL,EAAK,QAAQ,iDAAiDC,EAASI,CAAO,GAAG,GACpH,KAAK,UAAUA,GACX,CAAC,SAAS,eAAe,sBAAsB,GAAG;GACpD,IAAMC,IAAQ,SAAS,cAAc,OAAO;GAG5C,AAFA,EAAM,KAAK,wBACX,EAAM,cAAcJ,GACpB,SAAS,KAAK,QAAQI,CAAK;EAC7B;EAKA,AAJA,KAAK,KAAK,SAAS,cAAc,KAAK,GACtC,KAAK,GAAG,YAAY,iBAAiBC,IAAY,IAAIA,MAAc,MACnE,KAAK,GAAG,aAAa,QAAQ,SAAS,GACtC,KAAK,GAAG,SAAS,IACjB,SAAS,KAAK,OAAO,KAAK,EAAE;CAC9B;CAGA,KAAK,GAAK,GAAG,GAAG;EACd,IAAMF,IAAU,KAAK,QAAQG,CAAG;EAChC,IAAIH,KAAY,QAAiCA,MAAY,MAASA,MAAY,IAAI,OAAO,KAAK,KAAK;EAGvG,AAFA,KAAK,GAAG,gBAAgBI,EAAOJ,CAAO,CAAC,GACvC,KAAK,GAAG,SAAS,IACjB,KAAK,KAAKK,GAAGC,CAAC;CAChB;CAGA,KAAK,GAAG,GAAG;EACT,IAAI,KAAK,GAAG,QAAQ;EACpB,IAAMC,IAAI,KAAK,GAAG,aAAaC,IAAI,KAAK,GAAG,cACrCC,IAAOJ,IAAIP,IAAMS,IAAI,OAAO,aAAaF,IAAIP,IAAMS,IAAIF,IAAIP,GAC3DY,IAAMJ,IAAIR,IAAMU,IAAI,OAAO,cAAcF,IAAIR,IAAMU,IAAIF,IAAIR;EACjE,KAAK,GAAG,MAAM,YAAY,aAAa,KAAK,MAAM,KAAK,IAAI,GAAGW,CAAI,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,IAAI,GAAGC,CAAG,CAAC,EAAE;CAC1G;CAEA,OAAO;EACL,KAAK,GAAG,SAAS;CACnB;CAEA,UAAU;EACR,KAAK,GAAG,OAAO;CACjB;AACF;AAGA,SAASN,EAAO,GAAS;CACvB,IAAI,OAAOJ,KAAY,YAAY,OAAOA,KAAY,UAAU,OAAO,SAAS,eAAe,OAAOA,CAAO,CAAC;CAC9G,IAAIA,aAAmB,MAAM,OAAOA;CACpC,IAAI,OAAOA,KAAY,YAAYA,MAAY,WAAWA,KAAW,UAAUA,IAAU;EACvF,IAAMW,IAAM,SAAS,uBAAuB;EAC5C,IAAIX,EAAQ,UAAU,KAAA,GAAW;GAC/B,IAAMY,IAAQ,SAAS,cAAc,KAAK;GAG1C,AAFA,EAAM,YAAY,wBAClB,EAAM,cAAc,OAAOZ,EAAQ,KAAK,GACxCW,EAAI,OAAOC,CAAK;EAClB;EACA,IAAIZ,EAAQ,MAAM;GAChB,IAAMa,IAAO,SAAS,cAAc,KAAK;GACzC,EAAK,YAAY;GACjB,IAAMC,IAAU,MAAM,QAAQd,EAAQ,IAAI,IAAIA,EAAQ,OAAO,OAAO,QAAQA,EAAQ,IAAI;GACxF,KAAK,IAAM,CAACe,GAAMC,MAAUF,GAAS;IACnC,IAAMG,IAAI,SAAS,cAAc,MAAM,GAAGC,IAAI,SAAS,cAAc,MAAM;IAG3E,AAFA,EAAE,cAAc,OAAOH,CAAI,GAC3B,EAAE,cAAc,OAAOC,KAAU,WAAWA,EAAM,eAAe,IAAI,OAAOA,CAAK,GACjFH,EAAK,OAAOI,GAAGC,CAAC;GAClB;GACA,EAAI,OAAOL,CAAI;EACjB;EACA,OAAOF;CACT;CACA,OAAOhB,EAAK,QAAQ,uEAAuEC,EAASI,CAAO,GAAG;AAChH"}
@@ -134,8 +134,12 @@ export declare class OrbitControl {
134
134
  zoomAt(factor: number, x: number, y: number): void;
135
135
  /** Move the camera and target together by screen pixels; the scene follows the pointer. @param {number} dx @param {number} dy */
136
136
  panBy(dx: number, dy: number): void;
137
- /** Apply inertia and auto-rotate; the View calls this each frame. @param {number} dt seconds */
138
- update(dt: number): void;
137
+ /**
138
+ * Apply inertia and auto-rotate; the View calls this each frame.
139
+ * @param {number} dt seconds
140
+ * @param {boolean} [still] hold auto-rotation - the View passes its reducedMotion
141
+ */
142
+ update(dt: number, still?: boolean): void;
139
143
  /**
140
144
  * Let go of the gesture under way - for an app taking the pointer over, such as to drag
141
145
  * something across the scene. The camera stays where it is; the next press orbits as usual.