phoria2 1.2.0 → 1.4.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 (69) hide show
  1. package/README.md +11 -9
  2. package/dist/bloom.js +4 -4
  3. package/dist/bloom.js.map +1 -1
  4. package/dist/charts.js +527 -510
  5. package/dist/charts.js.map +1 -1
  6. package/dist/core.js +1760 -1170
  7. package/dist/core.js.map +1 -1
  8. package/dist/debug.js +297 -0
  9. package/dist/debug.js.map +1 -0
  10. package/dist/edit.js +60 -60
  11. package/dist/edit.js.map +1 -1
  12. package/dist/explain.js +32 -13
  13. package/dist/explain.js.map +1 -1
  14. package/dist/gltf.js +155 -155
  15. package/dist/gltf.js.map +1 -1
  16. package/dist/keyboard.js +188 -0
  17. package/dist/keyboard.js.map +1 -0
  18. package/dist/motion.js +35 -35
  19. package/dist/motion.js.map +1 -1
  20. package/dist/particles.js +187 -114
  21. package/dist/particles.js.map +1 -1
  22. package/dist/passes.js +116 -104
  23. package/dist/passes.js.map +1 -1
  24. package/dist/phoria2.js +1 -1
  25. package/dist/picking.js +95 -62
  26. package/dist/picking.js.map +1 -1
  27. package/dist/snapshot.js +1 -1
  28. package/dist/tooltip.js +1 -1
  29. package/dist/types/View.d.ts +27 -0
  30. package/dist/types/area.d.ts +18 -0
  31. package/dist/types/debug.d.ts +74 -0
  32. package/dist/types/explain.d.ts +4 -0
  33. package/dist/types/frame.d.ts +5 -0
  34. package/dist/types/geometry/Geometry.d.ts +16 -0
  35. package/dist/types/index.d.ts +2 -0
  36. package/dist/types/material/Material.d.ts +67 -0
  37. package/dist/types/material/Texture.d.ts +18 -2
  38. package/dist/types/particles/Emitter.d.ts +39 -2
  39. package/dist/types/scene/drawables.d.ts +23 -2
  40. package/dist/types/watch.d.ts +8 -1
  41. package/dist/types/webgl/hooks.d.ts +48 -0
  42. package/dist/types/webgl/passes.d.ts +4 -0
  43. package/dist/types/webgl/programs.d.ts +15 -5
  44. package/dist/types/webgl/resources.d.ts +12 -2
  45. package/dist/types/webgl/shaders.d.ts +41 -5
  46. package/llms-full.txt +275 -1
  47. package/llms.txt +1 -1
  48. package/package.json +1 -1
  49. package/schema/scene.schema.json +75 -0
  50. package/src/View.js +121 -7
  51. package/src/area.js +131 -0
  52. package/src/charts/marks.js +29 -2
  53. package/src/debug.js +283 -0
  54. package/src/explain.js +19 -0
  55. package/src/frame.js +7 -2
  56. package/src/geometry/Geometry.js +16 -1
  57. package/src/index.js +1 -0
  58. package/src/material/Material.js +130 -4
  59. package/src/material/Texture.js +55 -2
  60. package/src/particles/Emitter.js +121 -10
  61. package/src/scene/drawables.js +89 -8
  62. package/src/watch.js +26 -3
  63. package/src/webgl/WebGLRenderer.js +55 -7
  64. package/src/webgl/hooks.js +121 -0
  65. package/src/webgl/passes.js +17 -2
  66. package/src/webgl/picking.js +45 -3
  67. package/src/webgl/programs.js +20 -9
  68. package/src/webgl/resources.js +169 -15
  69. package/src/webgl/shaders.js +545 -38
package/dist/gltf.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"gltf.js","names":["quat.normalize","quat.fromMat3","Lines","PointLight","OrthographicCamera","SpotLight","PerspectiveCamera","DirectionalLight","Drawable","Material","Geometry","Mesh","normalize","warnOnce","slerp","Group","Texture","Points","fromMat3","PhoriaError","Animation","name","tracks","d","t","dt","track","scratch","sample","size","path","cubic","interpolation","stride","at","k","last","times","out","i","values","lo","hi","mid","t0","u","u2","u3","h00","h10","h01","h11","a","b","node","SUPPORTED","COMPRESSION","COMPONENTS","ARRAYS","NORMALIZE","WRAP","Model","n","which","x","names","loadGLTF","response","url","e","base","options","parseGLTF","unpack","data","version","json","ext","hint","model","build","Builder","bin","textures","bytes","view","length","type","chunk","uri","#buffers","#resolve","#textures","#objectUrls","#nodes","#node","c","scene","roots","#animation","index","parts","#mesh","part","decompose","camera","#camera","light","#light","m","geometry","#geometry","p","material","#defaultMaterial","#material","mode","pointMaterial","lineList","triangleList","key","cached","#geometries","#accessor","srgbColors","acc","count","integers","scale","#read","s","bv","viewIndex","buffer","Type","start","offset","get","o","#materials","pbr","#texture","clamp","v","transmission","coat","sheen","specular","brushed","translucent","transform","info","texCoord","colorSpace","sampler","image","texture","l","outer","inner","ch","sx","sy","sz","r","q","g","withIndices","triangles"],"sources":["../src/gltf/Animation.js","../src/gltf/load.js"],"sourcesContent":["// glTF node animations: keyframed position, rotation and scale, played by the scene clock through\n// the model's onUpdate, so they pause and run with the View like everything else.\nimport * as quat from '../math/quat.js'\n\n/** @import { Node } from '../scene/Node.js' */\n\n/**\n * One animated property of one node.\n * @typedef {object} Track\n * @property {Node} node\n * @property {'position' | 'quaternion' | 'scale'} path\n * @property {Float32Array} times seconds, ascending\n * @property {Float32Array} values per key: 3 numbers (4 for rotation); cubic splines store in-tangent, value, out-tangent\n * @property {'LINEAR' | 'STEP' | 'CUBICSPLINE'} interpolation\n */\n\n/** A named clip from a model: play(), stop(), and a few settings. */\nexport class Animation {\n /** @type {string} */ name\n /** Seconds. @type {number} */ duration\n /** @type {Track[]} */ tracks\n /** Seconds into the clip. */\n time = 0\n /** 1 = as authored; 2 = twice as fast; negative plays backwards. */\n speed = 1\n /** Start again at the end (default), or stop on the last frame. */\n loop = true\n playing = false\n\n /** @param {string} name @param {Track[]} tracks */\n constructor(name, tracks) {\n this.name = name\n this.tracks = tracks\n this.duration = tracks.reduce((d, t) => Math.max(d, t.times[t.times.length - 1] ?? 0), 0)\n }\n\n /** Start (or carry on) playing - from the start again, for a clip that doesn't loop and has finished. @returns {this} */\n play() {\n if (!this.loop && this.duration) {\n // at the end it is heading for: start over (from the end, playing backwards)\n if (this.speed >= 0 && this.time >= this.duration) this.seek(0)\n else if (this.speed < 0 && this.time <= 0) this.seek(this.duration)\n }\n this.playing = true\n return this\n }\n\n /** Pause where it is. @returns {this} */\n pause() {\n this.playing = false\n return this\n }\n\n /** Stop and go back to the first frame. @returns {this} */\n stop() {\n this.playing = false\n this.seek(0)\n return this\n }\n\n /** Jump to a time, in seconds, and pose the nodes there. @param {number} t @returns {this} */\n seek(t) {\n this.time = t\n this.apply()\n return this\n }\n\n /** @internal Advance by dt seconds when playing. @param {number} dt */\n advance(dt) {\n if (!this.playing) return\n // a clip of one key is a pose: hold it\n if (!this.duration) {\n this.apply()\n return\n }\n let t = this.time + dt * this.speed\n if (this.loop) t = ((t % this.duration) + this.duration) % this.duration\n else if (this.speed >= 0 ? t >= this.duration : t <= 0) {\n // it has run off the end it is heading for - not the one it starts at, as on the first frame\n t = Math.min(Math.max(t, 0), this.duration)\n this.playing = false\n }\n this.seek(t)\n }\n\n /** @internal Pose every animated node for the current time. */\n apply() {\n for (const track of this.tracks) sample(track, this.time)\n }\n}\n\nconst scratch = new Float32Array(4)\n\n/** @param {Track} track @param {number} t */\nfunction sample(track, t) {\n const { times, values, node, path, interpolation } = track\n const size = path === 'quaternion' ? 4 : 3\n const cubic = interpolation === 'CUBICSPLINE'\n // values per key: cubic splines hold [in-tangent, value, out-tangent]\n const stride = cubic ? size * 3 : size\n const at = (/** @type {number} */ k) => (cubic ? k * stride + size : k * stride)\n const last = times.length - 1\n const out = scratch\n if (t <= times[0] || last === 0) {\n for (let i = 0; i < size; i++) out[i] = values[at(0) + i]\n } else if (t >= times[last]) {\n for (let i = 0; i < size; i++) out[i] = values[at(last) + i]\n } else {\n // binary search for the key at or before t\n let lo = 0, hi = last\n while (hi - lo > 1) {\n const mid = (lo + hi) >> 1\n if (times[mid] <= t) lo = mid\n else hi = mid\n }\n const t0 = times[lo], t1 = times[hi], dt = t1 - t0\n const u = dt > 0 ? (t - t0) / dt : 0\n if (interpolation === 'STEP') {\n for (let i = 0; i < size; i++) out[i] = values[at(lo) + i]\n } else if (cubic) {\n // Hermite: p0, out-tangent of the first key, in-tangent of the second, p1\n const u2 = u * u, u3 = u2 * u\n const h00 = 2 * u3 - 3 * u2 + 1, h10 = u3 - 2 * u2 + u, h01 = -2 * u3 + 3 * u2, h11 = u3 - u2\n const a = lo * stride, b = hi * stride\n for (let i = 0; i < size; i++) {\n out[i] = h00 * values[a + size + i] + h10 * dt * values[a + size * 2 + i] + h01 * values[b + size + i] + h11 * dt * values[b + i]\n }\n if (size === 4) quat.normalize(out, out)\n } else if (size === 4) {\n quat.slerp(out, values.subarray(lo * 4, lo * 4 + 4), values.subarray(hi * 4, hi * 4 + 4), u)\n } else {\n for (let i = 0; i < 3; i++) out[i] = values[lo * 3 + i] + (values[hi * 3 + i] - values[lo * 3 + i]) * u\n }\n }\n if (path === 'quaternion') node.quaternion.set(out[0], out[1], out[2], out[3])\n else node[path].set(out[0], out[1], out[2])\n}\n","// glTF 2.0 (.gltf and .glb) to phoria2 nodes: meshes, the metallic-roughness material and its maps,\n// textures, the node hierarchy, cameras, KHR_lights_punctual and node animations. glTF's\n// conventions are phoria2's (+Y up, metres, counter-clockwise front faces, linear colour), so\n// little needs converting.\nimport * as quat from '../math/quat.js'\nimport { Group } from '../scene/Node.js'\nimport { Drawable, Mesh, Points, Lines } from '../scene/drawables.js'\nimport { PerspectiveCamera, OrthographicCamera } from '../scene/cameras.js'\nimport { DirectionalLight, PointLight, SpotLight } from '../scene/lights.js'\nimport { Geometry } from '../geometry/Geometry.js'\nimport { Material } from '../material/Material.js'\nimport { Texture } from '../material/Texture.js'\nimport { PhoriaError, warnOnce } from '../validate.js'\nimport { Animation } from './Animation.js'\n\n/** @import { Node } from '../scene/Node.js' */\n/** @import { Camera } from '../scene/cameras.js' */\n/** @import { Track } from './Animation.js' */\n\n/**\n * @typedef {object} GLTFOptions\n * @property {string} [baseUrl] where relative uris resolve from (default: the file's own url)\n * @property {boolean} [waitForTextures] resolve once every texture has loaded, so the first frame\n * is complete (default true)\n */\n\nconst SUPPORTED = new Set(['KHR_materials_emissive_strength', 'KHR_texture_transform', 'KHR_lights_punctual',\n 'KHR_materials_unlit', 'KHR_mesh_quantization', 'KHR_materials_transmission', 'KHR_materials_clearcoat', 'KHR_materials_sheen',\n 'KHR_materials_ior', 'KHR_materials_specular', 'KHR_materials_anisotropy', 'KHR_materials_diffuse_transmission'])\nconst COMPRESSION = new Set(['KHR_draco_mesh_compression', 'EXT_meshopt_compression', 'KHR_texture_basisu'])\n\nconst COMPONENTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 }\nconst ARRAYS = { 5120: Int8Array, 5121: Uint8Array, 5122: Int16Array, 5123: Uint16Array, 5125: Uint32Array, 5126: Float32Array }\n// normalized integers map to 0-1 (unsigned) or -1-1 (signed)\nconst NORMALIZE = { 5120: 127, 5121: 255, 5122: 32767, 5123: 65535, 5125: 1 }\nconst WRAP = { 33071: 'clamp', 33648: 'mirror', 10497: 'repeat' }\n\n/** A loaded glTF scene: a Group, plus the file's animations and cameras. */\nexport class Model extends Group {\n static type = 'model'\n /** @type {Animation[]} */ animations = []\n /** @type {Camera[]} */ cameras = []\n\n /**\n * Every mesh, point set and line set in the model - to change them together:\n * `for (const m of model.meshes) m.castShadow = true`.\n * @returns {Drawable[]}\n */\n get meshes() {\n return /** @type {Drawable[]} */ (this.findAll((n) => n instanceof Drawable))\n }\n\n /**\n * Play an animation by name or index (the first when not given).\n * @param {string | number} [which]\n * @returns {Animation | null}\n */\n play(which = 0) {\n const a = typeof which === 'number' ? this.animations[which] : this.animations.find((x) => x.name === which)\n if (!a) {\n const names = this.animations.map((x) => `'${x.name}'`).join(', ')\n warnOnce(this, `no animation ${typeof which === 'number' ? which : `'${which}'`} - this model has ${names || 'none'}`)\n return null\n }\n return a.play()\n }\n\n /**\n * A plain group of its parts, so create() can build it back without phoria2/gltf - with their\n * vertex data, but not the animations, or textures embedded in a .glb (they have no url).\n * @returns {Record<string, any>}\n */\n toJSON() {\n return { ...super.toJSON(), type: 'group' }\n }\n}\n\n/**\n * Load a .gltf or .glb file into a Model (a Group): add it to the scene, frame it, find its parts by\n * name. Resolves once its textures have loaded.\n *\n * const model = await loadGLTF('chair.glb')\n * view.scene.add(model)\n * view.frame(model)\n * model.find('Cushion').material.color.set('#2a6')\n *\n * @param {string} url\n * @param {GLTFOptions} [options]\n * @returns {Promise<Model>}\n */\nexport async function loadGLTF(url, options = {}) {\n const response = await fetch(url).catch((e) => { throw new PhoriaError(`loadGLTF: couldn't fetch '${url}' - ${e.message}`) })\n if (!response.ok) throw new PhoriaError(`loadGLTF: couldn't fetch '${url}' (${response.status} ${response.statusText})`)\n const base = options.baseUrl ?? new URL(url, globalThis.location?.href ?? 'file:///').href\n return parseGLTF(await response.arrayBuffer(), { ...options, baseUrl: base })\n}\n\n/**\n * Build a Model from a .glb file's bytes, a .gltf file's bytes or text, or its parsed JSON.\n * @param {ArrayBuffer | Uint8Array | string | Record<string, any>} data\n * @param {GLTFOptions} [options]\n * @returns {Promise<Model>}\n */\nexport async function parseGLTF(data, options = {}) {\n const { json, bin } = unpack(data)\n const version = String(json.asset?.version ?? '')\n if (!version.startsWith('2.')) throw new PhoriaError(`loadGLTF: glTF ${version || '(no version)'} isn't supported - only glTF 2.0`)\n for (const ext of json.extensionsRequired ?? []) {\n if (SUPPORTED.has(ext)) continue\n const hint = COMPRESSION.has(ext) ? ' - export the model without compression for now' : ''\n throw new PhoriaError(`loadGLTF: the model requires '${ext}', which isn't supported${hint}`)\n }\n const model = new Model({ name: json.scenes?.[json.scene ?? 0]?.name ?? 'model' })\n for (const ext of json.extensionsUsed ?? []) {\n if (!SUPPORTED.has(ext)) warnOnce(model, `the model uses '${ext}', which isn't supported - it is ignored`)\n }\n const build = new Builder(json, bin, options.baseUrl ?? '', model)\n await build.buffers()\n build.scene()\n // either way, embedded images' object urls are released once their textures settle\n const textures = build.textures()\n if (options.waitForTextures ?? true) await textures\n return model\n}\n\n/** @param {ArrayBuffer | Uint8Array | string | Record<string, any>} data */\nfunction unpack(data) {\n if (typeof data === 'string') return { json: JSON.parse(data), bin: null }\n if (!(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) return { json: data, bin: null }\n const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n // 'glTF' little-endian: a binary container of a JSON chunk and an optional binary chunk\n if (bytes.length >= 12 && view.getUint32(0, true) === 0x46546c67) {\n let json = null, bin = null\n for (let at = 12; at + 8 <= bytes.length;) {\n const length = view.getUint32(at, true), type = view.getUint32(at + 4, true)\n const chunk = bytes.subarray(at + 8, at + 8 + length)\n if (type === 0x4e4f534a) json = JSON.parse(new TextDecoder().decode(chunk))\n else if (type === 0x004e4942) bin = chunk\n at += 8 + length\n }\n if (!json) throw new PhoriaError('loadGLTF: the .glb file has no JSON chunk')\n return { json, bin }\n }\n return { json: JSON.parse(new TextDecoder().decode(bytes)), bin: null }\n}\n\nclass Builder {\n /** @type {Uint8Array[]} */ #buffers = []\n /** @type {Map<string, Texture>} */ #textures = new Map()\n /** @type {Map<number, Material>} */ #materials = new Map()\n /** @type {Map<string, Geometry>} */ #geometries = new Map()\n /** @type {Node[]} */ #nodes = []\n /** @type {string[]} */ #objectUrls = []\n\n /** @param {Record<string, any>} json @param {Uint8Array | null} bin @param {string} base @param {Model} model */\n constructor(json, bin, base, model) {\n this.json = json\n this.bin = bin\n this.base = base\n this.model = model\n }\n\n /** @param {string} uri */\n #resolve(uri) {\n try {\n return new URL(uri, this.base || undefined).href\n } catch {\n return uri\n }\n }\n\n async buffers() {\n this.#buffers = await Promise.all((this.json.buffers ?? []).map(async (b, i) => {\n if (b.uri === undefined) {\n if (i !== 0 || !this.bin) throw new PhoriaError(`loadGLTF: buffer ${i} has no uri and there is no binary chunk`)\n return this.bin\n }\n const url = this.#resolve(b.uri)\n const response = await fetch(url).catch((e) => { throw new PhoriaError(`loadGLTF: couldn't fetch buffer '${b.uri}' - ${e.message}`) })\n if (!response.ok) throw new PhoriaError(`loadGLTF: couldn't fetch buffer '${b.uri}' (${response.status})`)\n return new Uint8Array(await response.arrayBuffer())\n }))\n }\n\n /** Resolves when every texture has loaded (failures are warned about, not thrown). */\n async textures() {\n await Promise.all([...this.#textures.values()].map((t) => t.ready.catch((e) => warnOnce(this.model, e.message))))\n for (const url of this.#objectUrls) URL.revokeObjectURL(url)\n }\n\n scene() {\n const json = this.json\n this.#nodes = (json.nodes ?? []).map((_, i) => this.#node(i))\n // parent after every node exists, since children can come before their parents\n ;(json.nodes ?? []).forEach((n, i) => {\n for (const c of n.children ?? []) this.#nodes[i].add(this.#nodes[c])\n })\n const scene = json.scenes?.[json.scene ?? 0]\n const roots = scene ? scene.nodes ?? [] : this.#nodes.map((_, i) => i).filter((i) => !this.#nodes[i].parent)\n for (const i of roots) this.model.add(this.#nodes[i])\n this.model.animations = (json.animations ?? []).map((a, i) => this.#animation(a, i))\n if (this.model.animations.length) {\n const model = this.model\n model.onUpdate((_node, dt) => {\n for (const a of model.animations) a.advance(dt)\n })\n }\n }\n\n /** @param {number} index @returns {Node} */\n #node(index) {\n const n = this.json.nodes[index]\n const name = n.name ?? `node ${index}`\n if (n.skin !== undefined) warnOnce(this.model, `skinned meshes aren't supported - '${name}' is drawn in its bind pose`)\n if (n.weights || (n.mesh !== undefined && this.json.meshes[n.mesh].weights)) warnOnce(this.model, \"morph targets aren't supported - meshes are drawn without them\")\n\n const parts = n.mesh !== undefined ? this.#mesh(n.mesh) : []\n // a node with one primitive is that drawable; with several, a group of them\n /** @type {Node} */\n const node = parts.length === 1 ? parts[0] : new Group()\n for (const part of parts.length > 1 ? parts : []) node.add(part)\n node.name = name\n if (n.matrix) decompose(node, n.matrix)\n else {\n if (n.translation) node.position.set(n.translation[0], n.translation[1], n.translation[2])\n if (n.rotation) node.quaternion.set(n.rotation[0], n.rotation[1], n.rotation[2], n.rotation[3])\n if (n.scale) node.scale.set(n.scale[0], n.scale[1], n.scale[2])\n }\n if (n.camera !== undefined) {\n const camera = this.#camera(n.camera)\n node.add(camera)\n this.model.cameras.push(camera)\n }\n const light = n.extensions?.KHR_lights_punctual?.light\n if (light !== undefined) node.add(this.#light(light))\n if (n.extras && typeof n.extras === 'object') node.userData = { ...n.extras }\n return node\n }\n\n /** @param {number} index @returns {Node[]} */\n #mesh(index) {\n const m = this.json.meshes[index]\n return m.primitives.map((p, i) => {\n const geometry = this.#geometry(p)\n const material = p.material !== undefined ? this.#material(p.material) : this.#defaultMaterial()\n const mode = p.mode ?? 4\n /** @type {Node} */\n let node\n if (mode === 0) node = new Points({ geometry, material: pointMaterial(material) })\n else if (mode === 1 || mode === 2 || mode === 3) node = new Lines({ geometry: lineList(geometry, mode), material: pointMaterial(material) })\n else node = new Mesh({ geometry: mode === 4 ? geometry : triangleList(geometry, mode), material })\n node.name = m.primitives.length > 1 ? `${m.name ?? `mesh ${index}`} ${i}` : m.name ?? `mesh ${index}`\n return node\n })\n }\n\n /** @param {Record<string, any>} p */\n #geometry(p) {\n // primitives often share accessors; share their geometry too\n const key = JSON.stringify([p.attributes, p.indices])\n const cached = this.#geometries.get(key)\n if (cached) return cached\n const a = p.attributes\n if (a.POSITION === undefined) throw new PhoriaError('loadGLTF: a mesh primitive has no POSITION')\n /** @type {import('../geometry/Geometry.js').GeometryOptions} */\n const options = { positions: this.#accessor(a.POSITION) }\n if (a.NORMAL !== undefined) options.normals = this.#accessor(a.NORMAL)\n if (a.TEXCOORD_0 !== undefined) options.uvs = this.#accessor(a.TEXCOORD_0)\n if (a.TEXCOORD_1 !== undefined) options.uvs2 = this.#accessor(a.TEXCOORD_1)\n if (a.COLOR_0 !== undefined) options.colors = srgbColors(/** @type {Float32Array} */ (this.#accessor(a.COLOR_0)), COMPONENTS[this.json.accessors[a.COLOR_0].type])\n if (p.indices !== undefined) options.indices = this.#accessor(p.indices, true)\n const geometry = new Geometry(options)\n this.#geometries.set(key, geometry)\n return geometry\n }\n\n /**\n * An accessor's numbers, as floats (normalized integers scaled), or as integers for indices.\n * @param {number} index @param {boolean} [integers]\n * @returns {Float32Array | Uint32Array}\n */\n #accessor(index, integers = false) {\n const acc = this.json.accessors[index]\n const size = COMPONENTS[acc.type]\n const count = acc.count * size\n const out = integers ? new Uint32Array(count) : new Float32Array(count)\n const scale = acc.normalized && !integers ? 1 / NORMALIZE[acc.componentType] : 1\n if (acc.bufferView !== undefined) this.#read(acc.bufferView, acc.byteOffset ?? 0, acc.componentType, size, acc.count, out, scale)\n if (acc.sparse) {\n // a few elements replaced: indices of the elements, then their values\n const s = acc.sparse\n const at = new Uint32Array(s.count)\n this.#read(s.indices.bufferView, s.indices.byteOffset ?? 0, s.indices.componentType, 1, s.count, at, 1)\n const values = integers ? new Uint32Array(s.count * size) : new Float32Array(s.count * size)\n this.#read(s.values.bufferView, s.values.byteOffset ?? 0, acc.componentType, size, s.count, values, scale)\n for (let i = 0; i < s.count; i++) out.set(values.subarray(i * size, i * size + size), at[i] * size)\n }\n if (acc.normalized && !integers && (acc.componentType === 5120 || acc.componentType === 5122)) {\n for (let i = 0; i < out.length; i++) out[i] = Math.max(out[i], -1)\n }\n return out\n }\n\n /**\n * Copy elements out of a buffer view, honouring its stride.\n * @param {number} viewIndex @param {number} offset @param {number} type component type\n * @param {number} size components per element @param {number} count elements\n * @param {Float32Array | Uint32Array} out @param {number} scale\n */\n #read(viewIndex, offset, type, size, count, out, scale) {\n const bv = this.json.bufferViews[viewIndex]\n const buffer = this.#buffers[bv.buffer]\n const Type = ARRAYS[type]\n if (!Type) throw new PhoriaError(`loadGLTF: unknown component type ${type}`)\n const bytes = Type.BYTES_PER_ELEMENT\n const stride = bv.byteStride || size * bytes\n const start = buffer.byteOffset + (bv.byteOffset ?? 0) + offset\n const view = new DataView(buffer.buffer)\n const get = {\n 5120: (/** @type {number} */ o) => view.getInt8(o),\n 5121: (/** @type {number} */ o) => view.getUint8(o),\n 5122: (/** @type {number} */ o) => view.getInt16(o, true),\n 5123: (/** @type {number} */ o) => view.getUint16(o, true),\n 5125: (/** @type {number} */ o) => view.getUint32(o, true),\n 5126: (/** @type {number} */ o) => view.getFloat32(o, true),\n }[type]\n // the common case - tightly packed and aligned floats - is one copy\n if (type === 5126 && stride === size * 4 && start % 4 === 0 && scale === 1 && out instanceof Float32Array) {\n out.set(new Float32Array(buffer.buffer, start, count * size))\n return\n }\n for (let i = 0; i < count; i++) {\n for (let c = 0; c < size; c++) out[i * size + c] = get(start + i * stride + c * bytes) * scale\n }\n }\n\n /** @param {number} index @returns {Material} */\n #material(index) {\n const cached = this.#materials.get(index)\n if (cached) return cached\n const m = this.json.materials[index]\n const pbr = m.pbrMetallicRoughness ?? {}\n const material = new Material({ name: m.name ?? `material ${index}` })\n const base = pbr.baseColorFactor ?? [1, 1, 1, 1]\n material.color.setLinear(base[0], base[1], base[2])\n material.metalness = pbr.metallicFactor ?? 1\n material.roughness = pbr.roughnessFactor ?? 1\n if (pbr.baseColorTexture) material.map = this.#texture(pbr.baseColorTexture, 'srgb')\n if (pbr.metallicRoughnessTexture) {\n // one texture: roughness in green, metalness in blue - exactly what the two slots read\n material.roughnessMap = material.metalnessMap = this.#texture(pbr.metallicRoughnessTexture, 'linear')\n }\n if (m.normalTexture) {\n material.normalMap = this.#texture(m.normalTexture, 'linear')\n material.normalScale = m.normalTexture.scale ?? 1\n }\n if (m.occlusionTexture) {\n material.aoMap = this.#texture(m.occlusionTexture, 'linear')\n material.aoMapIntensity = Math.min(Math.max(m.occlusionTexture.strength ?? 1, 0), 1)\n }\n if (m.emissiveFactor) material.emissive.setLinear(m.emissiveFactor[0], m.emissiveFactor[1], m.emissiveFactor[2])\n if (m.emissiveTexture) {\n material.emissiveMap = this.#texture(m.emissiveTexture, 'srgb')\n if (!m.emissiveFactor) material.emissive.setLinear(1, 1, 1)\n }\n material.emissiveIntensity = m.extensions?.KHR_materials_emissive_strength?.emissiveStrength ?? 1\n if (m.extensions?.KHR_materials_unlit) material.unlit = true\n // glass, clear coat, cloth, reflectance, brushed metal and translucency, by their factors - their\n // own textures aren't read\n const clamp = (/** @type {number} */ v) => Math.min(Math.max(v, 0), 1)\n const x = m.extensions ?? {}\n const transmission = x.KHR_materials_transmission, coat = x.KHR_materials_clearcoat, sheen = x.KHR_materials_sheen\n if (transmission) material.transmission = clamp(transmission.transmissionFactor ?? 0)\n if (coat) {\n material.clearcoat = clamp(coat.clearcoatFactor ?? 0)\n material.clearcoatRoughness = clamp(coat.clearcoatRoughnessFactor ?? 0)\n }\n if (sheen) {\n const c = sheen.sheenColorFactor ?? [0, 0, 0]\n // glTF's sheen is its colour alone: black is none\n if (Math.max(c[0], c[1], c[2]) > 0) {\n material.sheen = 1\n material.sheenColor.setLinear(c[0], c[1], c[2])\n }\n material.sheenRoughness = clamp(sheen.sheenRoughnessFactor ?? 0)\n }\n if (x.KHR_materials_ior?.ior >= 1) material.ior = x.KHR_materials_ior.ior\n const specular = x.KHR_materials_specular\n if (specular) {\n material.specularIntensity = clamp(specular.specularFactor ?? 1)\n const c = specular.specularColorFactor ?? [1, 1, 1]\n material.specularColor.setLinear(c[0], c[1], c[2])\n }\n const brushed = x.KHR_materials_anisotropy\n if (brushed) {\n material.anisotropy = clamp(brushed.anisotropyStrength ?? 0)\n material.anisotropyRotation = brushed.anisotropyRotation ?? 0\n }\n const translucent = x.KHR_materials_diffuse_transmission\n if (translucent) {\n material.translucency = clamp(translucent.diffuseTransmissionFactor ?? 0)\n const c = translucent.diffuseTransmissionColorFactor ?? [1, 1, 1]\n material.translucencyColor.setLinear(c[0], c[1], c[2])\n }\n if (m.alphaMode === 'BLEND') {\n material.opacity = base[3]\n material.transparent = true\n material.depthWrite = false\n } else if (m.alphaMode === 'MASK') {\n material.alphaTest = m.alphaCutoff ?? 0.5\n }\n material.doubleSided = !!m.doubleSided\n this.#materials.set(index, material)\n return material\n }\n\n // glTF's default for primitives without a material\n #defaultMaterial() {\n let material = this.#materials.get(-1)\n if (!material) this.#materials.set(-1, material = new Material({ name: 'default', metalness: 1, roughness: 1 }))\n return material\n }\n\n /**\n * @param {Record<string, any>} info a textureInfo: index, texCoord, extensions\n * @param {'srgb' | 'linear'} colorSpace what the slot holds\n * @returns {Texture}\n */\n #texture(info, colorSpace) {\n const transform = info.extensions?.KHR_texture_transform\n let texCoord = transform?.texCoord ?? info.texCoord ?? 0\n if (texCoord > 1) {\n warnOnce(this.model, `textures on a third UV set or later (TEXCOORD_${texCoord}) are drawn with the first`)\n texCoord = 0\n }\n const key = JSON.stringify([info.index, colorSpace, transform?.offset, transform?.scale, transform?.rotation, texCoord])\n const cached = this.#textures.get(key)\n if (cached) return cached\n\n const t = this.json.textures[info.index]\n const sampler = this.json.samplers?.[t.sampler] ?? {}\n const image = this.json.images[t.source]\n if (t.source === undefined || !image) throw new PhoriaError(`loadGLTF: texture ${info.index} has no image (compressed textures aren't supported)`)\n let url\n if (image.bufferView !== undefined) {\n const bv = this.json.bufferViews[image.bufferView]\n const buffer = this.#buffers[bv.buffer]\n const bytes = buffer.subarray(bv.byteOffset ?? 0, (bv.byteOffset ?? 0) + bv.byteLength)\n url = URL.createObjectURL(new Blob([/** @type {Uint8Array<ArrayBuffer>} */ (bytes)], { type: image.mimeType ?? 'image/png' }))\n this.#objectUrls.push(url)\n } else {\n url = this.#resolve(image.uri)\n }\n const texture = new Texture({\n url,\n colorSpace,\n wrap: WRAP[sampler.wrapS ?? 10497] ?? 'repeat',\n filter: sampler.magFilter === 9728 ? 'nearest' : 'linear',\n // glTF UVs start at the image's top left, as phoria2's do\n flipY: false,\n repeat: transform?.scale ?? [1, 1],\n offset: transform?.offset ?? [0, 0],\n rotation: transform?.rotation ?? 0,\n uvSet: texCoord,\n })\n this.#textures.set(key, texture)\n return texture\n }\n\n /** @param {number} index @returns {Camera} */\n #camera(index) {\n const c = this.json.cameras[index]\n const name = c.name ?? `camera ${index}`\n if (c.type === 'orthographic') {\n const o = c.orthographic\n return new OrthographicCamera({ name, height: o.ymag * 2, near: o.znear, far: o.zfar })\n }\n const p = c.perspective\n return new PerspectiveCamera({ name, fov: (p.yfov * 180) / Math.PI, near: p.znear, far: p.zfar ?? 1e6 })\n }\n\n /** @param {number} index */\n #light(index) {\n const l = this.json.extensions?.KHR_lights_punctual?.lights?.[index]\n if (!l) throw new PhoriaError(`loadGLTF: KHR_lights_punctual light ${index} doesn't exist`)\n const c = l.color ?? [1, 1, 1]\n // glTF lights shine down their node's -Z; intensities are lux and candela, divided by PI for\n // phoria2's lights (where 1 lights a white surface to white)\n const options = { name: l.name, intensity: (l.intensity ?? 1) / Math.PI }\n let light\n if (l.type === 'directional') light = new DirectionalLight({ ...options, direction: [0, 0, -1] })\n else if (l.type === 'spot') {\n const outer = l.spot?.outerConeAngle ?? Math.PI / 4, inner = l.spot?.innerConeAngle ?? 0\n light = new SpotLight({ ...options, direction: [0, 0, -1], range: l.range ?? 0, angle: outer, penumbra: outer > 0 ? 1 - inner / outer : 0 })\n } else light = new PointLight({ ...options, range: l.range ?? 0 })\n light.color.setLinear(c[0], c[1], c[2])\n return light\n }\n\n /** @param {Record<string, any>} a @param {number} index @returns {Animation} */\n #animation(a, index) {\n /** @type {Track[]} */\n const tracks = []\n for (const ch of a.channels) {\n const path = { translation: 'position', rotation: 'quaternion', scale: 'scale' }[ch.target.path]\n if (!path) {\n warnOnce(this.model, `'${ch.target.path}' animations aren't supported - only translation, rotation and scale`)\n continue\n }\n const node = this.#nodes[ch.target.node]\n if (!node) continue\n const s = a.samplers[ch.sampler]\n tracks.push({\n node, path,\n times: /** @type {Float32Array} */ (this.#accessor(s.input)),\n values: /** @type {Float32Array} */ (this.#accessor(s.output)),\n interpolation: s.interpolation ?? 'LINEAR',\n })\n }\n return new Animation(a.name ?? `animation ${index}`, tracks)\n }\n}\n\n/** Set a node's position, rotation and scale from a column-major matrix. @param {Node} node @param {number[]} m */\nfunction decompose(node, m) {\n let sx = Math.hypot(m[0], m[1], m[2])\n const sy = Math.hypot(m[4], m[5], m[6]), sz = Math.hypot(m[8], m[9], m[10])\n // a mirroring matrix: put the flip in x\n const det = m[0] * (m[5] * m[10] - m[6] * m[9]) - m[4] * (m[1] * m[10] - m[2] * m[9]) + m[8] * (m[1] * m[6] - m[2] * m[5])\n if (det < 0) sx = -sx\n const r = [m[0] / sx, m[1] / sx, m[2] / sx, m[4] / sy, m[5] / sy, m[6] / sy, m[8] / sz, m[9] / sz, m[10] / sz]\n const q = quat.normalize([0, 0, 0, 1], quat.fromMat3([0, 0, 0, 1], r))\n node.position.set(m[12], m[13], m[14])\n node.quaternion.set(q[0], q[1], q[2], q[3])\n node.scale.set(sx, sy, sz)\n}\n\n/** glTF vertex colours are linear RGB(A); phoria2's are sRGB RGB. @param {Float32Array} c @param {number} size */\nfunction srgbColors(c, size) {\n const n = c.length / size\n const out = new Float32Array(n * 3)\n for (let i = 0; i < n; i++) {\n for (let k = 0; k < 3; k++) {\n const v = Math.min(Math.max(c[i * size + k], 0), 1)\n out[i * 3 + k] = v <= 0.0031308 ? v * 12.92 : 1.055 * v ** (1 / 2.4) - 0.055\n }\n }\n return out\n}\n\n/** Points and Lines take their colour and size from a lit material's basics. @param {Material} m */\nfunction pointMaterial(m) {\n return new Material({ name: m.name, color: m.color.getStyle(), opacity: m.opacity, map: m.map, vertexColors: true, size: 2, sizeAttenuation: false })\n}\n\n/** Triangle strips and fans as a plain triangle list. @param {Geometry} g @param {number} mode */\nfunction triangleList(g, mode) {\n const index = g.indices ?? Uint32Array.from({ length: g.vertexCount }, (_, i) => i)\n const out = []\n for (let i = 2; i < index.length; i++) {\n if (mode === 6) out.push(index[0], index[i - 1], index[i])\n // strips alternate winding, so every other triangle swaps two corners\n else if (i % 2 === 0) out.push(index[i - 2], index[i - 1], index[i])\n else out.push(index[i - 1], index[i - 2], index[i])\n }\n return withIndices(g, out, true)\n}\n\n/** Line strips and loops as segment pairs. @param {Geometry} g @param {number} mode */\nfunction lineList(g, mode) {\n if (mode === 1) return g\n const index = g.indices ?? Uint32Array.from({ length: g.vertexCount }, (_, i) => i)\n const out = []\n for (let i = 1; i < index.length; i++) out.push(index[i - 1], index[i])\n if (mode === 2 && index.length > 2) out.push(index[index.length - 1], index[0])\n return withIndices(g, out, false)\n}\n\n/** @param {Geometry} g @param {number[]} indices @param {boolean} triangles keep normals (lines have none) */\nfunction withIndices(g, indices, triangles) {\n // only normals the file gave - reading g.normals would work them out from the strip's own indices,\n // taken as a triangle list; the new geometry works them out from its real triangles instead\n return new Geometry({ positions: g.positions, normals: triangles && g.hasNormals ? g.normals : undefined, uvs: g.uvs ?? undefined, uvs2: g.uvs2 ?? undefined,\n colors: g.colors ?? undefined, indices })\n}\n"],"mappings":";;AAiBA,IAAaoB,IAAb,MAAuB;CACC;CACS;CACR;CAEvB,OAAO;CAEP,QAAQ;CAER,OAAO;CACP,UAAU;CAGV,YAAY,GAAM,GAAQ;EAGxB,AAFA,KAAK,OAAOC,GACZ,KAAK,SAASC,GACd,KAAK,WAAWA,EAAO,QAAQ,GAAG,MAAM,KAAK,IAAIC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAS,MAAM,CAAC,GAAG,CAAC;CAC1F;CAGA,OAAO;EAOL,OANI,CAAC,KAAK,QAAQ,KAAK,aAEjB,KAAK,SAAS,KAAK,KAAK,QAAQ,KAAK,WAAU,KAAK,KAAK,CAAC,IACrD,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAG,KAAK,KAAK,KAAK,QAAQ,IAEpE,KAAK,UAAU,IACR;CACT;CAGA,QAAQ;EAEN,OADA,KAAK,UAAU,IACR;CACT;CAGA,OAAO;EAGL,OAFA,KAAK,UAAU,IACf,KAAK,KAAK,CAAC,GACJ;CACT;CAGA,KAAK,GAAG;EAGN,OAFA,KAAK,OAAOC,GACZ,KAAK,MAAM,GACJ;CACT;CAGA,QAAQ,GAAI;EACV,IAAI,CAAC,KAAK,SAAS;EAEnB,IAAI,CAAC,KAAK,UAAU;GAClB,KAAK,MAAM;GACX;EACF;EACA,IAAI,IAAI,KAAK,OAAOC,IAAK,KAAK;EAO9B,AANI,KAAK,OAAM,KAAM,IAAI,KAAK,WAAY,KAAK,YAAY,KAAK,YACvD,KAAK,SAAS,IAAI,KAAK,KAAK,WAAW,KAAK,OAEnD,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,QAAQ,GAC1C,KAAK,UAAU,KAEjB,KAAK,KAAK,CAAC;CACb;CAGA,QAAQ;EACN,KAAK,IAAMC,KAAS,KAAK,QAAQ,EAAOA,GAAO,KAAK,IAAI;CAC1D;AACF,GAEMC,oBAAU,IAAI,aAAa,CAAC;AAGlC,SAASC,EAAO,GAAO,GAAG;CACxB,IAAM,EAAE,UAAO,WAAQ,SAAM,SAAM,qBAAkBF,GAC/CG,IAAOC,MAAS,eAAe,IAAI,GACnCC,IAAQC,MAAkB,eAE1BC,IAASF,IAAQF,IAAO,IAAIA,GAC5BK,KAA4B,MAAOH,IAAQI,IAAIF,IAASJ,IAAOM,IAAIF,GACnEG,IAAOC,EAAM,SAAS,GACtBC,IAAMX;CACZ,IAAI,KAAKU,EAAM,MAAMD,MAAS,GAC5B,KAAK,IAAIG,IAAI,GAAGA,IAAIV,GAAM,KAAK,EAAIU,KAAKC,EAAON,EAAG,CAAC,IAAIK;MAClD,IAAI,KAAKF,EAAMD,IACpB,KAAK,IAAIG,IAAI,GAAGA,IAAIV,GAAM,KAAK,EAAIU,KAAKC,EAAON,EAAGE,CAAI,IAAIG;MACrD;EAEL,IAAIE,IAAK,GAAGC,IAAKN;EACjB,OAAOM,IAAKD,IAAK,IAAG;GAClB,IAAME,IAAOF,IAAKC,KAAO;GACzB,AAAIL,EAAMM,MAAQ,IAAG,IAAKA,IACrB,IAAKA;EACZ;EACA,IAAMC,IAAKP,EAAMI,IAAqBhB,IAAXY,EAAMK,KAAeE,GAC1CC,IAAIpB,IAAK,KAAK,IAAImB,KAAMnB,IAAK;EACnC,IAAIO,MAAkB,QACpB,KAAK,IAAIO,IAAI,GAAGA,IAAIV,GAAM,KAAK,EAAIU,KAAKC,EAAON,EAAGO,CAAE,IAAIF;OACnD,IAAIR,GAAO;GAEhB,IAAMe,IAAKD,IAAIA,GAAGE,IAAKD,IAAKD,GACtBG,IAAM,IAAID,IAAK,IAAID,IAAK,GAAGG,IAAMF,IAAK,IAAID,IAAKD,GAAGK,IAAM,KAAKH,IAAK,IAAID,GAAIK,IAAMJ,IAAKD,GACrFM,IAAIX,IAAKR,GAAQoB,IAAIX,IAAKT;GAChC,KAAK,IAAIM,IAAI,GAAGA,IAAIV,GAAM,KACxB,EAAIU,KAAKS,IAAMR,EAAOY,IAAIvB,IAAOU,KAAKU,IAAMxB,IAAKe,EAAOY,IAAIvB,IAAO,IAAIU,KAAKW,IAAMV,EAAOa,IAAIxB,IAAOU,KAAKY,IAAM1B,IAAKe,EAAOa,IAAId;GAEjI,AAAIV,MAAS,KAAGjB,EAAe0B,GAAKA,CAAG;EACzC,OAAO,IAAIT,MAAS,GAClB,EAAWS,GAAKE,EAAO,SAASC,IAAK,GAAGA,IAAK,IAAI,CAAC,GAAGD,EAAO,SAASE,IAAK,GAAGA,IAAK,IAAI,CAAC,GAAGG,CAAC;OAE3F,KAAK,IAAIN,IAAI,GAAGA,IAAI,GAAG,KAAK,EAAIA,KAAKC,EAAOC,IAAK,IAAIF,MAAMC,EAAOE,IAAK,IAAIH,KAAKC,EAAOC,IAAK,IAAIF,MAAMM;CAE1G;CACA,AAAIf,MAAS,eAAcwB,EAAK,WAAW,IAAIhB,EAAI,IAAIA,EAAI,IAAIA,EAAI,IAAIA,EAAI,EAAE,IACxEgB,EAAKxB,EAAK,CAAC,IAAIQ,EAAI,IAAIA,EAAI,IAAIA,EAAI,EAAE;AAC5C;;AC9GA,IAAMiB,oBAAY,IAAI,IAAI;CAAC;CAAmC;CAAyB;CACrF;CAAuB;CAAyB;CAA8B;CAA2B;CACzG;CAAqB;CAA0B;CAA4B;AAAoC,CAAC,GAC5GC,oBAAc,IAAI,IAAI;CAAC;CAA8B;CAA2B;AAAoB,CAAC,GAErGC,IAAa;CAAE,QAAQ;CAAG,MAAM;CAAG,MAAM;CAAG,MAAM;CAAG,MAAM;CAAG,MAAM;CAAG,MAAM;AAAG,GAChFC,IAAS;CAAE,MAAM;CAAW,MAAM;CAAY,MAAM;CAAY,MAAM;CAAa,MAAM;CAAa,MAAM;AAAa,GAEzHC,IAAY;CAAE,MAAM;CAAK,MAAM;CAAK,MAAM;CAAO,MAAM;CAAO,MAAM;AAAE,GACtEC,IAAO;CAAE,OAAO;CAAS,OAAO;CAAU,OAAO;AAAS,GAGnDC,IAAb,cAA2B9C,EAAM;CAC/B,OAAO,OAAO;CACa,aAAa,CAAC;CACjB,UAAU,CAAC;CAOnC,IAAI,SAAS;EACX,OAAkC,KAAK,SAAS,MAAM+C,aAAatD,CAAQ;CAC7E;CAOA,KAAK,IAAQ,GAAG;EACd,IAAM4C,IAAI,OAAOW,KAAU,WAAW,KAAK,WAAWA,KAAS,KAAK,WAAW,MAAM,MAAMC,EAAE,SAASD,CAAK;EAC3G,IAAI,CAACX,GAAG;GACN,IAAMa,IAAQ,KAAK,WAAW,KAAK,MAAM,IAAID,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI;GAEjE,OADAnD,EAAS,MAAM,gBAAgB,OAAOkD,KAAU,WAAWA,IAAQ,IAAIA,EAAM,GAAG,oBAAoBE,KAAS,QAAQ,GAC9G;EACT;EACA,OAAOb,EAAE,KAAK;CAChB;CAOA,SAAS;EACP,OAAO;GAAE,GAAG,MAAM,OAAO;GAAG,MAAM;EAAQ;CAC5C;AACF;AAeA,eAAsBc,EAAS,GAAK,IAAU,CAAC,GAAG;CAChD,IAAMC,IAAW,MAAM,MAAMC,CAAG,CAAC,CAAC,OAAO,MAAM;EAAE,MAAM,IAAIjD,EAAY,6BAA6BiD,EAAI,MAAMC,EAAE,SAAS;CAAE,CAAC;CAC5H,IAAI,CAACF,EAAS,IAAI,MAAM,IAAIhD,EAAY,6BAA6BiD,EAAI,KAAKD,EAAS,OAAO,GAAGA,EAAS,WAAW,EAAE;CACvH,IAAMG,IAAOC,EAAQ,WAAW,IAAI,IAAIH,GAAK,WAAW,UAAU,QAAQ,UAAU,CAAC,CAAC;CACtF,OAAOI,EAAU,MAAML,EAAS,YAAY,GAAG;EAAE,GAAGI;EAAS,SAASD;CAAK,CAAC;AAC9E;AAQA,eAAsBE,EAAU,GAAM,IAAU,CAAC,GAAG;CAClD,IAAM,EAAE,SAAM,WAAQC,EAAOC,CAAI,GAC3BC,IAAU,OAAOC,EAAK,OAAO,WAAW,EAAE;CAChD,IAAI,CAACD,EAAQ,WAAW,IAAI,GAAG,MAAM,IAAIxD,EAAY,kBAAkBwD,KAAW,eAAe,iCAAiC;CAClI,KAAK,IAAME,KAAOD,EAAK,sBAAsB,CAAC,GAAG;EAC/C,IAAIrB,EAAU,IAAIsB,CAAG,GAAG;EACxB,IAAMC,IAAOtB,EAAY,IAAIqB,CAAG,IAAI,oDAAoD;EACxF,MAAM,IAAI1D,EAAY,iCAAiC0D,EAAI,0BAA0BC,GAAM;CAC7F;CACA,IAAMC,IAAQ,IAAIlB,EAAM,EAAE,MAAMe,EAAK,SAASA,EAAK,SAAS,EAAE,EAAE,QAAQ,QAAQ,CAAC;CACjF,KAAK,IAAMC,KAAOD,EAAK,kBAAkB,CAAC,GACxC,AAAKrB,EAAU,IAAIsB,CAAG,KAAGhE,EAASkE,GAAO,mBAAmBF,EAAI,yCAAyC;CAE3G,IAAMG,IAAQ,IAAIC,EAAQL,GAAMM,GAAKX,EAAQ,WAAW,IAAIQ,CAAK;CAEjE,AADA,MAAMC,EAAM,QAAQ,GACpBA,EAAM,MAAM;CAEZ,IAAMG,IAAWH,EAAM,SAAS;CAEhC,QADIT,EAAQ,mBAAmB,OAAM,MAAMY,GACpCJ;AACT;AAGA,SAASN,EAAO,GAAM;CACpB,IAAI,OAAOC,KAAS,UAAU,OAAO;EAAE,MAAM,KAAK,MAAMA,CAAI;EAAG,KAAK;CAAK;CACzE,IAAI,EAAEA,aAAgB,gBAAgB,CAAC,YAAY,OAAOA,CAAI,GAAG,OAAO;EAAE,MAAMA;EAAM,KAAK;CAAK;CAChG,IAAMU,IAAQV,aAAgB,cAAc,IAAI,WAAWA,CAAI,IAAI,IAAI,WAAWA,EAAK,QAAQA,EAAK,YAAYA,EAAK,UAAU,GACzHW,IAAO,IAAI,SAASD,EAAM,QAAQA,EAAM,YAAYA,EAAM,UAAU;CAE1E,IAAIA,EAAM,UAAU,MAAMC,EAAK,UAAU,GAAG,EAAI,MAAM,YAAY;EAChE,IAAIT,IAAO,MAAMM,IAAM;EACvB,KAAK,IAAIhD,IAAK,IAAIA,IAAK,KAAKkD,EAAM,SAAS;GACzC,IAAME,IAASD,EAAK,UAAUnD,GAAI,EAAI,GAAGqD,IAAOF,EAAK,UAAUnD,IAAK,GAAG,EAAI,GACrEsD,IAAQJ,EAAM,SAASlD,IAAK,GAAGA,IAAK,IAAIoD,CAAM;GAGpD,AAFIC,MAAS,aAAY,IAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAOC,CAAK,CAAC,IACjED,MAAS,YAAY,IAAMC,IACpC,KAAM,IAAIF;EACZ;EACA,IAAI,CAACV,GAAM,MAAM,IAAIzD,EAAY,2CAA2C;EAC5E,OAAO;GAAE;GAAM;EAAI;CACrB;CACA,OAAO;EAAE,MAAM,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAOiE,CAAK,CAAC;EAAG,KAAK;CAAK;AACxE;AAEA,IAAMH,IAAN,MAAc;CACgB,KAAW,CAAC;CACJ,qBAAY,IAAI,IAAI;CACnB,qBAAa,IAAI,IAAI;CACrB,qBAAc,IAAI,IAAI;CACrC,KAAS,CAAC;CACR,KAAc,CAAC;CAGvC,YAAY,GAAM,GAAK,GAAM,GAAO;EAIlC,AAHA,KAAK,OAAOL,GACZ,KAAK,MAAMM,GACX,KAAK,OAAOZ,GACZ,KAAK,QAAQS;CACf;CAGA,GAAS,GAAK;EACZ,IAAI;GACF,OAAO,IAAI,IAAIU,GAAK,KAAK,QAAQ,KAAA,CAAS,CAAC,CAAC;EAC9C,QAAQ;GACN,OAAOA;EACT;CACF;CAEA,MAAM,UAAU;EACd,KAAKC,KAAW,MAAM,QAAQ,KAAK,KAAK,KAAK,WAAW,CAAC,EAAA,CAAG,IAAI,OAAO,GAAG,MAAM;GAC9E,IAAIrC,EAAE,QAAQ,KAAA,GAAW;IACvB,IAAId,MAAM,KAAK,CAAC,KAAK,KAAK,MAAM,IAAIpB,EAAY,oBAAoBoB,EAAE,yCAAyC;IAC/G,OAAO,KAAK;GACd;GACA,IAAM6B,IAAM,KAAKuB,GAAStC,EAAE,GAAG,GACzBc,IAAW,MAAM,MAAMC,CAAG,CAAC,CAAC,OAAO,MAAM;IAAE,MAAM,IAAIjD,EAAY,oCAAoCkC,EAAE,IAAI,MAAMgB,EAAE,SAAS;GAAE,CAAC;GACrI,IAAI,CAACF,EAAS,IAAI,MAAM,IAAIhD,EAAY,oCAAoCkC,EAAE,IAAI,KAAKc,EAAS,OAAO,EAAE;GACzG,OAAO,IAAI,WAAW,MAAMA,EAAS,YAAY,CAAC;EACpD,CAAC,CAAC;CACJ;CAGA,MAAM,WAAW;EACf,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAKyB,GAAU,OAAO,CAAC,CAAC,CAAC,KAAK,MAAMpE,EAAE,MAAM,OAAO,MAAMX,EAAS,KAAK,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;EAChH,KAAK,IAAMuD,KAAO,KAAKyB,IAAa,IAAI,gBAAgBzB,CAAG;CAC7D;CAEA,QAAQ;EACN,IAAMQ,IAAO,KAAK;EAGjB,AAFD,KAAKkB,MAAUlB,EAAK,SAAS,CAAC,EAAA,CAAG,KAAK,GAAG,MAAM,KAAKmB,GAAMxD,CAAC,CAAC,IAE1DqC,EAAK,SAAS,CAAC,EAAA,CAAG,SAAS,GAAG,MAAM;GACpC,KAAK,IAAMoB,KAAKlC,EAAE,YAAY,CAAC,GAAG,KAAKgC,GAAOvD,EAAE,CAAC,IAAI,KAAKuD,GAAOE,EAAE;EACrE,CAAC;EACD,IAAMC,IAAQrB,EAAK,SAASA,EAAK,SAAS,IACpCsB,IAAQD,IAAQA,EAAM,SAAS,CAAC,IAAI,KAAKH,GAAO,KAAK,GAAG,MAAMvD,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,KAAKuD,GAAOvD,EAAE,CAAC,MAAM;EAC3G,KAAK,IAAMA,KAAK2D,GAAO,KAAK,MAAM,IAAI,KAAKJ,GAAOvD,EAAE;EAEpD,IADA,KAAK,MAAM,cAAcqC,EAAK,cAAc,CAAC,EAAA,CAAG,KAAK,GAAG,MAAM,KAAKuB,GAAW/C,GAAGb,CAAC,CAAC,GAC/E,KAAK,MAAM,WAAW,QAAQ;GAChC,IAAMwC,IAAQ,KAAK;GACnB,EAAM,UAAU,GAAO,MAAO;IAC5B,KAAK,IAAM3B,KAAK2B,EAAM,YAAY,EAAE,QAAQtD,CAAE;GAChD,CAAC;EACH;CACF;CAGA,GAAM,GAAO;EACX,IAAMqC,IAAI,KAAK,KAAK,MAAMsC,IACpB/E,IAAOyC,EAAE,QAAQ,QAAQsC;EAE/B,AADItC,EAAE,SAAS,KAAA,KAAWjD,EAAS,KAAK,OAAO,sCAAsCQ,EAAK,4BAA4B,IAClHyC,EAAE,WAAYA,EAAE,SAAS,KAAA,KAAa,KAAK,KAAK,OAAOA,EAAE,KAAK,CAAC,YAAUjD,EAAS,KAAK,OAAO,gEAAgE;EAElK,IAAMwF,IAAQvC,EAAE,SAAS,KAAA,IAAiC,CAAC,IAAtB,KAAKwC,GAAMxC,EAAE,IAAI,GAGhDR,IAAO+C,EAAM,WAAW,IAAIA,EAAM,KAAK,IAAItF,EAAM;EACvD,KAAK,IAAMwF,KAAQF,EAAM,SAAS,IAAIA,IAAQ,CAAC,GAAG,EAAK,IAAIE,CAAI;EAQ/D,IAPA,EAAK,OAAOlF,GACRyC,EAAE,SAAQ0C,EAAUlD,GAAMQ,EAAE,MAAM,KAEhCA,EAAE,eAAaR,EAAK,SAAS,IAAIQ,EAAE,YAAY,IAAIA,EAAE,YAAY,IAAIA,EAAE,YAAY,EAAE,GACrFA,EAAE,YAAUR,EAAK,WAAW,IAAIQ,EAAE,SAAS,IAAIA,EAAE,SAAS,IAAIA,EAAE,SAAS,IAAIA,EAAE,SAAS,EAAE,GAC1FA,EAAE,SAAOR,EAAK,MAAM,IAAIQ,EAAE,MAAM,IAAIA,EAAE,MAAM,IAAIA,EAAE,MAAM,EAAE,IAE5DA,EAAE,WAAW,KAAA,GAAW;GAC1B,IAAM2C,IAAS,KAAKC,GAAQ5C,EAAE,MAAM;GAEpC,AADAR,EAAK,IAAImD,CAAM,GACf,KAAK,MAAM,QAAQ,KAAKA,CAAM;EAChC;EACA,IAAME,IAAQ7C,EAAE,YAAY,qBAAqB;EAGjD,OAFI6C,MAAU,KAAA,KAAWrD,EAAK,IAAI,KAAKsD,GAAOD,CAAK,CAAC,GAChD7C,EAAE,UAAU,OAAOA,EAAE,UAAW,aAAU,EAAK,WAAW,EAAE,GAAGA,EAAE,OAAO,IACrER;CACT;CAGA,GAAM,GAAO;EACX,IAAMuD,IAAI,KAAK,KAAK,OAAOT;EAC3B,OAAOS,EAAE,WAAW,KAAK,GAAG,MAAM;GAChC,IAAMC,IAAW,KAAKC,GAAUC,CAAC,GAC3BC,IAAWD,EAAE,aAAa,KAAA,IAAyC,KAAKE,GAAiB,IAAnD,KAAKC,GAAUH,EAAE,QAAQ,GAC/DI,IAAOJ,EAAE,QAAQ,GAEnB1D;GAKJ,OAJA,AAEKA,IAFD8D,MAAS,IAAU,IAAInG,EAAO;IAAE;IAAU,UAAUoG,EAAcJ,CAAQ;GAAE,CAAC,IACxEG,MAAS,KAAKA,MAAS,KAAKA,MAAS,IAAU,IAAIlH,EAAM;IAAE,UAAUoH,EAASR,GAAUM,CAAI;IAAG,UAAUC,EAAcJ,CAAQ;GAAE,CAAC,IAC/H,IAAItG,EAAK;IAAE,UAAUyG,MAAS,IAAIN,IAAWS,EAAaT,GAAUM,CAAI;IAAG;GAAS,CAAC,GACjG,EAAK,OAAOP,EAAE,WAAW,SAAS,IAAI,GAAGA,EAAE,QAAQ,QAAQT,IAAQ,GAAG,MAAMS,EAAE,QAAQ,QAAQT,KACvF9C;EACT,CAAC;CACH;CAGA,GAAU,GAAG;EAEX,IAAMkE,IAAM,KAAK,UAAU,CAACR,EAAE,YAAYA,EAAE,OAAO,CAAC,GAC9CS,IAAS,KAAKC,GAAY,IAAIF,CAAG;EACvC,IAAIC,GAAQ,OAAOA;EACnB,IAAMrE,IAAI4D,EAAE;EACZ,IAAI5D,EAAE,aAAa,KAAA,GAAW,MAAM,IAAIjC,EAAY,4CAA4C;EAEhG,IAAMoD,IAAU,EAAE,WAAW,KAAKoD,GAAUvE,EAAE,QAAQ,EAAE;EAKxD,AAJIA,EAAE,WAAW,KAAA,MAAW,EAAQ,UAAU,KAAKuE,GAAUvE,EAAE,MAAM,IACjEA,EAAE,eAAe,KAAA,MAAW,EAAQ,MAAM,KAAKuE,GAAUvE,EAAE,UAAU,IACrEA,EAAE,eAAe,KAAA,MAAW,EAAQ,OAAO,KAAKuE,GAAUvE,EAAE,UAAU,IACtEA,EAAE,YAAY,KAAA,MAAW,EAAQ,SAASwE,EAAwC,KAAKD,GAAUvE,EAAE,OAAO,GAAIK,EAAW,KAAK,KAAK,UAAUL,EAAE,QAAQ,CAAC,KAAK,IAC7J4D,EAAE,YAAY,KAAA,MAAW,EAAQ,UAAU,KAAKW,GAAUX,EAAE,SAAS,EAAI;EAC7E,IAAMF,IAAW,IAAIpG,EAAS6D,CAAO;EAErC,OADA,KAAKmD,GAAY,IAAIF,GAAKV,CAAQ,GAC3BA;CACT;CAOA,GAAU,GAAO,IAAW,IAAO;EACjC,IAAMe,IAAM,KAAK,KAAK,UAAUzB,IAC1BvE,IAAO4B,EAAWoE,EAAI,OACtBC,IAAQD,EAAI,QAAQhG,GACpBS,IAAMyF,IAAW,IAAI,YAAYD,CAAK,IAAI,IAAI,aAAaA,CAAK,GAChEE,IAAQH,EAAI,cAAc,CAACE,IAAW,IAAIpE,EAAUkE,EAAI,iBAAiB;EAE/E,IADIA,EAAI,eAAe,KAAA,KAAW,KAAKI,GAAMJ,EAAI,YAAYA,EAAI,cAAc,GAAGA,EAAI,eAAehG,GAAMgG,EAAI,OAAOvF,GAAK0F,CAAK,GAC5HH,EAAI,QAAQ;GAEd,IAAMK,IAAIL,EAAI,QACR3F,IAAK,IAAI,YAAYgG,EAAE,KAAK;GAClC,KAAKD,GAAMC,EAAE,QAAQ,YAAYA,EAAE,QAAQ,cAAc,GAAGA,EAAE,QAAQ,eAAe,GAAGA,EAAE,OAAOhG,GAAI,CAAC;GACtG,IAAMM,IAASuF,IAAW,IAAI,YAAYG,EAAE,QAAQrG,CAAI,IAAI,IAAI,aAAaqG,EAAE,QAAQrG,CAAI;GAC3F,KAAKoG,GAAMC,EAAE,OAAO,YAAYA,EAAE,OAAO,cAAc,GAAGL,EAAI,eAAehG,GAAMqG,EAAE,OAAO1F,GAAQwF,CAAK;GACzG,KAAK,IAAIzF,IAAI,GAAGA,IAAI2F,EAAE,OAAO,KAAK,EAAI,IAAI1F,EAAO,SAASD,IAAIV,GAAMU,IAAIV,IAAOA,CAAI,GAAGK,EAAGK,KAAKV,CAAI;EACpG;EACA,IAAIgG,EAAI,cAAc,CAACE,MAAaF,EAAI,kBAAkB,QAAQA,EAAI,kBAAkB,OACtF,KAAK,IAAItF,IAAI,GAAGA,IAAID,EAAI,QAAQ,KAAK,EAAIC,KAAK,KAAK,IAAID,EAAIC,IAAI,EAAE;EAEnE,OAAOD;CACT;CAQA,GAAM,GAAW,GAAQ,GAAM,GAAM,GAAO,GAAK,GAAO;EACtD,IAAM6F,IAAK,KAAK,KAAK,YAAYC,IAC3BC,IAAS,KAAK3C,GAASyC,EAAG,SAC1BG,IAAO5E,EAAO6B;EACpB,IAAI,CAAC+C,GAAM,MAAM,IAAInH,EAAY,oCAAoCoE,GAAM;EAC3E,IAAMH,IAAQkD,EAAK,mBACbrG,IAASkG,EAAG,cAActG,IAAOuD,GACjCmD,IAAQF,EAAO,cAAcF,EAAG,cAAc,KAAKK,GACnDnD,IAAO,IAAI,SAASgD,EAAO,MAAM,GACjCI,IAAM;GACV,OAA6B,MAAMpD,EAAK,QAAQqD,CAAC;GACjD,OAA6B,MAAMrD,EAAK,SAASqD,CAAC;GAClD,OAA6B,MAAMrD,EAAK,SAASqD,GAAG,EAAI;GACxD,OAA6B,MAAMrD,EAAK,UAAUqD,GAAG,EAAI;GACzD,OAA6B,MAAMrD,EAAK,UAAUqD,GAAG,EAAI;GACzD,OAA6B,MAAMrD,EAAK,WAAWqD,GAAG,EAAI;EAC5D,EAAEnD;EAEF,IAAIA,MAAS,QAAQtD,MAAWJ,IAAO,KAAK0G,IAAQ,KAAM,KAAKP,MAAU,KAAK1F,aAAe,cAC3F,EAAI,IAAI,IAAI,aAAa+F,EAAO,QAAQE,GAAOT,IAAQjG,CAAI,CAAC;OAG9D,KAAK,IAAIU,IAAI,GAAGA,IAAIuF,GAAO,KACzB,KAAK,IAAI9B,IAAI,GAAGA,IAAInE,GAAM,KAAK,EAAIU,IAAIV,IAAOmE,KAAKyC,EAAIF,IAAQhG,IAAIN,IAAS+D,IAAIZ,CAAK,IAAI4C;CAE7F;CAGA,GAAU,GAAO;EACf,IAAMP,IAAS,KAAKkB,GAAW,IAAIvC,CAAK;EACxC,IAAIqB,GAAQ,OAAOA;EACnB,IAAMZ,IAAI,KAAK,KAAK,UAAUT,IACxBwC,IAAM/B,EAAE,wBAAwB,CAAC,GACjCI,IAAW,IAAIxG,EAAS,EAAE,MAAMoG,EAAE,QAAQ,YAAYT,IAAQ,CAAC,GAC/D9B,IAAOsE,EAAI,mBAAmB;GAAC;GAAG;GAAG;GAAG;EAAC;EAuB/C,AAtBA3B,EAAS,MAAM,UAAU3C,EAAK,IAAIA,EAAK,IAAIA,EAAK,EAAE,GAClD,EAAS,YAAYsE,EAAI,kBAAkB,GAC3C,EAAS,YAAYA,EAAI,mBAAmB,GACxCA,EAAI,qBAAkB,EAAS,MAAM,KAAKC,GAASD,EAAI,kBAAkB,MAAM,IAC/EA,EAAI,6BAEN,EAAS,eAAe,EAAS,eAAe,KAAKC,GAASD,EAAI,0BAA0B,QAAQ,IAElG/B,EAAE,kBACJ,EAAS,YAAY,KAAKgC,GAAShC,EAAE,eAAe,QAAQ,GAC5D,EAAS,cAAcA,EAAE,cAAc,SAAS,IAE9CA,EAAE,qBACJ,EAAS,QAAQ,KAAKgC,GAAShC,EAAE,kBAAkB,QAAQ,GAC3D,EAAS,iBAAiB,KAAK,IAAI,KAAK,IAAIA,EAAE,iBAAiB,YAAY,GAAG,CAAC,GAAG,CAAC,IAEjFA,EAAE,kBAAgBI,EAAS,SAAS,UAAUJ,EAAE,eAAe,IAAIA,EAAE,eAAe,IAAIA,EAAE,eAAe,EAAE,GAC3GA,EAAE,oBACJ,EAAS,cAAc,KAAKgC,GAAShC,EAAE,iBAAiB,MAAM,GACzDA,EAAE,kBAAgBI,EAAS,SAAS,UAAU,GAAG,GAAG,CAAC,IAE5D,EAAS,oBAAoBJ,EAAE,YAAY,iCAAiC,oBAAoB,GAC5FA,EAAE,YAAY,wBAAqB,EAAS,QAAQ;EAGxD,IAAMiC,KAA+B,MAAM,KAAK,IAAI,KAAK,IAAIC,GAAG,CAAC,GAAG,CAAC,GAC/D/E,IAAI6C,EAAE,cAAc,CAAC,GACrBmC,IAAehF,EAAE,4BAA4BiF,IAAOjF,EAAE,yBAAyBkF,IAAQlF,EAAE;EAM/F,IALIgF,MAAc,EAAS,eAAeF,EAAME,EAAa,sBAAsB,CAAC,IAChFC,MACF,EAAS,YAAYH,EAAMG,EAAK,mBAAmB,CAAC,GACpD,EAAS,qBAAqBH,EAAMG,EAAK,4BAA4B,CAAC,IAEpEC,GAAO;GACT,IAAMlD,IAAIkD,EAAM,oBAAoB;IAAC;IAAG;IAAG;GAAC;GAM5C,AAJI,KAAK,IAAIlD,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,IAAI,MAC/B,EAAS,QAAQ,GACjBiB,EAAS,WAAW,UAAUjB,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,IAEhD,EAAS,iBAAiB8C,EAAMI,EAAM,wBAAwB,CAAC;EACjE;EACA,AAAIlF,EAAE,mBAAmB,OAAO,MAAG,EAAS,MAAMA,EAAE,kBAAkB;EACtE,IAAMmF,IAAWnF,EAAE;EACnB,IAAImF,GAAU;GACZ,EAAS,oBAAoBL,EAAMK,EAAS,kBAAkB,CAAC;GAC/D,IAAMnD,IAAImD,EAAS,uBAAuB;IAAC;IAAG;IAAG;GAAC;GAClD,EAAS,cAAc,UAAUnD,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE;EACnD;EACA,IAAMoD,IAAUpF,EAAE;EAClB,AAAIoF,MACF,EAAS,aAAaN,EAAMM,EAAQ,sBAAsB,CAAC,GAC3D,EAAS,qBAAqBA,EAAQ,sBAAsB;EAE9D,IAAMC,IAAcrF,EAAE;EACtB,IAAIqF,GAAa;GACf,EAAS,eAAeP,EAAMO,EAAY,6BAA6B,CAAC;GACxE,IAAMrD,IAAIqD,EAAY,kCAAkC;IAAC;IAAG;IAAG;GAAC;GAChE,EAAS,kBAAkB,UAAUrD,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE;EACvD;EAUA,OATIa,EAAE,cAAc,WAClB,EAAS,UAAUvC,EAAK,IACxB,EAAS,cAAc,IACvB,EAAS,aAAa,MACbuC,EAAE,cAAc,WACzB,EAAS,YAAYA,EAAE,eAAe,KAExC,EAAS,cAAc,CAAC,CAACA,EAAE,aAC3B,KAAK8B,GAAW,IAAIvC,GAAOa,CAAQ,GAC5BA;CACT;CAGA,KAAmB;EACjB,IAAIA,IAAW,KAAK0B,GAAW,IAAI,EAAE;EAErC,OADK1B,KAAU,KAAK0B,GAAW,IAAI,IAAI,IAAW,IAAIlI,EAAS;GAAE,MAAM;GAAW,WAAW;GAAG,WAAW;EAAE,CAAC,CAAC,GACxGwG;CACT;CAOA,GAAS,GAAM,GAAY;EACzB,IAAMqC,IAAYC,EAAK,YAAY,uBAC/BC,IAAWF,GAAW,YAAYC,EAAK,YAAY;EACvD,AAAIC,IAAW,MACb3I,EAAS,KAAK,OAAO,iDAAiD2I,EAAS,2BAA2B,GAC1G,IAAW;EAEb,IAAMhC,IAAM,KAAK,UAAU;GAAC+B,EAAK;GAAOE;GAAYH,GAAW;GAAQA,GAAW;GAAOA,GAAW;GAAUE;EAAQ,CAAC,GACjH/B,IAAS,KAAK7B,GAAU,IAAI4B,CAAG;EACrC,IAAIC,GAAQ,OAAOA;EAEnB,IAAMjG,IAAI,KAAK,KAAK,SAAS+H,EAAK,QAC5BG,IAAU,KAAK,KAAK,WAAWlI,EAAE,YAAY,CAAC,GAC9CmI,IAAQ,KAAK,KAAK,OAAOnI,EAAE;EACjC,IAAIA,EAAE,WAAW,KAAA,KAAa,CAACmI,GAAO,MAAM,IAAIxI,EAAY,qBAAqBoI,EAAK,MAAM,qDAAqD;EACjJ,IAAInF;EACJ,IAAIuF,EAAM,eAAe,KAAA,GAAW;GAClC,IAAMxB,IAAK,KAAK,KAAK,YAAYwB,EAAM,aAEjCvE,IADS,KAAKM,GAASyC,EAAG,OACZ,CAAC,SAASA,EAAG,cAAc,IAAIA,EAAG,cAAc,KAAKA,EAAG,UAAU;GAEtF,AADA,IAAM,IAAI,gBAAgB,IAAI,KAAK,CAAyC/C,CAAM,GAAG,EAAE,MAAMuE,EAAM,YAAY,YAAY,CAAC,CAAC,GAC7H,KAAK9D,GAAY,KAAKzB,CAAG;EAC3B,OACE,IAAM,KAAKuB,GAASgE,EAAM,GAAG;EAE/B,IAAMC,IAAU,IAAI5I,EAAQ;GAC1B;GACA;GACA,MAAM4C,EAAK8F,EAAQ,SAAS,UAAU;GACtC,QAAQA,EAAQ,cAAc,OAAO,YAAY;GAEjD,OAAO;GACP,QAAQJ,GAAW,SAAS,CAAC,GAAG,CAAC;GACjC,QAAQA,GAAW,UAAU,CAAC,GAAG,CAAC;GAClC,UAAUA,GAAW,YAAY;GACjC,OAAOE;EACT,CAAC;EAED,OADA,KAAK5D,GAAU,IAAI4B,GAAKoC,CAAO,GACxBA;CACT;CAGA,GAAQ,GAAO;EACb,IAAM5D,IAAI,KAAK,KAAK,QAAQI,IACtB/E,IAAO2E,EAAE,QAAQ,UAAUI;EACjC,IAAIJ,EAAE,SAAS,gBAAgB;GAC7B,IAAM0C,IAAI1C,EAAE;GACZ,OAAO,IAAI5F,EAAmB;IAAE;IAAM,QAAQsI,EAAE,OAAO;IAAG,MAAMA,EAAE;IAAO,KAAKA,EAAE;GAAK,CAAC;EACxF;EACA,IAAM1B,IAAIhB,EAAE;EACZ,OAAO,IAAI1F,EAAkB;GAAE;GAAM,KAAM0G,EAAE,OAAO,MAAO,KAAK;GAAI,MAAMA,EAAE;GAAO,KAAKA,EAAE,QAAQ;EAAI,CAAC;CACzG;CAGA,GAAO,GAAO;EACZ,IAAM6C,IAAI,KAAK,KAAK,YAAY,qBAAqB,SAASzD;EAC9D,IAAI,CAACyD,GAAG,MAAM,IAAI1I,EAAY,uCAAuCiF,EAAM,eAAe;EAC1F,IAAMJ,IAAI6D,EAAE,SAAS;GAAC;GAAG;GAAG;EAAC,GAGvBtF,IAAU;GAAE,MAAMsF,EAAE;GAAM,YAAYA,EAAE,aAAa,KAAK,KAAK;EAAG,GACpElD;EACJ,IAAIkD,EAAE,SAAS,eAAe,IAAQ,IAAItJ,EAAiB;GAAE,GAAGgE;GAAS,WAAW;IAAC;IAAG;IAAG;GAAE;EAAE,CAAC;OAC3F,IAAIsF,EAAE,SAAS,QAAQ;GAC1B,IAAMC,IAAQD,EAAE,MAAM,kBAAkB,KAAK,KAAK,GAAGE,IAAQF,EAAE,MAAM,kBAAkB;GACvF,IAAQ,IAAIxJ,EAAU;IAAE,GAAGkE;IAAS,WAAW;KAAC;KAAG;KAAG;IAAE;IAAG,OAAOsF,EAAE,SAAS;IAAG,OAAOC;IAAO,UAAUA,IAAQ,IAAI,IAAIC,IAAQD,IAAQ;GAAE,CAAC;EAC7I,OAAO,IAAQ,IAAI3J,EAAW;GAAE,GAAGoE;GAAS,OAAOsF,EAAE,SAAS;EAAE,CAAC;EAEjE,OADAlD,EAAM,MAAM,UAAUX,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,GAC/BW;CACT;CAGA,GAAW,GAAG,GAAO;EAEnB,IAAMrF,IAAS,CAAC;EAChB,KAAK,IAAM0I,KAAM5G,EAAE,UAAU;GAC3B,IAAMtB,IAAO;IAAE,aAAa;IAAY,UAAU;IAAc,OAAO;GAAQ,EAAEkI,EAAG,OAAO;GAC3F,IAAI,CAAClI,GAAM;IACT,EAAS,KAAK,OAAO,IAAIkI,EAAG,OAAO,KAAK,qEAAqE;IAC7G;GACF;GACA,IAAM1G,IAAO,KAAKwC,GAAOkE,EAAG,OAAO;GACnC,IAAI,CAAC1G,GAAM;GACX,IAAM4E,IAAI9E,EAAE,SAAS4G,EAAG;GACxB,EAAO,KAAK;IACV;IAAM;IACN,OAAoC,KAAKrC,GAAUO,EAAE,KAAK;IAC1D,QAAqC,KAAKP,GAAUO,EAAE,MAAM;IAC5D,eAAeA,EAAE,iBAAiB;GACpC,CAAC;EACH;EACA,OAAO,IAAI9G,EAAUgC,EAAE,QAAQ,aAAagD,KAAS9E,CAAM;CAC7D;AACF;AAGA,SAASkF,EAAU,GAAM,GAAG;CAC1B,IAAIyD,IAAK,KAAK,MAAMpD,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,GAC9BqD,IAAK,KAAK,MAAMrD,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,GAAGsD,IAAK,KAAK,MAAMtD,EAAE,IAAIA,EAAE,IAAIA,EAAE,GAAG;CAG1E,AADYA,EAAE,MAAMA,EAAE,KAAKA,EAAE,MAAMA,EAAE,KAAKA,EAAE,MAAMA,EAAE,MAAMA,EAAE,KAAKA,EAAE,MAAMA,EAAE,KAAKA,EAAE,MAAMA,EAAE,MAAMA,EAAE,KAAKA,EAAE,KAAKA,EAAE,KAAKA,EAAE,MAC7G,MAAG,IAAK,CAACoD;CACnB,IAAMG,IAAI;EAACvD,EAAE,KAAKoD;EAAIpD,EAAE,KAAKoD;EAAIpD,EAAE,KAAKoD;EAAIpD,EAAE,KAAKqD;EAAIrD,EAAE,KAAKqD;EAAIrD,EAAE,KAAKqD;EAAIrD,EAAE,KAAKsD;EAAItD,EAAE,KAAKsD;EAAItD,EAAE,MAAMsD;CAAE,GACvGE,IAAIrK,EAAe;EAAC;EAAG;EAAG;EAAG;CAAC,GAAGC,EAAc;EAAC;EAAG;EAAG;EAAG;CAAC,GAAGmK,CAAC,CAAC;CAGrE,AAFA9G,EAAK,SAAS,IAAIuD,EAAE,KAAKA,EAAE,KAAKA,EAAE,GAAG,GACrCvD,EAAK,WAAW,IAAI+G,EAAE,IAAIA,EAAE,IAAIA,EAAE,IAAIA,EAAE,EAAE,GAC1C/G,EAAK,MAAM,IAAI2G,GAAIC,GAAIC,CAAE;AAC3B;AAGA,SAASvC,EAAW,GAAG,GAAM;CAC3B,IAAM,IAAI5B,EAAE,SAASnE,GACfS,IAAM,IAAI,aAAa,IAAI,CAAC;CAClC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,KAAK,IAAIH,IAAI,GAAGA,IAAI,GAAG,KAAK;EAC1B,IAAM4G,IAAI,KAAK,IAAI,KAAK,IAAI/C,EAAE,IAAInE,IAAOM,IAAI,CAAC,GAAG,CAAC;EAClD,EAAI,IAAI,IAAIA,KAAK4G,KAAK,WAAYA,IAAI,QAAQ,QAAQA,MAAM,IAAI,OAAO;CACzE;CAEF,OAAOzG;AACT;AAGA,SAAS+E,EAAc,GAAG;CACxB,OAAO,IAAI5G,EAAS;EAAE,MAAMoG,EAAE;EAAM,OAAOA,EAAE,MAAM,SAAS;EAAG,SAASA,EAAE;EAAS,KAAKA,EAAE;EAAK,cAAc;EAAM,MAAM;EAAG,iBAAiB;CAAM,CAAC;AACtJ;AAGA,SAASU,EAAa,GAAG,GAAM;CAC7B,IAAMnB,IAAQkE,EAAE,WAAW,YAAY,KAAK,EAAE,QAAQA,EAAE,YAAY,IAAI,GAAG,MAAM/H,CAAC,GAC5ED,IAAM,CAAC;CACb,KAAK,IAAIC,IAAI,GAAGA,IAAI6D,EAAM,QAAQ,KAChC,AAAIgB,MAAS,IAAG9E,EAAI,KAAK8D,EAAM,IAAIA,EAAM7D,IAAI,IAAI6D,EAAM7D,EAAE,IAEhDA,IAAI,KAAM,IAAGD,EAAI,KAAK8D,EAAM7D,IAAI,IAAI6D,EAAM7D,IAAI,IAAI6D,EAAM7D,EAAE,IAC9DD,EAAI,KAAK8D,EAAM7D,IAAI,IAAI6D,EAAM7D,IAAI,IAAI6D,EAAM7D,EAAE;CAEpD,OAAOgI,EAAYD,GAAGhI,GAAK,EAAI;AACjC;AAGA,SAASgF,EAAS,GAAG,GAAM;CACzB,IAAIF,MAAS,GAAG,OAAOkD;CACvB,IAAMlE,IAAQkE,EAAE,WAAW,YAAY,KAAK,EAAE,QAAQA,EAAE,YAAY,IAAI,GAAG,MAAM/H,CAAC,GAC5ED,IAAM,CAAC;CACb,KAAK,IAAIC,IAAI,GAAGA,IAAI6D,EAAM,QAAQ,KAAK,EAAI,KAAKA,EAAM7D,IAAI,IAAI6D,EAAM7D,EAAE;CAEtE,OADI6E,MAAS,KAAKhB,EAAM,SAAS,KAAG9D,EAAI,KAAK8D,EAAMA,EAAM,SAAS,IAAIA,EAAM,EAAE,GACvEmE,EAAYD,GAAGhI,GAAK,EAAK;AAClC;AAGA,SAASiI,EAAY,GAAG,GAAS,GAAW;CAG1C,OAAO,IAAI7J,EAAS;EAAE,WAAW4J,EAAE;EAAW,SAASE,KAAaF,EAAE,aAAaA,EAAE,UAAU,KAAA;EAAW,KAAKA,EAAE,OAAO,KAAA;EAAW,MAAMA,EAAE,QAAQ,KAAA;EACjJ,QAAQA,EAAE,UAAU,KAAA;EAAW;CAAQ,CAAC;AAC5C"}
1
+ {"version":3,"file":"gltf.js","names":["quat.normalize","quat.fromMat3","DirectionalLight","warnOnce","OrthographicCamera","PointLight","PerspectiveCamera","normalize","Points","Texture","Drawable","fromMat3","Mesh","PhoriaError","Geometry","Lines","Group","Material","slerp","SpotLight","Animation","name","tracks","d","t","dt","track","scratch","sample","size","path","cubic","interpolation","stride","at","k","last","times","out","i","values","lo","hi","mid","t0","u","u2","u3","h00","h10","h01","h11","a","b","node","SUPPORTED","COMPRESSION","COMPONENTS","ARRAYS","NORMALIZE","WRAP","Model","n","which","x","names","loadGLTF","response","url","e","base","options","parseGLTF","unpack","data","version","json","ext","hint","model","build","Builder","bin","textures","bytes","view","length","type","chunk","uri","#buffers","#resolve","#textures","#objectUrls","#nodes","#node","c","scene","roots","#animation","index","parts","#mesh","part","decompose","camera","#camera","light","#light","m","geometry","#geometry","p","material","#defaultMaterial","#material","mode","pointMaterial","lineList","triangleList","key","cached","#geometries","#accessor","srgbColors","acc","count","integers","scale","#read","s","bv","viewIndex","buffer","Type","start","offset","get","o","#materials","pbr","#texture","clamp","v","transmission","coat","sheen","specular","brushed","translucent","transform","info","texCoord","colorSpace","sampler","image","texture","l","outer","inner","ch","sx","sy","sz","r","q","g","withIndices","triangles"],"sources":["../src/gltf/Animation.js","../src/gltf/load.js"],"sourcesContent":["// glTF node animations: keyframed position, rotation and scale, played by the scene clock through\n// the model's onUpdate, so they pause and run with the View like everything else.\nimport * as quat from '../math/quat.js'\n\n/** @import { Node } from '../scene/Node.js' */\n\n/**\n * One animated property of one node.\n * @typedef {object} Track\n * @property {Node} node\n * @property {'position' | 'quaternion' | 'scale'} path\n * @property {Float32Array} times seconds, ascending\n * @property {Float32Array} values per key: 3 numbers (4 for rotation); cubic splines store in-tangent, value, out-tangent\n * @property {'LINEAR' | 'STEP' | 'CUBICSPLINE'} interpolation\n */\n\n/** A named clip from a model: play(), stop(), and a few settings. */\nexport class Animation {\n /** @type {string} */ name\n /** Seconds. @type {number} */ duration\n /** @type {Track[]} */ tracks\n /** Seconds into the clip. */\n time = 0\n /** 1 = as authored; 2 = twice as fast; negative plays backwards. */\n speed = 1\n /** Start again at the end (default), or stop on the last frame. */\n loop = true\n playing = false\n\n /** @param {string} name @param {Track[]} tracks */\n constructor(name, tracks) {\n this.name = name\n this.tracks = tracks\n this.duration = tracks.reduce((d, t) => Math.max(d, t.times[t.times.length - 1] ?? 0), 0)\n }\n\n /** Start (or carry on) playing - from the start again, for a clip that doesn't loop and has finished. @returns {this} */\n play() {\n if (!this.loop && this.duration) {\n // at the end it is heading for: start over (from the end, playing backwards)\n if (this.speed >= 0 && this.time >= this.duration) this.seek(0)\n else if (this.speed < 0 && this.time <= 0) this.seek(this.duration)\n }\n this.playing = true\n return this\n }\n\n /** Pause where it is. @returns {this} */\n pause() {\n this.playing = false\n return this\n }\n\n /** Stop and go back to the first frame. @returns {this} */\n stop() {\n this.playing = false\n this.seek(0)\n return this\n }\n\n /** Jump to a time, in seconds, and pose the nodes there. @param {number} t @returns {this} */\n seek(t) {\n this.time = t\n this.apply()\n return this\n }\n\n /** @internal Advance by dt seconds when playing. @param {number} dt */\n advance(dt) {\n if (!this.playing) return\n // a clip of one key is a pose: hold it\n if (!this.duration) {\n this.apply()\n return\n }\n let t = this.time + dt * this.speed\n if (this.loop) t = ((t % this.duration) + this.duration) % this.duration\n else if (this.speed >= 0 ? t >= this.duration : t <= 0) {\n // it has run off the end it is heading for - not the one it starts at, as on the first frame\n t = Math.min(Math.max(t, 0), this.duration)\n this.playing = false\n }\n this.seek(t)\n }\n\n /** @internal Pose every animated node for the current time. */\n apply() {\n for (const track of this.tracks) sample(track, this.time)\n }\n}\n\nconst scratch = new Float32Array(4)\n\n/** @param {Track} track @param {number} t */\nfunction sample(track, t) {\n const { times, values, node, path, interpolation } = track\n const size = path === 'quaternion' ? 4 : 3\n const cubic = interpolation === 'CUBICSPLINE'\n // values per key: cubic splines hold [in-tangent, value, out-tangent]\n const stride = cubic ? size * 3 : size\n const at = (/** @type {number} */ k) => (cubic ? k * stride + size : k * stride)\n const last = times.length - 1\n const out = scratch\n if (t <= times[0] || last === 0) {\n for (let i = 0; i < size; i++) out[i] = values[at(0) + i]\n } else if (t >= times[last]) {\n for (let i = 0; i < size; i++) out[i] = values[at(last) + i]\n } else {\n // binary search for the key at or before t\n let lo = 0, hi = last\n while (hi - lo > 1) {\n const mid = (lo + hi) >> 1\n if (times[mid] <= t) lo = mid\n else hi = mid\n }\n const t0 = times[lo], t1 = times[hi], dt = t1 - t0\n const u = dt > 0 ? (t - t0) / dt : 0\n if (interpolation === 'STEP') {\n for (let i = 0; i < size; i++) out[i] = values[at(lo) + i]\n } else if (cubic) {\n // Hermite: p0, out-tangent of the first key, in-tangent of the second, p1\n const u2 = u * u, u3 = u2 * u\n const h00 = 2 * u3 - 3 * u2 + 1, h10 = u3 - 2 * u2 + u, h01 = -2 * u3 + 3 * u2, h11 = u3 - u2\n const a = lo * stride, b = hi * stride\n for (let i = 0; i < size; i++) {\n out[i] = h00 * values[a + size + i] + h10 * dt * values[a + size * 2 + i] + h01 * values[b + size + i] + h11 * dt * values[b + i]\n }\n if (size === 4) quat.normalize(out, out)\n } else if (size === 4) {\n quat.slerp(out, values.subarray(lo * 4, lo * 4 + 4), values.subarray(hi * 4, hi * 4 + 4), u)\n } else {\n for (let i = 0; i < 3; i++) out[i] = values[lo * 3 + i] + (values[hi * 3 + i] - values[lo * 3 + i]) * u\n }\n }\n if (path === 'quaternion') node.quaternion.set(out[0], out[1], out[2], out[3])\n else node[path].set(out[0], out[1], out[2])\n}\n","// glTF 2.0 (.gltf and .glb) to phoria2 nodes: meshes, the metallic-roughness material and its maps,\n// textures, the node hierarchy, cameras, KHR_lights_punctual and node animations. glTF's\n// conventions are phoria2's (+Y up, metres, counter-clockwise front faces, linear colour), so\n// little needs converting.\nimport * as quat from '../math/quat.js'\nimport { Group } from '../scene/Node.js'\nimport { Drawable, Mesh, Points, Lines } from '../scene/drawables.js'\nimport { PerspectiveCamera, OrthographicCamera } from '../scene/cameras.js'\nimport { DirectionalLight, PointLight, SpotLight } from '../scene/lights.js'\nimport { Geometry } from '../geometry/Geometry.js'\nimport { Material } from '../material/Material.js'\nimport { Texture } from '../material/Texture.js'\nimport { PhoriaError, warnOnce } from '../validate.js'\nimport { Animation } from './Animation.js'\n\n/** @import { Node } from '../scene/Node.js' */\n/** @import { Camera } from '../scene/cameras.js' */\n/** @import { Track } from './Animation.js' */\n\n/**\n * @typedef {object} GLTFOptions\n * @property {string} [baseUrl] where relative uris resolve from (default: the file's own url)\n * @property {boolean} [waitForTextures] resolve once every texture has loaded, so the first frame\n * is complete (default true)\n */\n\nconst SUPPORTED = new Set(['KHR_materials_emissive_strength', 'KHR_texture_transform', 'KHR_lights_punctual',\n 'KHR_materials_unlit', 'KHR_mesh_quantization', 'KHR_materials_transmission', 'KHR_materials_clearcoat', 'KHR_materials_sheen',\n 'KHR_materials_ior', 'KHR_materials_specular', 'KHR_materials_anisotropy', 'KHR_materials_diffuse_transmission'])\nconst COMPRESSION = new Set(['KHR_draco_mesh_compression', 'EXT_meshopt_compression', 'KHR_texture_basisu'])\n\nconst COMPONENTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 }\nconst ARRAYS = { 5120: Int8Array, 5121: Uint8Array, 5122: Int16Array, 5123: Uint16Array, 5125: Uint32Array, 5126: Float32Array }\n// normalized integers map to 0-1 (unsigned) or -1-1 (signed)\nconst NORMALIZE = { 5120: 127, 5121: 255, 5122: 32767, 5123: 65535, 5125: 1 }\nconst WRAP = { 33071: 'clamp', 33648: 'mirror', 10497: 'repeat' }\n\n/** A loaded glTF scene: a Group, plus the file's animations and cameras. */\nexport class Model extends Group {\n static type = 'model'\n /** @type {Animation[]} */ animations = []\n /** @type {Camera[]} */ cameras = []\n\n /**\n * Every mesh, point set and line set in the model - to change them together:\n * `for (const m of model.meshes) m.castShadow = true`.\n * @returns {Drawable[]}\n */\n get meshes() {\n return /** @type {Drawable[]} */ (this.findAll((n) => n instanceof Drawable))\n }\n\n /**\n * Play an animation by name or index (the first when not given).\n * @param {string | number} [which]\n * @returns {Animation | null}\n */\n play(which = 0) {\n const a = typeof which === 'number' ? this.animations[which] : this.animations.find((x) => x.name === which)\n if (!a) {\n const names = this.animations.map((x) => `'${x.name}'`).join(', ')\n warnOnce(this, `no animation ${typeof which === 'number' ? which : `'${which}'`} - this model has ${names || 'none'}`)\n return null\n }\n return a.play()\n }\n\n /**\n * A plain group of its parts, so create() can build it back without phoria2/gltf - with their\n * vertex data, but not the animations, or textures embedded in a .glb (they have no url).\n * @returns {Record<string, any>}\n */\n toJSON() {\n return { ...super.toJSON(), type: 'group' }\n }\n}\n\n/**\n * Load a .gltf or .glb file into a Model (a Group): add it to the scene, frame it, find its parts by\n * name. Resolves once its textures have loaded.\n *\n * const model = await loadGLTF('chair.glb')\n * view.scene.add(model)\n * view.frame(model)\n * model.find('Cushion').material.color.set('#2a6')\n *\n * @param {string} url\n * @param {GLTFOptions} [options]\n * @returns {Promise<Model>}\n */\nexport async function loadGLTF(url, options = {}) {\n const response = await fetch(url).catch((e) => { throw new PhoriaError(`loadGLTF: couldn't fetch '${url}' - ${e.message}`) })\n if (!response.ok) throw new PhoriaError(`loadGLTF: couldn't fetch '${url}' (${response.status} ${response.statusText})`)\n const base = options.baseUrl ?? new URL(url, globalThis.location?.href ?? 'file:///').href\n return parseGLTF(await response.arrayBuffer(), { ...options, baseUrl: base })\n}\n\n/**\n * Build a Model from a .glb file's bytes, a .gltf file's bytes or text, or its parsed JSON.\n * @param {ArrayBuffer | Uint8Array | string | Record<string, any>} data\n * @param {GLTFOptions} [options]\n * @returns {Promise<Model>}\n */\nexport async function parseGLTF(data, options = {}) {\n const { json, bin } = unpack(data)\n const version = String(json.asset?.version ?? '')\n if (!version.startsWith('2.')) throw new PhoriaError(`loadGLTF: glTF ${version || '(no version)'} isn't supported - only glTF 2.0`)\n for (const ext of json.extensionsRequired ?? []) {\n if (SUPPORTED.has(ext)) continue\n const hint = COMPRESSION.has(ext) ? ' - export the model without compression for now' : ''\n throw new PhoriaError(`loadGLTF: the model requires '${ext}', which isn't supported${hint}`)\n }\n const model = new Model({ name: json.scenes?.[json.scene ?? 0]?.name ?? 'model' })\n for (const ext of json.extensionsUsed ?? []) {\n if (!SUPPORTED.has(ext)) warnOnce(model, `the model uses '${ext}', which isn't supported - it is ignored`)\n }\n const build = new Builder(json, bin, options.baseUrl ?? '', model)\n await build.buffers()\n build.scene()\n // either way, embedded images' object urls are released once their textures settle\n const textures = build.textures()\n if (options.waitForTextures ?? true) await textures\n return model\n}\n\n/** @param {ArrayBuffer | Uint8Array | string | Record<string, any>} data */\nfunction unpack(data) {\n if (typeof data === 'string') return { json: JSON.parse(data), bin: null }\n if (!(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) return { json: data, bin: null }\n const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n // 'glTF' little-endian: a binary container of a JSON chunk and an optional binary chunk\n if (bytes.length >= 12 && view.getUint32(0, true) === 0x46546c67) {\n let json = null, bin = null\n for (let at = 12; at + 8 <= bytes.length;) {\n const length = view.getUint32(at, true), type = view.getUint32(at + 4, true)\n const chunk = bytes.subarray(at + 8, at + 8 + length)\n if (type === 0x4e4f534a) json = JSON.parse(new TextDecoder().decode(chunk))\n else if (type === 0x004e4942) bin = chunk\n at += 8 + length\n }\n if (!json) throw new PhoriaError('loadGLTF: the .glb file has no JSON chunk')\n return { json, bin }\n }\n return { json: JSON.parse(new TextDecoder().decode(bytes)), bin: null }\n}\n\nclass Builder {\n /** @type {Uint8Array[]} */ #buffers = []\n /** @type {Map<string, Texture>} */ #textures = new Map()\n /** @type {Map<number, Material>} */ #materials = new Map()\n /** @type {Map<string, Geometry>} */ #geometries = new Map()\n /** @type {Node[]} */ #nodes = []\n /** @type {string[]} */ #objectUrls = []\n\n /** @param {Record<string, any>} json @param {Uint8Array | null} bin @param {string} base @param {Model} model */\n constructor(json, bin, base, model) {\n this.json = json\n this.bin = bin\n this.base = base\n this.model = model\n }\n\n /** @param {string} uri */\n #resolve(uri) {\n try {\n return new URL(uri, this.base || undefined).href\n } catch {\n return uri\n }\n }\n\n async buffers() {\n this.#buffers = await Promise.all((this.json.buffers ?? []).map(async (b, i) => {\n if (b.uri === undefined) {\n if (i !== 0 || !this.bin) throw new PhoriaError(`loadGLTF: buffer ${i} has no uri and there is no binary chunk`)\n return this.bin\n }\n const url = this.#resolve(b.uri)\n const response = await fetch(url).catch((e) => { throw new PhoriaError(`loadGLTF: couldn't fetch buffer '${b.uri}' - ${e.message}`) })\n if (!response.ok) throw new PhoriaError(`loadGLTF: couldn't fetch buffer '${b.uri}' (${response.status})`)\n return new Uint8Array(await response.arrayBuffer())\n }))\n }\n\n /** Resolves when every texture has loaded (failures are warned about, not thrown). */\n async textures() {\n await Promise.all([...this.#textures.values()].map((t) => t.ready.catch((e) => warnOnce(this.model, e.message))))\n for (const url of this.#objectUrls) URL.revokeObjectURL(url)\n }\n\n scene() {\n const json = this.json\n this.#nodes = (json.nodes ?? []).map((_, i) => this.#node(i))\n // parent after every node exists, since children can come before their parents\n ;(json.nodes ?? []).forEach((n, i) => {\n for (const c of n.children ?? []) this.#nodes[i].add(this.#nodes[c])\n })\n const scene = json.scenes?.[json.scene ?? 0]\n const roots = scene ? scene.nodes ?? [] : this.#nodes.map((_, i) => i).filter((i) => !this.#nodes[i].parent)\n for (const i of roots) this.model.add(this.#nodes[i])\n this.model.animations = (json.animations ?? []).map((a, i) => this.#animation(a, i))\n if (this.model.animations.length) {\n const model = this.model\n model.onUpdate((_node, dt) => {\n for (const a of model.animations) a.advance(dt)\n })\n }\n }\n\n /** @param {number} index @returns {Node} */\n #node(index) {\n const n = this.json.nodes[index]\n const name = n.name ?? `node ${index}`\n if (n.skin !== undefined) warnOnce(this.model, `skinned meshes aren't supported - '${name}' is drawn in its bind pose`)\n if (n.weights || (n.mesh !== undefined && this.json.meshes[n.mesh].weights)) warnOnce(this.model, \"morph targets aren't supported - meshes are drawn without them\")\n\n const parts = n.mesh !== undefined ? this.#mesh(n.mesh) : []\n // a node with one primitive is that drawable; with several, a group of them\n /** @type {Node} */\n const node = parts.length === 1 ? parts[0] : new Group()\n for (const part of parts.length > 1 ? parts : []) node.add(part)\n node.name = name\n if (n.matrix) decompose(node, n.matrix)\n else {\n if (n.translation) node.position.set(n.translation[0], n.translation[1], n.translation[2])\n if (n.rotation) node.quaternion.set(n.rotation[0], n.rotation[1], n.rotation[2], n.rotation[3])\n if (n.scale) node.scale.set(n.scale[0], n.scale[1], n.scale[2])\n }\n if (n.camera !== undefined) {\n const camera = this.#camera(n.camera)\n node.add(camera)\n this.model.cameras.push(camera)\n }\n const light = n.extensions?.KHR_lights_punctual?.light\n if (light !== undefined) node.add(this.#light(light))\n if (n.extras && typeof n.extras === 'object') node.userData = { ...n.extras }\n return node\n }\n\n /** @param {number} index @returns {Node[]} */\n #mesh(index) {\n const m = this.json.meshes[index]\n return m.primitives.map((p, i) => {\n const geometry = this.#geometry(p)\n const material = p.material !== undefined ? this.#material(p.material) : this.#defaultMaterial()\n const mode = p.mode ?? 4\n /** @type {Node} */\n let node\n if (mode === 0) node = new Points({ geometry, material: pointMaterial(material) })\n else if (mode === 1 || mode === 2 || mode === 3) node = new Lines({ geometry: lineList(geometry, mode), material: pointMaterial(material) })\n else node = new Mesh({ geometry: mode === 4 ? geometry : triangleList(geometry, mode), material })\n node.name = m.primitives.length > 1 ? `${m.name ?? `mesh ${index}`} ${i}` : m.name ?? `mesh ${index}`\n return node\n })\n }\n\n /** @param {Record<string, any>} p */\n #geometry(p) {\n // primitives often share accessors; share their geometry too\n const key = JSON.stringify([p.attributes, p.indices])\n const cached = this.#geometries.get(key)\n if (cached) return cached\n const a = p.attributes\n if (a.POSITION === undefined) throw new PhoriaError('loadGLTF: a mesh primitive has no POSITION')\n /** @type {import('../geometry/Geometry.js').GeometryOptions} */\n const options = { positions: this.#accessor(a.POSITION) }\n if (a.NORMAL !== undefined) options.normals = this.#accessor(a.NORMAL)\n if (a.TEXCOORD_0 !== undefined) options.uvs = this.#accessor(a.TEXCOORD_0)\n if (a.TEXCOORD_1 !== undefined) options.uvs2 = this.#accessor(a.TEXCOORD_1)\n if (a.COLOR_0 !== undefined) options.colors = srgbColors(/** @type {Float32Array} */ (this.#accessor(a.COLOR_0)), COMPONENTS[this.json.accessors[a.COLOR_0].type])\n if (p.indices !== undefined) options.indices = this.#accessor(p.indices, true)\n const geometry = new Geometry(options)\n this.#geometries.set(key, geometry)\n return geometry\n }\n\n /**\n * An accessor's numbers, as floats (normalized integers scaled), or as integers for indices.\n * @param {number} index @param {boolean} [integers]\n * @returns {Float32Array | Uint32Array}\n */\n #accessor(index, integers = false) {\n const acc = this.json.accessors[index]\n const size = COMPONENTS[acc.type]\n const count = acc.count * size\n const out = integers ? new Uint32Array(count) : new Float32Array(count)\n const scale = acc.normalized && !integers ? 1 / NORMALIZE[acc.componentType] : 1\n if (acc.bufferView !== undefined) this.#read(acc.bufferView, acc.byteOffset ?? 0, acc.componentType, size, acc.count, out, scale)\n if (acc.sparse) {\n // a few elements replaced: indices of the elements, then their values\n const s = acc.sparse\n const at = new Uint32Array(s.count)\n this.#read(s.indices.bufferView, s.indices.byteOffset ?? 0, s.indices.componentType, 1, s.count, at, 1)\n const values = integers ? new Uint32Array(s.count * size) : new Float32Array(s.count * size)\n this.#read(s.values.bufferView, s.values.byteOffset ?? 0, acc.componentType, size, s.count, values, scale)\n for (let i = 0; i < s.count; i++) out.set(values.subarray(i * size, i * size + size), at[i] * size)\n }\n if (acc.normalized && !integers && (acc.componentType === 5120 || acc.componentType === 5122)) {\n for (let i = 0; i < out.length; i++) out[i] = Math.max(out[i], -1)\n }\n return out\n }\n\n /**\n * Copy elements out of a buffer view, honouring its stride.\n * @param {number} viewIndex @param {number} offset @param {number} type component type\n * @param {number} size components per element @param {number} count elements\n * @param {Float32Array | Uint32Array} out @param {number} scale\n */\n #read(viewIndex, offset, type, size, count, out, scale) {\n const bv = this.json.bufferViews[viewIndex]\n const buffer = this.#buffers[bv.buffer]\n const Type = ARRAYS[type]\n if (!Type) throw new PhoriaError(`loadGLTF: unknown component type ${type}`)\n const bytes = Type.BYTES_PER_ELEMENT\n const stride = bv.byteStride || size * bytes\n const start = buffer.byteOffset + (bv.byteOffset ?? 0) + offset\n const view = new DataView(buffer.buffer)\n const get = {\n 5120: (/** @type {number} */ o) => view.getInt8(o),\n 5121: (/** @type {number} */ o) => view.getUint8(o),\n 5122: (/** @type {number} */ o) => view.getInt16(o, true),\n 5123: (/** @type {number} */ o) => view.getUint16(o, true),\n 5125: (/** @type {number} */ o) => view.getUint32(o, true),\n 5126: (/** @type {number} */ o) => view.getFloat32(o, true),\n }[type]\n // the common case - tightly packed and aligned floats - is one copy\n if (type === 5126 && stride === size * 4 && start % 4 === 0 && scale === 1 && out instanceof Float32Array) {\n out.set(new Float32Array(buffer.buffer, start, count * size))\n return\n }\n for (let i = 0; i < count; i++) {\n for (let c = 0; c < size; c++) out[i * size + c] = get(start + i * stride + c * bytes) * scale\n }\n }\n\n /** @param {number} index @returns {Material} */\n #material(index) {\n const cached = this.#materials.get(index)\n if (cached) return cached\n const m = this.json.materials[index]\n const pbr = m.pbrMetallicRoughness ?? {}\n const material = new Material({ name: m.name ?? `material ${index}` })\n const base = pbr.baseColorFactor ?? [1, 1, 1, 1]\n material.color.setLinear(base[0], base[1], base[2])\n material.metalness = pbr.metallicFactor ?? 1\n material.roughness = pbr.roughnessFactor ?? 1\n if (pbr.baseColorTexture) material.map = this.#texture(pbr.baseColorTexture, 'srgb')\n if (pbr.metallicRoughnessTexture) {\n // one texture: roughness in green, metalness in blue - exactly what the two slots read\n material.roughnessMap = material.metalnessMap = this.#texture(pbr.metallicRoughnessTexture, 'linear')\n }\n if (m.normalTexture) {\n material.normalMap = this.#texture(m.normalTexture, 'linear')\n material.normalScale = m.normalTexture.scale ?? 1\n }\n if (m.occlusionTexture) {\n material.aoMap = this.#texture(m.occlusionTexture, 'linear')\n material.aoMapIntensity = Math.min(Math.max(m.occlusionTexture.strength ?? 1, 0), 1)\n }\n if (m.emissiveFactor) material.emissive.setLinear(m.emissiveFactor[0], m.emissiveFactor[1], m.emissiveFactor[2])\n if (m.emissiveTexture) {\n material.emissiveMap = this.#texture(m.emissiveTexture, 'srgb')\n if (!m.emissiveFactor) material.emissive.setLinear(1, 1, 1)\n }\n material.emissiveIntensity = m.extensions?.KHR_materials_emissive_strength?.emissiveStrength ?? 1\n if (m.extensions?.KHR_materials_unlit) material.unlit = true\n // glass, clear coat, cloth, reflectance, brushed metal and translucency, by their factors - their\n // own textures aren't read\n const clamp = (/** @type {number} */ v) => Math.min(Math.max(v, 0), 1)\n const x = m.extensions ?? {}\n const transmission = x.KHR_materials_transmission, coat = x.KHR_materials_clearcoat, sheen = x.KHR_materials_sheen\n if (transmission) material.transmission = clamp(transmission.transmissionFactor ?? 0)\n if (coat) {\n material.clearcoat = clamp(coat.clearcoatFactor ?? 0)\n material.clearcoatRoughness = clamp(coat.clearcoatRoughnessFactor ?? 0)\n }\n if (sheen) {\n const c = sheen.sheenColorFactor ?? [0, 0, 0]\n // glTF's sheen is its colour alone: black is none\n if (Math.max(c[0], c[1], c[2]) > 0) {\n material.sheen = 1\n material.sheenColor.setLinear(c[0], c[1], c[2])\n }\n material.sheenRoughness = clamp(sheen.sheenRoughnessFactor ?? 0)\n }\n if (x.KHR_materials_ior?.ior >= 1) material.ior = x.KHR_materials_ior.ior\n const specular = x.KHR_materials_specular\n if (specular) {\n material.specularIntensity = clamp(specular.specularFactor ?? 1)\n const c = specular.specularColorFactor ?? [1, 1, 1]\n material.specularColor.setLinear(c[0], c[1], c[2])\n }\n const brushed = x.KHR_materials_anisotropy\n if (brushed) {\n material.anisotropy = clamp(brushed.anisotropyStrength ?? 0)\n material.anisotropyRotation = brushed.anisotropyRotation ?? 0\n }\n const translucent = x.KHR_materials_diffuse_transmission\n if (translucent) {\n material.translucency = clamp(translucent.diffuseTransmissionFactor ?? 0)\n const c = translucent.diffuseTransmissionColorFactor ?? [1, 1, 1]\n material.translucencyColor.setLinear(c[0], c[1], c[2])\n }\n if (m.alphaMode === 'BLEND') {\n material.opacity = base[3]\n material.transparent = true\n material.depthWrite = false\n } else if (m.alphaMode === 'MASK') {\n material.alphaTest = m.alphaCutoff ?? 0.5\n }\n material.doubleSided = !!m.doubleSided\n this.#materials.set(index, material)\n return material\n }\n\n // glTF's default for primitives without a material\n #defaultMaterial() {\n let material = this.#materials.get(-1)\n if (!material) this.#materials.set(-1, material = new Material({ name: 'default', metalness: 1, roughness: 1 }))\n return material\n }\n\n /**\n * @param {Record<string, any>} info a textureInfo: index, texCoord, extensions\n * @param {'srgb' | 'linear'} colorSpace what the slot holds\n * @returns {Texture}\n */\n #texture(info, colorSpace) {\n const transform = info.extensions?.KHR_texture_transform\n let texCoord = transform?.texCoord ?? info.texCoord ?? 0\n if (texCoord > 1) {\n warnOnce(this.model, `textures on a third UV set or later (TEXCOORD_${texCoord}) are drawn with the first`)\n texCoord = 0\n }\n const key = JSON.stringify([info.index, colorSpace, transform?.offset, transform?.scale, transform?.rotation, texCoord])\n const cached = this.#textures.get(key)\n if (cached) return cached\n\n const t = this.json.textures[info.index]\n const sampler = this.json.samplers?.[t.sampler] ?? {}\n const image = this.json.images[t.source]\n if (t.source === undefined || !image) throw new PhoriaError(`loadGLTF: texture ${info.index} has no image (compressed textures aren't supported)`)\n let url\n if (image.bufferView !== undefined) {\n const bv = this.json.bufferViews[image.bufferView]\n const buffer = this.#buffers[bv.buffer]\n const bytes = buffer.subarray(bv.byteOffset ?? 0, (bv.byteOffset ?? 0) + bv.byteLength)\n url = URL.createObjectURL(new Blob([/** @type {Uint8Array<ArrayBuffer>} */ (bytes)], { type: image.mimeType ?? 'image/png' }))\n this.#objectUrls.push(url)\n } else {\n url = this.#resolve(image.uri)\n }\n const texture = new Texture({\n url,\n colorSpace,\n wrap: WRAP[sampler.wrapS ?? 10497] ?? 'repeat',\n filter: sampler.magFilter === 9728 ? 'nearest' : 'linear',\n // glTF UVs start at the image's top left, as phoria2's do\n flipY: false,\n repeat: transform?.scale ?? [1, 1],\n offset: transform?.offset ?? [0, 0],\n rotation: transform?.rotation ?? 0,\n uvSet: texCoord,\n })\n this.#textures.set(key, texture)\n return texture\n }\n\n /** @param {number} index @returns {Camera} */\n #camera(index) {\n const c = this.json.cameras[index]\n const name = c.name ?? `camera ${index}`\n if (c.type === 'orthographic') {\n const o = c.orthographic\n return new OrthographicCamera({ name, height: o.ymag * 2, near: o.znear, far: o.zfar })\n }\n const p = c.perspective\n return new PerspectiveCamera({ name, fov: (p.yfov * 180) / Math.PI, near: p.znear, far: p.zfar ?? 1e6 })\n }\n\n /** @param {number} index */\n #light(index) {\n const l = this.json.extensions?.KHR_lights_punctual?.lights?.[index]\n if (!l) throw new PhoriaError(`loadGLTF: KHR_lights_punctual light ${index} doesn't exist`)\n const c = l.color ?? [1, 1, 1]\n // glTF lights shine down their node's -Z; intensities are lux and candela, divided by PI for\n // phoria2's lights (where 1 lights a white surface to white)\n const options = { name: l.name, intensity: (l.intensity ?? 1) / Math.PI }\n let light\n if (l.type === 'directional') light = new DirectionalLight({ ...options, direction: [0, 0, -1] })\n else if (l.type === 'spot') {\n const outer = l.spot?.outerConeAngle ?? Math.PI / 4, inner = l.spot?.innerConeAngle ?? 0\n light = new SpotLight({ ...options, direction: [0, 0, -1], range: l.range ?? 0, angle: outer, penumbra: outer > 0 ? 1 - inner / outer : 0 })\n } else light = new PointLight({ ...options, range: l.range ?? 0 })\n light.color.setLinear(c[0], c[1], c[2])\n return light\n }\n\n /** @param {Record<string, any>} a @param {number} index @returns {Animation} */\n #animation(a, index) {\n /** @type {Track[]} */\n const tracks = []\n for (const ch of a.channels) {\n const path = { translation: 'position', rotation: 'quaternion', scale: 'scale' }[ch.target.path]\n if (!path) {\n warnOnce(this.model, `'${ch.target.path}' animations aren't supported - only translation, rotation and scale`)\n continue\n }\n const node = this.#nodes[ch.target.node]\n if (!node) continue\n const s = a.samplers[ch.sampler]\n tracks.push({\n node, path,\n times: /** @type {Float32Array} */ (this.#accessor(s.input)),\n values: /** @type {Float32Array} */ (this.#accessor(s.output)),\n interpolation: s.interpolation ?? 'LINEAR',\n })\n }\n return new Animation(a.name ?? `animation ${index}`, tracks)\n }\n}\n\n/** Set a node's position, rotation and scale from a column-major matrix. @param {Node} node @param {number[]} m */\nfunction decompose(node, m) {\n let sx = Math.hypot(m[0], m[1], m[2])\n const sy = Math.hypot(m[4], m[5], m[6]), sz = Math.hypot(m[8], m[9], m[10])\n // a mirroring matrix: put the flip in x\n const det = m[0] * (m[5] * m[10] - m[6] * m[9]) - m[4] * (m[1] * m[10] - m[2] * m[9]) + m[8] * (m[1] * m[6] - m[2] * m[5])\n if (det < 0) sx = -sx\n const r = [m[0] / sx, m[1] / sx, m[2] / sx, m[4] / sy, m[5] / sy, m[6] / sy, m[8] / sz, m[9] / sz, m[10] / sz]\n const q = quat.normalize([0, 0, 0, 1], quat.fromMat3([0, 0, 0, 1], r))\n node.position.set(m[12], m[13], m[14])\n node.quaternion.set(q[0], q[1], q[2], q[3])\n node.scale.set(sx, sy, sz)\n}\n\n/** glTF vertex colours are linear RGB(A); phoria2's are sRGB RGB. @param {Float32Array} c @param {number} size */\nfunction srgbColors(c, size) {\n const n = c.length / size\n const out = new Float32Array(n * 3)\n for (let i = 0; i < n; i++) {\n for (let k = 0; k < 3; k++) {\n const v = Math.min(Math.max(c[i * size + k], 0), 1)\n out[i * 3 + k] = v <= 0.0031308 ? v * 12.92 : 1.055 * v ** (1 / 2.4) - 0.055\n }\n }\n return out\n}\n\n/** Points and Lines take their colour and size from a lit material's basics. @param {Material} m */\nfunction pointMaterial(m) {\n return new Material({ name: m.name, color: m.color.getStyle(), opacity: m.opacity, map: m.map, vertexColors: true, size: 2, sizeAttenuation: false })\n}\n\n/** Triangle strips and fans as a plain triangle list. @param {Geometry} g @param {number} mode */\nfunction triangleList(g, mode) {\n const index = g.indices ?? Uint32Array.from({ length: g.vertexCount }, (_, i) => i)\n const out = []\n for (let i = 2; i < index.length; i++) {\n if (mode === 6) out.push(index[0], index[i - 1], index[i])\n // strips alternate winding, so every other triangle swaps two corners\n else if (i % 2 === 0) out.push(index[i - 2], index[i - 1], index[i])\n else out.push(index[i - 1], index[i - 2], index[i])\n }\n return withIndices(g, out, true)\n}\n\n/** Line strips and loops as segment pairs. @param {Geometry} g @param {number} mode */\nfunction lineList(g, mode) {\n if (mode === 1) return g\n const index = g.indices ?? Uint32Array.from({ length: g.vertexCount }, (_, i) => i)\n const out = []\n for (let i = 1; i < index.length; i++) out.push(index[i - 1], index[i])\n if (mode === 2 && index.length > 2) out.push(index[index.length - 1], index[0])\n return withIndices(g, out, false)\n}\n\n/** @param {Geometry} g @param {number[]} indices @param {boolean} triangles keep normals (lines have none) */\nfunction withIndices(g, indices, triangles) {\n // only normals the file gave - reading g.normals would work them out from the strip's own indices,\n // taken as a triangle list; the new geometry works them out from its real triangles instead\n return new Geometry({ positions: g.positions, normals: triangles && g.hasNormals ? g.normals : undefined, uvs: g.uvs ?? undefined, uvs2: g.uvs2 ?? undefined,\n colors: g.colors ?? undefined, indices })\n}\n"],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ import { Ot as e, ot as t } from "./core.js";
2
+ // src/keyboard.js
3
+ var n = ":where(.phoria-sr-only) { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;\n clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }", r = 10, i = 0, a = class {
4
+ #e;
5
+ #t;
6
+ #n;
7
+ #r = null;
8
+ #i;
9
+ #a;
10
+ #o;
11
+ #s = "";
12
+ #c = !0;
13
+ #l = [];
14
+ constructor(e, t, r) {
15
+ if (this.#e = e, this.#t = t, this.#n = r, !document.getElementById("phoria-sr-style")) {
16
+ let e = document.createElement("style");
17
+ e.id = "phoria-sr-style", e.textContent = n, document.head.prepend(e);
18
+ }
19
+ let a = e.canvas, o = `phoria-keys-${++i}`;
20
+ this.#i = document.createElement("div"), this.#i.className = "phoria-sr-only", this.#i.setAttribute("aria-live", "polite"), this.#i.setAttribute("aria-atomic", "true"), this.#a = document.createElement("div"), this.#a.className = "phoria-sr-only", this.#a.id = o, a.after(this.#i, this.#a), this.#o = [
21
+ "tabindex",
22
+ "role",
23
+ "aria-roledescription",
24
+ "aria-label",
25
+ "aria-describedby"
26
+ ].map((e) => [e, a.getAttribute(e)]), a.hasAttribute("tabindex") || (a.tabIndex = 0), a.setAttribute("role", "application"), a.setAttribute("aria-roledescription", "3D view"), a.setAttribute("aria-describedby", o);
27
+ let s = (e) => this.#d(e), c = () => this.clear(), l = () => this.#u();
28
+ a.addEventListener("keydown", s), a.addEventListener("blur", c), a.addEventListener("focus", l), this.#l.push(() => {
29
+ a.removeEventListener("keydown", s), a.removeEventListener("blur", c), a.removeEventListener("focus", l);
30
+ }), this.#u();
31
+ }
32
+ setDescription(e) {
33
+ this.#c = e === null, this.#s = e ?? "", this.#u();
34
+ }
35
+ #u() {
36
+ let e = this.#p().length, t = this.#c ? f(this.#e.scene, e) : this.#s;
37
+ this.#e.canvas.setAttribute("aria-label", t), this.#a.textContent = e ? `Use the arrow keys to move between ${e === 1 ? "the one item" : `${e} items`}, Enter to select, Escape to leave.` : "Nothing here can be selected.";
38
+ }
39
+ clear() {
40
+ this.#r && (this.#r = null, this.#t.focus(null));
41
+ }
42
+ #d(e) {
43
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
44
+ let t = this.#p(), n = this.#r ? t.findIndex((e) => o(e, this.#r)) : -1;
45
+ switch (e.key) {
46
+ case "ArrowRight":
47
+ case "ArrowDown":
48
+ n = n < 0 ? 0 : Math.min(t.length - 1, n + 1);
49
+ break;
50
+ case "ArrowLeft":
51
+ case "ArrowUp":
52
+ n = n < 0 ? t.length - 1 : Math.max(0, n - 1);
53
+ break;
54
+ case "PageDown":
55
+ n = Math.min(t.length - 1, Math.max(0, n) + r);
56
+ break;
57
+ case "PageUp":
58
+ n = Math.max(0, n - r);
59
+ break;
60
+ case "Home":
61
+ n = 0;
62
+ break;
63
+ case "End":
64
+ n = t.length - 1;
65
+ break;
66
+ case "Enter":
67
+ case " ":
68
+ if (!this.#r || n < 0) return;
69
+ e.preventDefault(), this.#t.press(c(t[n]));
70
+ return;
71
+ case "Escape":
72
+ if (!this.#r) return;
73
+ e.preventDefault(), this.clear(), this.#i.textContent = "";
74
+ return;
75
+ default: return;
76
+ }
77
+ if (e.preventDefault(), !t.length) {
78
+ this.#i.textContent = "Nothing here can be selected.";
79
+ return;
80
+ }
81
+ this.#r = t[n];
82
+ let i = c(t[n]);
83
+ this.#t.focus(i), this.#i.textContent = `${this.#n.label?.(i) ?? this.#f(i)}. ${n + 1} of ${t.length}`;
84
+ }
85
+ #f(e) {
86
+ let t = u(this.#t.tooltip(e));
87
+ if (t) return t;
88
+ let n = e.datum;
89
+ if (n != null) {
90
+ if (typeof n != "object") return String(n);
91
+ let e = Object.entries(n).filter(([, e]) => typeof e != "object" || !e).slice(0, 4).map(([e, t]) => `${e}: ${d(t)}`);
92
+ if (e.length) return e.join(", ");
93
+ }
94
+ for (let t = e.node; t; t = t.parent) if (t.name) return t.name;
95
+ return "Item";
96
+ }
97
+ #p() {
98
+ let e = [], n = [], r = this.#t.viewWide(), i = /* @__PURE__ */ new Set(), a = (o, c, l) => {
99
+ if (!o.visible || o.pickable === !1) return;
100
+ let u = !!(o.tooltip || o.onDrag || o.highlight || o.handlersFor("click").length || o.handlersFor("hover").length);
101
+ if (c ||= u, l = o.highlightWhole ? o : l, o.isDrawable) {
102
+ if (l) (c || r) && !i.has(l) && (i.add(l), e.push({
103
+ node: o,
104
+ index: null,
105
+ whole: l
106
+ }));
107
+ else if ("instanceMatrices" in o) for (let n = 0; n < o.count; n++) !t(o.instanceMatrices, n) && (c || r && o.datumAt(n) !== null) && e.push({
108
+ node: o,
109
+ index: n,
110
+ whole: null
111
+ });
112
+ else if (o.drawMode === "points" && Array.isArray(o.data) || s(o)) for (let t = 0; t < o.data.length; t++) (c || r) && e.push({
113
+ node: o,
114
+ index: t,
115
+ whole: null
116
+ });
117
+ else if (o.drawMode === "lines" && Array.isArray(o.data)) for (let e = 0; e < o.data.length; e++) (c || r) && n.push({
118
+ node: o,
119
+ index: e,
120
+ whole: null
121
+ });
122
+ else (u || (c || r) && (o.name || o.datumAt(null) !== null)) && e.push({
123
+ node: o,
124
+ index: null,
125
+ whole: null
126
+ });
127
+ }
128
+ for (let e of o.children) a(e, c, l);
129
+ };
130
+ return a(this.#e.scene, !1, null), e.concat(n);
131
+ }
132
+ dispose() {
133
+ for (let e of this.#l) e();
134
+ let e = this.#e.canvas;
135
+ for (let [t, n] of this.#o) n === null ? e.removeAttribute(t) : e.setAttribute(t, n);
136
+ this.#i.remove(), this.#a.remove();
137
+ }
138
+ }, o = (e, t) => e.node === t.node && e.index === t.index, s = (e) => e.drawMode === "triangles" && !("instanceMatrices" in e) && Array.isArray(e.data) && e.data.length === e.geometry.vertexCount;
139
+ function c({ node: t, index: n, whole: r }) {
140
+ let i = t, a = n !== null && i.drawMode === "points", o = n !== null && s(i), c = n !== null && i.drawMode === "lines", u;
141
+ if (r) u = r.bounds.getCenter();
142
+ else if (n !== null && "instanceMatrices" in i) {
143
+ t.updateWorld();
144
+ let e = i.geometry.bounds.getCenter();
145
+ u = l(i.worldMatrix, l(i.instanceMatrices.subarray(n * 16, n * 16 + 16), e));
146
+ } else if (a || o) {
147
+ let r = i.geometry.positions;
148
+ t.updateWorld(), u = l(i.worldMatrix, new e(r[n * 3], r[n * 3 + 1], r[n * 3 + 2]));
149
+ } else if (c) {
150
+ let r = i.geometry.positions, a = i.geometry.indices, o = a ? a[n * 2] : n * 2, s = a ? a[n * 2 + 1] : n * 2 + 1;
151
+ t.updateWorld(), u = l(i.worldMatrix, new e((r[o * 3] + r[s * 3]) / 2, (r[o * 3 + 1] + r[s * 3 + 1]) / 2, (r[o * 3 + 2] + r[s * 3 + 2]) / 2));
152
+ } else u = t.bounds.getCenter();
153
+ return {
154
+ node: t,
155
+ point: u,
156
+ distance: 0,
157
+ normal: null,
158
+ face: a || c ? n : null,
159
+ instance: n !== null && !a && !o && !c ? n : null,
160
+ uv: null,
161
+ datum: o ? i.data[n] ?? null : i.datumAt?.(n) ?? null
162
+ };
163
+ }
164
+ function l(t, n) {
165
+ let [r, i, a] = n;
166
+ return new e(t[0] * r + t[4] * i + t[8] * a + t[12], t[1] * r + t[5] * i + t[9] * a + t[13], t[2] * r + t[6] * i + t[10] * a + t[14]);
167
+ }
168
+ function u(e) {
169
+ if (e == null || e === !1 || e === "") return "";
170
+ if (typeof e == "string" || typeof e == "number") return String(e).replace(/\s*\n\s*/g, ", ");
171
+ if (globalThis.Node !== void 0 && e instanceof globalThis.Node) return (e.textContent ?? "").trim();
172
+ if (typeof e == "object") {
173
+ let t = e, n = t.rows ? (Array.isArray(t.rows) ? t.rows : Object.entries(t.rows)).map(([e, t]) => `${e}: ${d(t)}`) : [];
174
+ return [t.title, ...n].filter((e) => e !== void 0 && e !== "").join(", ");
175
+ }
176
+ return "";
177
+ }
178
+ var d = (e) => typeof e == "number" ? e.toLocaleString() : String(e);
179
+ function f(e, t) {
180
+ let n = [];
181
+ return e.traverse((t) => {
182
+ let r = t.summary;
183
+ t !== e && t.visible && typeof r == "function" && n.push(r.call(t));
184
+ }), n.length || n.push(t ? `3D view of ${t === 1 ? "one item" : `${t} items`}` : "3D view"), n.join(". ");
185
+ }
186
+ export { a as Keyboard };
187
+
188
+ //# sourceMappingURL=keyboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.js","names":["Vec3","hiddenInstance","STYLE","PAGE","ids","Keyboard","#view","view","#hooks","hooks","#options","options","style","canvas","id","#say","#help","#before","a","keydown","#key","blur","focus","#describe","#cleanup","#auto","text","#description","count","#items","label","autoDescription","#at","items","i","same","it","hitOf","hit","#textOf","tip","textOfContent","datum","parts","v","k","format","n","links","viewWide","wholes","walk","direct","whole","own","perVertex","c","fn","name","value","b","d","node","points","index","vertex","segment","point","local","through","p","idx","x","y","z","m","content","rows","s","scene","summary"],"sources":["../src/keyboard.js"],"sourcesContent":["// Keyboard use of a View, for people who can't use a pointer and for screen readers: the canvas\n// becomes a stop in the page's tab order, and the arrow keys step through what you can act on - each\n// instance, point or node with a tooltip, a handler or data - as hovering would: the hover tint, the\n// tooltip and hover handlers, with Enter or Space as a click. A live region says what each one is.\n// Loaded when a View is given keyboard: true, so apps without it don't carry it.\nimport { hiddenInstance } from './scene/drawables.js'\nimport { Vec3 } from './value/Vec3.js'\n\n/** @import { Hit } from './Raycaster.js' */\n/** @import { TooltipContent } from './tooltip.js' */\n/** @import { Node } from './scene/Node.js' */\n/** @import { View } from './View.js' */\n\n/**\n * @typedef {object} KeyboardOptions\n * @property {(hit: Hit) => string} [label] what a screen reader says for each thing stepped to (default: the\n * tooltip's text, then its data, then the node's name)\n */\n\n/**\n * What the View lends the keyboard: the hover it shows, the click it runs, and what it says about a hit.\n * @typedef {object} KeyboardHooks\n * @property {(hit: Hit | null) => void} focus show this as hovered, or nothing\n * @property {(hit: Hit) => void} press click it\n * @property {(hit: Hit) => TooltipContent} tooltip the tooltip's content for it, if there is a tooltip\n * @property {() => boolean} viewWide does the View itself answer hovers or clicks (a tooltip, handlers)?\n */\n\n/** @typedef {{ node: Node, index: number | null, whole: Node | null }} Item */\n\nconst STYLE = `:where(.phoria-sr-only) { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;\n clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }`\n// how far PageUp and PageDown jump\nconst PAGE = 10\nlet ids = 0\n\nexport class Keyboard {\n /** @type {View} */ #view\n /** @type {KeyboardHooks} */ #hooks\n /** @type {KeyboardOptions} */ #options\n /** The item stepped to, or null. @type {Item | null} */ #at = null\n /** @type {HTMLDivElement} */ #say\n /** @type {HTMLDivElement} */ #help\n /** Attributes the canvas had before, put back on dispose. @type {[string, string | null][]} */ #before\n #description = ''\n #auto = true\n /** @type {(() => void)[]} */ #cleanup = []\n\n /** @param {View} view @param {KeyboardHooks} hooks @param {KeyboardOptions} options */\n constructor(view, hooks, options) {\n this.#view = view\n this.#hooks = hooks\n this.#options = options\n if (!document.getElementById('phoria-sr-style')) {\n const style = document.createElement('style')\n style.id = 'phoria-sr-style'\n style.textContent = STYLE\n document.head.prepend(style)\n }\n const canvas = view.canvas, id = `phoria-keys-${++ids}`\n // what a screen reader says as you step: politely, after what it's saying already\n this.#say = document.createElement('div')\n this.#say.className = 'phoria-sr-only'\n this.#say.setAttribute('aria-live', 'polite')\n this.#say.setAttribute('aria-atomic', 'true')\n // how to use it, read once the canvas has focus\n this.#help = document.createElement('div')\n this.#help.className = 'phoria-sr-only'\n this.#help.id = id\n canvas.after(this.#say, this.#help)\n this.#before = ['tabindex', 'role', 'aria-roledescription', 'aria-label', 'aria-describedby'].map((a) => [a, canvas.getAttribute(a)])\n if (!canvas.hasAttribute('tabindex')) canvas.tabIndex = 0\n canvas.setAttribute('role', 'application')\n canvas.setAttribute('aria-roledescription', '3D view')\n canvas.setAttribute('aria-describedby', id)\n\n const keydown = (/** @type {KeyboardEvent} */ e) => this.#key(e)\n const blur = () => this.clear()\n const focus = () => this.#describe()\n canvas.addEventListener('keydown', keydown)\n canvas.addEventListener('blur', blur)\n canvas.addEventListener('focus', focus)\n this.#cleanup.push(() => {\n canvas.removeEventListener('keydown', keydown)\n canvas.removeEventListener('blur', blur)\n canvas.removeEventListener('focus', focus)\n })\n this.#describe()\n }\n\n /**\n * The canvas's label for screen readers: the View's description, or - when it has none - one made\n * from the scene: what its charts show, and how many things there are to step through.\n * @param {string | null} text\n */\n setDescription(text) {\n this.#auto = text === null\n this.#description = text ?? ''\n this.#describe()\n }\n\n #describe() {\n const count = this.#items().length\n const label = this.#auto ? autoDescription(this.#view.scene, count) : this.#description\n this.#view.canvas.setAttribute('aria-label', label)\n this.#help.textContent = count\n ? `Use the arrow keys to move between ${count === 1 ? 'the one item' : `${count} items`}, Enter to select, Escape to leave.`\n : 'Nothing here can be selected.'\n }\n\n /** Step off whatever was stepped to: the pointer has taken over, or focus has gone. */\n clear() {\n if (!this.#at) return\n this.#at = null\n this.#hooks.focus(null)\n }\n\n /** @param {KeyboardEvent} e */\n #key(e) {\n if (e.altKey || e.ctrlKey || e.metaKey) return\n const items = this.#items()\n let i = this.#at ? items.findIndex((it) => same(it, /** @type {Item} */ (this.#at))) : -1\n switch (e.key) {\n case 'ArrowRight': case 'ArrowDown': i = i < 0 ? 0 : Math.min(items.length - 1, i + 1); break\n case 'ArrowLeft': case 'ArrowUp': i = i < 0 ? items.length - 1 : Math.max(0, i - 1); break\n case 'PageDown': i = Math.min(items.length - 1, Math.max(0, i) + PAGE); break\n case 'PageUp': i = Math.max(0, i - PAGE); break\n case 'Home': i = 0; break\n case 'End': i = items.length - 1; break\n case 'Enter': case ' ':\n if (!this.#at || i < 0) return\n e.preventDefault()\n this.#hooks.press(hitOf(items[i]))\n return\n case 'Escape':\n if (!this.#at) return\n e.preventDefault()\n this.clear()\n this.#say.textContent = ''\n return\n default: return\n }\n // the arrows and paging keys are the view's while it has focus, not the page's to scroll\n e.preventDefault()\n if (!items.length) {\n this.#say.textContent = 'Nothing here can be selected.'\n return\n }\n this.#at = items[i]\n const hit = hitOf(items[i])\n this.#hooks.focus(hit)\n this.#say.textContent = `${this.#options.label?.(hit) ?? this.#textOf(hit)}. ${i + 1} of ${items.length}`\n }\n\n /** What to say about a hit: the tooltip's text, its data, or its node's name. @param {Hit} hit @returns {string} */\n #textOf(hit) {\n const tip = textOfContent(this.#hooks.tooltip(hit))\n if (tip) return tip\n const datum = hit.datum\n if (datum !== null && datum !== undefined) {\n if (typeof datum !== 'object') return String(datum)\n const parts = Object.entries(datum).filter(([, v]) => v === null || typeof v !== 'object').slice(0, 4).map(([k, v]) => `${k}: ${format(v)}`)\n if (parts.length) return parts.join(', ')\n }\n for (let n = /** @type {Node | null} */ (hit.node); n; n = n.parent) if (n.name) return n.name\n return 'Item'\n }\n\n /**\n * What can be stepped to, in scene order and each mesh's instances in order: everything visible and\n * pickable in a subtree with its own tooltip, handlers, drag or tint - and, when the View answers\n * hovers or clicks itself, each thing with data or a name. A highlightWhole subtree is one item, and\n * a surface - a mesh with a row of data per vertex - is a stop per vertex, as picking gives its rows.\n * Lines with a row per segment - a network's links - are a stop per segment, after everything else:\n * the things first, then what joins them. Something with no row and no name of its own is a stop\n * only when it has a handler or tooltip itself, not one it shares with the subtree it's in.\n * @returns {Item[]}\n */\n #items() {\n /** @type {Item[]} */\n const items = [], links = []\n const viewWide = this.#hooks.viewWide()\n /** @type {Set<Node>} */\n const wholes = new Set()\n /** @param {any} n @param {boolean} own @param {Node | null} whole */\n const walk = (n, own, whole) => {\n if (!n.visible || n.pickable === false) return\n const direct = !!(n.tooltip || n.onDrag || n.highlight || n.handlersFor('click').length || n.handlersFor('hover').length)\n own ||= direct\n whole = n.highlightWhole ? n : whole\n if (n.isDrawable) {\n if (whole) {\n if ((own || viewWide) && !wholes.has(whole)) {\n wholes.add(whole)\n items.push({ node: n, index: null, whole })\n }\n } else if ('instanceMatrices' in n) {\n for (let i = 0; i < n.count; i++) {\n if (!hiddenInstance(n.instanceMatrices, i) && (own || (viewWide && n.datumAt(i) !== null))) items.push({ node: n, index: i, whole: null })\n }\n } else if ((n.drawMode === 'points' && Array.isArray(n.data)) || perVertex(n)) {\n for (let i = 0; i < n.data.length; i++) if (own || viewWide) items.push({ node: n, index: i, whole: null })\n } else if (n.drawMode === 'lines' && Array.isArray(n.data)) {\n for (let i = 0; i < n.data.length; i++) if (own || viewWide) links.push({ node: n, index: i, whole: null })\n } else if (direct || ((own || viewWide) && (n.name || n.datumAt(null) !== null))) items.push({ node: n, index: null, whole: null })\n }\n for (const c of n.children) walk(c, own, whole)\n }\n walk(this.#view.scene, false, null)\n return items.concat(links)\n }\n\n dispose() {\n for (const fn of this.#cleanup) fn()\n const canvas = this.#view.canvas\n for (const [name, value] of this.#before) {\n if (value === null) canvas.removeAttribute(name)\n else canvas.setAttribute(name, value)\n }\n this.#say.remove()\n this.#help.remove()\n }\n}\n\n/** @param {Item} a @param {Item} b */\nconst same = (a, b) => a.node === b.node && a.index === b.index\n\n/** A surface: a mesh of triangles with a row of data for each vertex. @param {any} n */\nconst perVertex = (n) => n.drawMode === 'triangles' && !('instanceMatrices' in n) && Array.isArray(n.data) && n.data.length === n.geometry.vertexCount\n\n/**\n * A hit on an item, as the pointer would make over its middle.\n * @param {Item} item @returns {Hit}\n */\nfunction hitOf({ node, index, whole }) {\n const d = /** @type {any} */ (node)\n const points = index !== null && d.drawMode === 'points', vertex = index !== null && perVertex(d)\n const segment = index !== null && d.drawMode === 'lines'\n /** @type {Vec3} */\n let point\n if (whole) point = whole.bounds.getCenter()\n else if (index !== null && 'instanceMatrices' in d) {\n // the middle of the geometry, through the instance's matrix and then the mesh's\n node.updateWorld()\n const local = d.geometry.bounds.getCenter()\n point = through(d.worldMatrix, through(d.instanceMatrices.subarray(index * 16, index * 16 + 16), local))\n } else if (points || vertex) {\n const p = d.geometry.positions\n node.updateWorld()\n point = through(d.worldMatrix, new Vec3(p[index * 3], p[index * 3 + 1], p[index * 3 + 2]))\n } else if (segment) {\n // the middle of the segment: its two ends, by index when the lines have them\n const p = d.geometry.positions, idx = d.geometry.indices\n const a = idx ? idx[index * 2] : index * 2, b = idx ? idx[index * 2 + 1] : index * 2 + 1\n node.updateWorld()\n point = through(d.worldMatrix, new Vec3((p[a * 3] + p[b * 3]) / 2, (p[a * 3 + 1] + p[b * 3 + 1]) / 2, (p[a * 3 + 2] + p[b * 3 + 2]) / 2))\n } else point = node.bounds.getCenter()\n // a surface's vertex is no face or instance - its row is the datum, as a pointer over it finds\n return { node, point, distance: 0, normal: null, face: points || segment ? index : null, instance: index !== null && !points && !vertex && !segment ? index : null,\n uv: null, datum: vertex ? d.data[index] ?? null : d.datumAt?.(index) ?? null }\n}\n\n/** A point through a 4x4 matrix (column-major). @param {ArrayLike<number>} m @param {Vec3} p @returns {Vec3} */\nfunction through(m, p) {\n const [x, y, z] = p\n return new Vec3(m[0] * x + m[4] * y + m[8] * z + m[12], m[1] * x + m[5] * y + m[9] * z + m[13], m[2] * x + m[6] * y + m[10] * z + m[14])\n}\n\n/** The text of a tooltip's content, for a screen reader. @param {TooltipContent} content @returns {string} */\nfunction textOfContent(content) {\n if (content === null || content === undefined || content === false || content === '') return ''\n if (typeof content === 'string' || typeof content === 'number') return String(content).replace(/\\s*\\n\\s*/g, ', ')\n if (typeof globalThis.Node !== 'undefined' && content instanceof globalThis.Node) return (content.textContent ?? '').trim()\n if (typeof content === 'object') {\n const c = /** @type {{ title?: string, rows?: Record<string, unknown> | Array<[string, unknown]> }} */ (content)\n const rows = c.rows ? (Array.isArray(c.rows) ? c.rows : Object.entries(c.rows)).map(([k, v]) => `${k}: ${format(v)}`) : []\n return [c.title, ...rows].filter((s) => s !== undefined && s !== '').join(', ')\n }\n return ''\n}\n\n/** @param {unknown} v */\nconst format = (v) => (typeof v === 'number' ? v.toLocaleString() : String(v))\n\n/**\n * A label for the canvas made from the scene: each chart's summary, or how many things there are.\n * @param {Node} scene @param {number} count @returns {string}\n */\nfunction autoDescription(scene, count) {\n /** @type {string[]} */\n const parts = []\n scene.traverse((n) => {\n const summary = /** @type {any} */ (n).summary\n if (n !== scene && n.visible && typeof summary === 'function') parts.push(summary.call(n))\n })\n if (!parts.length) parts.push(count ? `3D view of ${count === 1 ? 'one item' : `${count} items`}` : '3D view')\n return parts.join('. ')\n}\n"],"mappings":"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"}