@layoutit/polycss-morph 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +298 -0
- package/dist/index.d.ts +298 -0
- package/dist/index.js +1 -0
- package/dist/prepare.cjs +1 -0
- package/dist/prepare.d.cts +118 -0
- package/dist/prepare.d.ts +118 -0
- package/dist/prepare.js +1 -0
- package/dist/validation-CY2nydbS.d.cts +306 -0
- package/dist/validation-CY2nydbS.d.ts +306 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Layoutit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @layoutit/polycss-morph
|
|
2
|
+
|
|
3
|
+
Prepared retained-model deformation and playback for PolyCSS.
|
|
4
|
+
|
|
5
|
+
Version `0.0.1` is the first release candidate. This README documents the
|
|
6
|
+
source-tree API; it does not announce npm registry availability.
|
|
7
|
+
|
|
8
|
+
## Boundary
|
|
9
|
+
|
|
10
|
+
Morph has two public entries:
|
|
11
|
+
|
|
12
|
+
- `@layoutit/polycss-morph/prepare` is Node-only. It reads strict authoring
|
|
13
|
+
config and glTF/GLB source, builds topology and retained render plans,
|
|
14
|
+
emits canonical solid CSS triangle leaves plus packed alpha-atlas fallback
|
|
15
|
+
pages with one local-size slice per polygon, and writes a deterministic,
|
|
16
|
+
content-addressed package with `manifest.json` last.
|
|
17
|
+
- `@layoutit/polycss-morph` is browser-safe. It validates and loads prepared
|
|
18
|
+
packages, mounts one retained PolyCSS graph, and exposes imperative,
|
|
19
|
+
caller-driven runtimes.
|
|
20
|
+
|
|
21
|
+
The generic Node preparer directly creates `static-prepared` and
|
|
22
|
+
`morph-regions` models. The browser runtime executes all four validated
|
|
23
|
+
profiles:
|
|
24
|
+
|
|
25
|
+
| Profile | Runtime contract |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `static-prepared` | Mount a prepared retained graph without deformation. |
|
|
28
|
+
| `morph-regions` | Apply sparse prepared morph targets, semantic controls, springs, and clips. |
|
|
29
|
+
| `joint-skin` | Evaluate a validated joint hierarchy and weighted vertex deformation. |
|
|
30
|
+
| `prepared-playback` | Apply source-ordered model, shape, visibility, opacity, transform, and atlas-row changes. |
|
|
31
|
+
|
|
32
|
+
There are no React or Vue wrappers. React, Vue, and vanilla applications use
|
|
33
|
+
the same imperative package.
|
|
34
|
+
|
|
35
|
+
## Prepare in Node
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { preparePolyMorphModel } from "@layoutit/polycss-morph/prepare";
|
|
39
|
+
|
|
40
|
+
const report = await preparePolyMorphModel({
|
|
41
|
+
configPath: "./source/prepare.json",
|
|
42
|
+
outputRoot: "./public/model/package",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
console.log(report.manifestSha256);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Pass `check: true` to verify that an existing output directory matches the
|
|
49
|
+
deterministic package exactly without rewriting it.
|
|
50
|
+
|
|
51
|
+
## Load and mount in a browser
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import {
|
|
55
|
+
createPolyMorphDeformationRuntime,
|
|
56
|
+
loadPolyMorphPackage,
|
|
57
|
+
mountPolyMorphModel,
|
|
58
|
+
} from "@layoutit/polycss-morph";
|
|
59
|
+
|
|
60
|
+
const loaded = await loadPolyMorphPackage("/model/");
|
|
61
|
+
const mounted = mountPolyMorphModel(host, loaded.model, {
|
|
62
|
+
resources: loaded.resources,
|
|
63
|
+
});
|
|
64
|
+
const deformation = createPolyMorphDeformationRuntime(loaded.model);
|
|
65
|
+
const frame = deformation.sample({
|
|
66
|
+
tick: 0,
|
|
67
|
+
morphWeights: { "corner-lift": 0.5 },
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
mounted.apply({ leaves: frame.leafUpdates });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The browser API is intentionally imperative:
|
|
74
|
+
|
|
75
|
+
- load or validate a model;
|
|
76
|
+
- mount once;
|
|
77
|
+
- create only the runtimes the model uses;
|
|
78
|
+
- sample them from application input or time;
|
|
79
|
+
- pass changed model, shape, or leaf rows to `mounted.apply(...)`;
|
|
80
|
+
- for prepared playback, call `runtime.commit(sample)` only after
|
|
81
|
+
`mounted.apply(sample.update)` succeeds;
|
|
82
|
+
- call `mounted.destroy()` at teardown.
|
|
83
|
+
|
|
84
|
+
Morph owns no `requestAnimationFrame` loop, interval, or other scheduler. A
|
|
85
|
+
mounted model keeps the same leaf elements for its lifetime. Runtime updates do
|
|
86
|
+
not rebuild topology, add or remove leaves, construct image resources, or
|
|
87
|
+
redraw prepared image resources.
|
|
88
|
+
|
|
89
|
+
The browser resolves prepared triangles once during mount. Supporting browsers,
|
|
90
|
+
including Firefox, use a native CSS triangle primitive. WebKit/Safari and other
|
|
91
|
+
browsers without a supported primitive use each leaf's prepared polygon-sized
|
|
92
|
+
atlas slice. Mount creates object URLs from the loader's already-verified image
|
|
93
|
+
bytes and revokes them at teardown; it does not refetch package resources.
|
|
94
|
+
Atlas pages are generated with Node built-ins, so Morph has no Sharp or other
|
|
95
|
+
native image dependency.
|
|
96
|
+
|
|
97
|
+
## Consumer adapters
|
|
98
|
+
|
|
99
|
+
Product-specific source cadence, schemas, input ordering, presentation, and
|
|
100
|
+
oracle tooling stay in the consuming product. Product adapters own their
|
|
101
|
+
prepared packages, mounting paths, presentation, and oracle evidence.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var Je=Object.defineProperty;var Go=Object.getOwnPropertyDescriptor;var Qo=Object.getOwnPropertyNames;var Ko=Object.prototype.hasOwnProperty;var Xo=(o,e)=>{for(var t in e)Je(o,t,{get:e[t],enumerable:!0})},Zo=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Qo(e))!Ko.call(o,r)&&r!==t&&Je(o,r,{get:()=>e[r],enumerable:!(n=Go(e,r))||n.enumerable});return o};var et=o=>Zo(Je({},"__esModule",{value:!0}),o);var on={};Xo(on,{POLY_MORPH_CATALOG_SCHEMA:()=>de,POLY_MORPH_EXECUTABLE_PROFILES:()=>_o,POLY_MORPH_MODEL_SCHEMA:()=>ge,POLY_MORPH_PACKAGE_SCHEMA:()=>ce,PolyMorphContractError:()=>je,PolyMorphPackageError:()=>k,PolyMorphRenderError:()=>we,PolyMorphRuntimeError:()=>K,applyPolyMorphPlaybackFrame:()=>De,assertPolyMorphPackageModelBinding:()=>Ee,buildPolyMorphCatalog:()=>vo,buildPolyMorphPackage:()=>$o,createPolyMorphAnimationRuntime:()=>_e,createPolyMorphControlRuntime:()=>Lo,createPolyMorphControlState:()=>To,createPolyMorphDeformationRuntime:()=>Uo,createPolyMorphPlaybackRuntime:()=>Bo,createPolyMorphPreparedState:()=>Ne,createPolyMorphSkinningRuntime:()=>qo,createPolyMorphSpringRuntime:()=>Jo,createPolyMorphSpringState:()=>Wo,decodePolyMorphJson:()=>be,diffPolyMorphPreparedStates:()=>qe,encodePolyMorphCanonicalJson:()=>Pe,hashPolyMorphBytes:()=>ie,isPolyMorphId:()=>ze,isPolyMorphResourcePath:()=>Ve,loadPolyMorphCatalog:()=>oo,loadPolyMorphPackage:()=>So,mountPolyMorphModel:()=>Co,pickPolyMorphControl:()=>io,stepPolyMorphControls:()=>zo,stepPolyMorphSprings:()=>Yo,stringifyPolyMorphCanonicalJson:()=>Ge,validatePolyMorphCatalog:()=>$e,validatePolyMorphModel:()=>D,validatePolyMorphPackageManifest:()=>xe});module.exports=et(on);var ge="polycss-morph.model@1",de="polycss-morph.catalog@1",ce="polycss-morph.package@1";var uo=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,ot=/^[a-z0-9][a-z0-9._-]*$/,mo=/^\d+\.\d+\.\d+$/,tt=/^[a-f0-9]{64}$/,nt=new Set(["joint-skin","morph-regions","prepared-playback","static-prepared"]),rt=new Set(["animation","joint-skinning","morph-targets","prepared-playback","retained-render","semantic-controls","sparse-updates","springs"]),at=new Set(["atlas-slice","direct-image","solid-quad","solid-triangle"]),it=new Set(["control-value","joint-rotation","joint-scale","joint-translation","morph-weight","shape-matrix"]),je=class extends TypeError{constructor(e,t,n){super(`${t}: ${n}`),this.name="PolyMorphContractError",this.code=e,this.path=t}};function f(o,e,t){throw new je(o,e,t)}function A(o,e,t){(!o||typeof o!="object"||Array.isArray(o))&&f("invalid-type",e,"expected an object");let n=Object.keys(o).sort(),r=[...t].sort();return(n.length!==r.length||n.some((a,i)=>a!==r[i]))&&f("invalid-keys",e,`expected exactly ${r.join(", ")}`),o}function L(o,e){return Array.isArray(o)||f("invalid-type",e,"expected an array"),o}function Z(o,e){return(typeof o!="string"||o.length===0)&&f("invalid-string",e,"expected a non-empty string"),o}function J(o,e){return(typeof o!="number"||!Number.isFinite(o))&&f("invalid-number",e,"expected a finite number"),o}function X(o,e,t=0){let n=J(o,e);return(!Number.isSafeInteger(n)||n<t)&&f("invalid-integer",e,`expected an integer >= ${t}`),n}function We(o,e){return typeof o!="boolean"&&f("invalid-boolean",e,"expected a boolean"),o}function N(o,e){let t=Z(o,e);return uo.test(t)||f("invalid-id",e,"expected a normalized kebab-case id"),t}function G(o,e){let t=new Set;for(let n of o)t.has(n)&&f("duplicate-id",e,`duplicate id ${n}`),t.add(n)}function Me(o,e){let t=L(o,e);return t.length!==3&&f("invalid-vector",e,"expected three components"),t.map((n,r)=>J(n,`${e}[${r}]`))}function se(o,e){let t=L(o,e);return t.length!==16&&f("invalid-matrix",e,"expected sixteen components"),t.map((n,r)=>J(n,`${e}[${r}]`))}function fo(o,e){let t=Z(o,e);return t.split("/").some(n=>!ot.test(n))&&f("invalid-path",e,"expected lowercase URL-safe package path segments"),t}function Te(o,e,t){let n=X(o,e);return n>=t&&f("out-of-range",e,`expected an index below ${t}`),n}function st(o,e){let t=A(o,e,["normals","polygons","vertices"]),n=L(t.vertices,`${e}.vertices`).map((i,s)=>Me(i,`${e}.vertices[${s}]`)),r=L(t.normals,`${e}.normals`).map((i,s)=>Me(i,`${e}.normals[${s}]`));n.length===0&&f("missing-topology",`${e}.vertices`,"expected at least one vertex"),r.length===0&&f("missing-topology",`${e}.normals`,"expected at least one normal");let a=L(t.polygons,`${e}.polygons`).map((i,s)=>{let d=`${e}.polygons[${s}]`,l=A(i,d,["id","normalIndices","vertexIndices"]),c=L(l.vertexIndices,`${d}.vertexIndices`).map((y,b)=>Te(y,`${d}.vertexIndices[${b}]`,n.length)),p=L(l.normalIndices,`${d}.normalIndices`).map((y,b)=>Te(y,`${d}.normalIndices[${b}]`,r.length));return c.length<3&&f("invalid-polygon",d,"expected at least three vertices"),p.length!==c.length&&f("invalid-polygon",d,"normal and vertex index counts must match"),new Set(c).size!==c.length&&f("invalid-polygon",d,"vertex indices must be unique"),{id:N(l.id,`${d}.id`),vertexIndices:c,normalIndices:p}});return a.length===0&&f("missing-topology",`${e}.polygons`,"expected at least one polygon"),G(a.map(i=>i.id),`${e}.polygons`),{vertices:n,normals:r,polygons:a}}function lt(o,e,t){let n=A(o,e,["atlas","fallback","height","id","materialId","matrix","polygonId","shapeId","strategy","width"]),r=Z(n.strategy,`${e}.strategy`);at.has(r)||f("invalid-strategy",`${e}.strategy`,"unknown render strategy");let a=N(n.polygonId,`${e}.polygonId`),i=N(n.shapeId,`${e}.shapeId`),s=N(n.materialId,`${e}.materialId`);t.polygonIds.has(a)||f("unknown-reference",`${e}.polygonId`,a),t.shapeIds.has(i)||f("unknown-reference",`${e}.shapeId`,i),t.materialIds.has(s)||f("unknown-reference",`${e}.materialId`,s);let d=J(n.width,`${e}.width`),l=J(n.height,`${e}.height`);(d<=0||l<=0)&&f("invalid-size",e,"leaf dimensions must be positive");let c=r==="atlas-slice"||r==="direct-image",p=n.atlas===null?null:ho(n.atlas,`${e}.atlas`);c!==(p!==null)&&f("invalid-strategy",`${e}.atlas`,c?"image strategies require an atlas/source slice":"solid strategies cannot declare an atlas/source slice");let y=n.fallback===null?null:dt(n.fallback,`${e}.fallback`);return y!==null&&r!=="solid-triangle"&&f("invalid-strategy",`${e}.fallback`,"only solid-triangle leaves may declare a prepared fallback"),{id:N(n.id,`${e}.id`),polygonId:a,shapeId:i,materialId:s,strategy:r,width:d,height:l,matrix:se(n.matrix,`${e}.matrix`),atlas:p,fallback:y}}function dt(o,e){let t=A(o,e,["atlas","height","matrixFromLeaf","width"]),n=X(t.width,`${e}.width`,1),r=X(t.height,`${e}.height`,1),a=ho(t.atlas,`${e}.atlas`);return(a.width!==n||a.height!==r)&&f("invalid-size",e,"fallback dimensions must match its per-polygon atlas slice"),{width:n,height:r,matrixFromLeaf:se(t.matrixFromLeaf,`${e}.matrixFromLeaf`),atlas:a}}function ho(o,e){let t=A(o,e,["height","pageHeight","pageWidth","resourcePath","width","x","y"]),n={resourcePath:fo(t.resourcePath,`${e}.resourcePath`),x:X(t.x,`${e}.x`),y:X(t.y,`${e}.y`),width:X(t.width,`${e}.width`,1),height:X(t.height,`${e}.height`,1),pageWidth:X(t.pageWidth,`${e}.pageWidth`,1),pageHeight:X(t.pageHeight,`${e}.pageHeight`,1)};return(n.x+n.width>n.pageWidth||n.y+n.height>n.pageHeight)&&f("out-of-range",e,"slice must fit inside its page"),n}function ct(o,e,t){(!o||typeof o!="object"||Array.isArray(o))&&f("invalid-type",e,"expected a deformation object");let n=Z(o.kind,`${e}.kind`);if(n==="none")return A(o,e,["kind"]),{kind:n};if(n==="morph-regions"){let r=A(o,e,["kind","targets"]),a=L(r.targets,`${e}.targets`).map((i,s)=>{let d=`${e}.targets[${s}]`,l=A(i,d,["deltas","id"]),c=L(l.deltas,`${d}.deltas`).map((y,b)=>{let u=`${d}.deltas[${b}]`,M=A(y,u,["normal","position","vertexIndex"]),$=M.position===null?null:Me(M.position,`${u}.position`),h=M.normal===null?null:Me(M.normal,`${u}.normal`);return $===null&&h===null&&f("empty-delta",u,"expected a position or normal delta"),{vertexIndex:Te(M.vertexIndex,`${u}.vertexIndex`,t.vertices.length),position:$,normal:h}});c.length===0&&f("missing-deltas",`${d}.deltas`,"expected at least one delta");let p=c.map(y=>String(y.vertexIndex));return G(p,`${d}.deltas`),{id:N(l.id,`${d}.id`),deltas:c}});return a.length===0&&f("missing-targets",`${e}.targets`,"expected at least one target"),G(a.map(i=>i.id),`${e}.targets`),{kind:n,targets:a}}if(n==="joint-skin"){let r=A(o,e,["joints","kind","vertices"]),a=L(r.joints,`${e}.joints`).map((l,c)=>{let p=`${e}.joints[${c}]`,y=A(l,p,["id","inverseBindMatrix","parentId","restMatrix"]);return{id:N(y.id,`${p}.id`),parentId:y.parentId===null?null:N(y.parentId,`${p}.parentId`),restMatrix:se(y.restMatrix,`${p}.restMatrix`),inverseBindMatrix:se(y.inverseBindMatrix,`${p}.inverseBindMatrix`)}});a.length===0&&f("missing-joints",`${e}.joints`,"expected at least one joint"),G(a.map(l=>l.id),`${e}.joints`),pt(a,`${e}.joints`);let i=new Set(a.map(l=>l.id)),s=L(r.vertices,`${e}.vertices`).map((l,c)=>{let p=`${e}.vertices[${c}]`,y=A(l,p,["influences","vertexIndex"]),b=Te(y.vertexIndex,`${p}.vertexIndex`,t.vertices.length),u=L(y.influences,`${p}.influences`).map(($,h)=>{let v=`${p}.influences[${h}]`,I=A($,v,["jointId","weight"]),E=N(I.jointId,`${v}.jointId`);i.has(E)||f("unknown-reference",`${v}.jointId`,E);let x=J(I.weight,`${v}.weight`);return(x<=0||x>1)&&f("invalid-weight",`${v}.weight`,"expected 0 < weight <= 1"),{jointId:E,weight:x}});u.length===0&&f("missing-influences",`${p}.influences`,"expected at least one influence"),G(u.map($=>$.jointId),`${p}.influences`);let M=u.reduce(($,h)=>$+h.weight,0);return Math.abs(M-1)>1e-6&&f("invalid-weight",`${p}.influences`,"weights must sum to 1"),{vertexIndex:b,influences:u}});s.length!==t.vertices.length&&f("missing-skin-vertex",`${e}.vertices`,"every topology vertex must have one skin record");let d=s.map(l=>String(l.vertexIndex));return G(d,`${e}.vertices`),{kind:n,joints:a,vertices:s}}f("invalid-deformation",`${e}.kind`,`unknown deformation kind ${n}`)}function pt(o,e){let t=new Map(o.map(r=>[r.id,r]));o.filter(r=>r.parentId===null).length!==1&&f("invalid-hierarchy",e,"expected exactly one root joint");for(let r of o){r.parentId!==null&&!t.has(r.parentId)&&f("unknown-reference",e,`joint ${r.id} references ${r.parentId}`);let a=new Set,i=r;for(;i;)a.has(i.id)&&f("invalid-hierarchy",e,`cycle at joint ${i.id}`),a.add(i.id),i=i.parentId===null?void 0:t.get(i.parentId)}}function yt(o){return o==="control-value"||o==="morph-weight"?1:o==="joint-rotation"?4:o==="shape-matrix"?16:3}function mt(o,e,t,n){let r=A(o,e,["interpolation","target","targetId","timesMs","values"]),a=Z(r.target,`${e}.target`);it.has(a)||f("invalid-animation-target",`${e}.target`,a);let i=N(r.targetId,`${e}.targetId`);(a==="control-value"?t.controlIds:a==="morph-weight"?t.targetIds:a==="shape-matrix"?t.shapeIds:t.jointIds).has(i)||f("unknown-reference",`${e}.targetId`,i);let d=Z(r.interpolation,`${e}.interpolation`);d!=="linear"&&d!=="step"&&f("invalid-interpolation",`${e}.interpolation`,d),a==="shape-matrix"&&d!=="step"&&f("invalid-interpolation",`${e}.interpolation`,"shape matrices require step interpolation");let l=L(r.timesMs,`${e}.timesMs`).map((p,y)=>J(p,`${e}.timesMs[${y}]`)),c=L(r.values,`${e}.values`).map((p,y)=>{let b=L(p,`${e}.values[${y}]`),u=yt(a);b.length!==u&&f("invalid-animation-value",`${e}.values[${y}]`,`expected ${u} components`);let M=b.map(($,h)=>J($,`${e}.values[${y}][${h}]`));return a==="joint-rotation"&&Math.hypot(...M)<=1e-12&&f("invalid-animation-value",`${e}.values[${y}]`,"quaternion must be non-zero"),M});return(l.length===0||l.length!==c.length)&&f("invalid-animation-samples",e,"times and values must have the same non-zero length"),(l[0]!==0||l.some((p,y)=>p<0||p>n||y>0&&p<=l[y-1]))&&f("invalid-animation-time",`${e}.timesMs`,"times must start at zero and increase within the clip"),{target:a,targetId:i,interpolation:d,timesMs:l,values:c}}function ut(o,e,t,n){let r=A(o,e,["durationMs","frames","loop"]),a=J(r.durationMs,`${e}.durationMs`);a<=0&&f("invalid-duration",`${e}.durationMs`,"expected a positive duration");let i=L(r.frames,`${e}.frames`).map((s,d)=>{let l=`${e}.frames[${d}]`,c=A(s,l,["leaves","modelMatrix","shapes","timeMs"]),p=J(c.timeMs,`${l}.timeMs`),y=L(c.shapes,`${l}.shapes`).map((u,M)=>{let $=`${l}.shapes[${M}]`,h=A(u,$,["matrix","shapeId"]),v=N(h.shapeId,`${$}.shapeId`);return n.has(v)||f("unknown-reference",`${$}.shapeId`,v),{shapeId:v,matrix:se(h.matrix,`${$}.matrix`)}});G(y.map(u=>u.shapeId),`${l}.shapes`);let b=L(c.leaves,`${l}.leaves`).map((u,M)=>{let $=`${l}.leaves[${M}]`,h=A(u,$,["atlasRow","leafId","matrix","opacity","visible"]),v=N(h.leafId,`${$}.leafId`);t.has(v)||f("unknown-reference",`${$}.leafId`,v);let I=h.opacity===null?null:J(h.opacity,`${$}.opacity`);return I!==null&&(I<0||I>1)&&f("out-of-range",`${$}.opacity`,"expected 0 <= opacity <= 1"),{leafId:v,matrix:h.matrix===null?null:se(h.matrix,`${$}.matrix`),visible:h.visible===null?null:We(h.visible,`${$}.visible`),opacity:I,atlasRow:h.atlasRow===null?null:X(h.atlasRow,`${$}.atlasRow`)}});return G(b.map(u=>u.leafId),`${l}.leaves`),{timeMs:p,modelMatrix:c.modelMatrix===null?null:se(c.modelMatrix,`${l}.modelMatrix`),shapes:y,leaves:b}});return i.length===0&&f("missing-frames",`${e}.frames`,"expected at least one frame"),(i[0].timeMs!==0||i.some((s,d)=>s.timeMs<0||s.timeMs>a||d>0&&s.timeMs<=i[d-1].timeMs))&&f("invalid-frame-time",`${e}.frames`,"frames must start at zero and increase within the timeline"),{durationMs:a,loop:We(r.loop,`${e}.loop`),frames:i}}function ft(o,e){let t=["retained-render"];return o==="morph-regions"&&t.push("morph-targets","sparse-updates"),o==="joint-skin"&&t.push("joint-skinning","sparse-updates"),o==="prepared-playback"&&t.push("prepared-playback","sparse-updates"),e.controls.length>0&&t.push("semantic-controls"),e.springs.length>0&&t.push("springs"),e.animations.length>0&&t.push("animation"),t}function D(o){let t=A(o,"$",["animations","budgets","capabilities","controls","deformation","identity","materials","playback","profile","provenance","render","schema","springs","topology"]);t.schema!==ge&&f("invalid-schema","$.schema",`expected ${ge}`);let n=A(t.identity,"$.identity",["id","name","revision"]),r={id:N(n.id,"$.identity.id"),name:Z(n.name,"$.identity.name"),revision:Z(n.revision,"$.identity.revision")};mo.test(r.revision)||f("invalid-revision","$.identity.revision","expected x.y.z");let a=Z(t.profile,"$.profile");nt.has(a)||f("invalid-profile","$.profile",a);let i=L(t.capabilities,"$.capabilities").map((P,C)=>{let m=Z(P,`$.capabilities[${C}]`);return rt.has(m)||f("invalid-capability",`$.capabilities[${C}]`,m),m});G(i,"$.capabilities"),i.some((P,C)=>C>0&&P<=i[C-1])&&f("non-canonical-order","$.capabilities","capabilities must be sorted");let s=A(t.budgets,"$.budgets",["maxBytes","maxFrames","maxJoints","maxLeaves","maxPolygons","maxResources","maxVertices"]),d={maxVertices:X(s.maxVertices,"$.budgets.maxVertices"),maxPolygons:X(s.maxPolygons,"$.budgets.maxPolygons"),maxLeaves:X(s.maxLeaves,"$.budgets.maxLeaves"),maxFrames:X(s.maxFrames,"$.budgets.maxFrames"),maxJoints:X(s.maxJoints,"$.budgets.maxJoints"),maxResources:X(s.maxResources,"$.budgets.maxResources"),maxBytes:X(s.maxBytes,"$.budgets.maxBytes")},l=st(t.topology,"$.topology"),c=L(t.materials,"$.materials").map((P,C)=>{let m=`$.materials[${C}]`,S=A(P,m,["color","id"]),g=L(S.color,`${m}.color`);g.length!==4&&f("invalid-color",`${m}.color`,"expected four components");let R=g.map((z,q)=>{let ee=J(z,`${m}.color[${q}]`);return(ee<0||ee>1)&&f("out-of-range",`${m}.color[${q}]`,"expected 0 <= component <= 1"),ee});return{id:N(S.id,`${m}.id`),color:R}});c.length===0&&f("missing-materials","$.materials","expected at least one material"),G(c.map(P=>P.id),"$.materials");let p=A(t.render,"$.render",["leaves","modelMatrix","shapes"]),y=L(p.shapes,"$.render.shapes").map((P,C)=>{let m=`$.render.shapes[${C}]`,S=A(P,m,["id","matrix"]);return{id:N(S.id,`${m}.id`),matrix:se(S.matrix,`${m}.matrix`)}});y.length===0&&f("missing-shapes","$.render.shapes","expected at least one shape"),G(y.map(P=>P.id),"$.render.shapes");let b=L(p.leaves,"$.render.leaves").map((P,C)=>lt(P,`$.render.leaves[${C}]`,{polygonIds:new Set(l.polygons.map(m=>m.id)),shapeIds:new Set(y.map(m=>m.id)),materialIds:new Set(c.map(m=>m.id))}));G(b.map(P=>P.id),"$.render.leaves"),G(b.map(P=>P.polygonId),"$.render.leaves[*].polygonId"),b.length!==l.polygons.length&&f("unstable-topology","$.render.leaves","every polygon must bind exactly one retained leaf");let u={modelMatrix:se(p.modelMatrix,"$.render.modelMatrix"),shapes:y,leaves:b},M=ct(t.deformation,"$.deformation",l);(a==="static-prepared"||a==="prepared-playback"?M.kind!=="none":M.kind!==a)&&f("profile-mismatch","$.deformation.kind",`does not match profile ${a}`);let $=new Set(M.kind==="morph-regions"?M.targets.map(P=>P.id):[]),h=new Set(M.kind==="joint-skin"?M.joints.map(P=>P.id):[]),v=L(t.controls,"$.controls").map((P,C)=>{let m=`$.controls[${C}]`,S=A(P,m,["anchor","axis","id","initial","maximum","minimum","radius","targets"]),g=J(S.minimum,`${m}.minimum`),R=J(S.maximum,`${m}.maximum`),z=J(S.initial,`${m}.initial`);(g>R||z<g||z>R)&&f("invalid-control-bounds",m,"expected minimum <= initial <= maximum");let q=Me(S.anchor,`${m}.anchor`),ee=Me(S.axis,`${m}.axis`);Math.hypot(...ee)<1e-9&&f("invalid-control-axis",`${m}.axis`,"axis must be non-zero");let fe=J(S.radius,`${m}.radius`);fe<=0&&f("invalid-control-radius",`${m}.radius`,"radius must be positive");let he=L(S.targets,`${m}.targets`).map((ye,Se)=>{let j=`${m}.targets[${Se}]`,Q=A(ye,j,["scale","targetId"]),Y=N(Q.targetId,`${j}.targetId`);return $.has(Y)||f("unknown-reference",`${j}.targetId`,Y),{targetId:Y,scale:J(Q.scale,`${j}.scale`)}});return G(he.map(ye=>ye.targetId),`${m}.targets`),{id:N(S.id,`${m}.id`),anchor:q,axis:ee,radius:fe,minimum:g,maximum:R,initial:z,targets:he}});G(v.map(P=>P.id),"$.controls");let I=new Set(v.map(P=>P.id)),E=L(t.springs,"$.springs").map((P,C)=>{let m=`$.springs[${C}]`,S=A(P,m,["controlId","damping","id","stiffness"]),g=N(S.controlId,`${m}.controlId`);I.has(g)||f("unknown-reference",`${m}.controlId`,g);let R=J(S.stiffness,`${m}.stiffness`),z=J(S.damping,`${m}.damping`);return(R<=0||z<0)&&f("invalid-spring",m,"expected stiffness > 0 and damping >= 0"),{id:N(S.id,`${m}.id`),controlId:g,stiffness:R,damping:z}});G(E.map(P=>P.id),"$.springs");let x=new Set(y.map(P=>P.id)),w=L(t.animations,"$.animations").map((P,C)=>{let m=`$.animations[${C}]`,S=A(P,m,["channels","durationMs","id","loop"]),g=J(S.durationMs,`${m}.durationMs`);g<=0&&f("invalid-duration",`${m}.durationMs`,"expected a positive duration");let R=L(S.channels,`${m}.channels`).map((q,ee)=>mt(q,`${m}.channels[${ee}]`,{controlIds:I,jointIds:h,shapeIds:x,targetIds:$},g));R.length===0&&f("missing-channels",`${m}.channels`,"expected at least one channel");let z=R.map(q=>`${q.target}:${q.targetId}`);return G(z,`${m}.channels`),{id:N(S.id,`${m}.id`),durationMs:g,loop:We(S.loop,`${m}.loop`),channels:R}});G(w.map(P=>P.id),"$.animations");let W=t.playback===null?null:ut(t.playback,"$.playback",new Set(b.map(P=>P.id)),x);a==="prepared-playback"!=(W!==null)&&f("profile-mismatch","$.playback","playback is required only by the prepared-playback profile");let V=A(t.provenance,"$.provenance",["generator","generatorVersion","sources"]),B=L(V.sources,"$.provenance.sources").map((P,C)=>{let m=`$.provenance.sources[${C}]`,S=A(P,m,["id","kind","license","sha256","uri"]),g=Z(S.kind,`${m}.kind`);g!=="authored"&&g!=="generated"&&g!=="open-data"&&f("invalid-source-kind",`${m}.kind`,g);let R=Z(S.uri,`${m}.uri`);(R.startsWith("/")||R.startsWith("file:")||R.includes("\\"))&&f("invalid-source-uri",`${m}.uri`,"local filesystem paths are forbidden");let z=S.sha256===null?null:Z(S.sha256,`${m}.sha256`);return z!==null&&!tt.test(z)&&f("invalid-hash",`${m}.sha256`,"expected lowercase SHA-256"),{id:N(S.id,`${m}.id`),kind:g,uri:R,sha256:z,license:Z(S.license,`${m}.license`)}});B.length===0&&f("missing-provenance","$.provenance.sources","expected at least one source"),G(B.map(P=>P.id),"$.provenance.sources");let ne={generator:N(V.generator,"$.provenance.generator"),generatorVersion:Z(V.generatorVersion,"$.provenance.generatorVersion"),sources:B};mo.test(ne.generatorVersion)||f("invalid-revision","$.provenance.generatorVersion","expected x.y.z");let O=ft(a,{controls:v,springs:E,animations:w});for(let P of O)i.includes(P)||f("missing-capability","$.capabilities",`profile requires ${P}`);let T=M.kind==="joint-skin"?M.joints.length:0,_=W?.frames.length??0,H=[["maxVertices",l.vertices.length,d.maxVertices],["maxPolygons",l.polygons.length,d.maxPolygons],["maxLeaves",b.length,d.maxLeaves],["maxFrames",_,d.maxFrames],["maxJoints",T,d.maxJoints]];for(let[P,C,m]of H)C>m&&f("budget-exceeded",`$.budgets.${P}`,`${C} exceeds ${m}`);return{schema:ge,identity:r,profile:a,capabilities:i,budgets:d,topology:l,materials:c,render:u,deformation:M,controls:v,springs:E,animations:w,playback:W,provenance:ne}}function ze(o){return uo.test(o)}function Ve(o){try{return fo(o,"$"),!0}catch{return!1}}var k=class extends Error{constructor(e,t,n,r={}){super(`${t}: ${n}`),this.name="PolyMorphPackageError",this.code=e,this.path=t,"cause"in r&&(this.cause=r.cause)}};function Ye(o,e,t){if(o===null)return"null";if(typeof o=="string"||typeof o=="boolean")return JSON.stringify(o);if(typeof o=="number"){if(!Number.isFinite(o))throw new k("invalid-json",e,"numbers must be finite");return JSON.stringify(Object.is(o,-0)?0:o)}if(Array.isArray(o)){if(t.has(o))throw new k("invalid-json",e,"cycles are forbidden");t.add(o);let n=`[${o.map((r,a)=>Ye(r,`${e}[${a}]`,t)).join(",")}]`;return t.delete(o),n}if(typeof o=="object"&&o){if(t.has(o))throw new k("invalid-json",e,"cycles are forbidden");let n=Object.getPrototypeOf(o);if(n!==Object.prototype&&n!==null)throw new k("invalid-json",e,"expected a plain object");t.add(o);let r=o,a=`{${Object.keys(r).sort().map(i=>{let s=r[i];if(s===void 0||typeof s=="function"||typeof s=="symbol")throw new k("invalid-json",`${e}.${i}`,"value is not JSON");return`${JSON.stringify(i)}:${Ye(s,`${e}.${i}`,t)}`}).join(",")}}`;return t.delete(o),a}throw new k("invalid-json",e,"value is not JSON")}function Ge(o){return Ye(o,"$",new WeakSet)}function Pe(o){return new TextEncoder().encode(Ge(o))}function be(o,e="$"){let t;try{t=new TextDecoder("utf-8",{fatal:!0}).decode(o)}catch{throw new k("invalid-utf8",e,"expected UTF-8 bytes")}try{return JSON.parse(t)}catch{throw new k("invalid-json",e,"expected valid JSON")}}async function ie(o){if(!globalThis.crypto?.subtle)throw new k("missing-crypto","$","Web Crypto is required");let e=Uint8Array.from(o),t=await globalThis.crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(n=>n.toString(16).padStart(2,"0")).join("")}var ht=/^[a-f0-9]{64}$/,gt=/^\d+\.\d+\.\d+$/,Mt=/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/,Pt=new Set(["joint-skin","morph-regions","prepared-playback","static-prepared"]),bt=new Set(["data","image","model"]);function F(o,e,t){throw new k(o,e,t)}function Ce(o,e,t){(!o||typeof o!="object"||Array.isArray(o))&&F("invalid-type",e,"expected an object");let n=Object.keys(o).sort(),r=[...t].sort();return(n.length!==r.length||n.some((a,i)=>a!==r[i]))&&F("invalid-keys",e,`expected exactly ${r.join(", ")}`),o}function go(o,e){return Array.isArray(o)||F("invalid-type",e,"expected an array"),o}function le(o,e){return(typeof o!="string"||o.length===0)&&F("invalid-string",e,"expected a non-empty string"),o}function Ke(o,e){let t=le(o,e);return ze(t)||F("invalid-id",e,"expected a normalized kebab-case id"),t}function Xe(o,e){let t=le(o,e);return Ve(t)||F("invalid-path",e,"expected a normalized package-relative path"),t}function Mo(o,e){let t=le(o,e);return gt.test(t)||F("invalid-revision",e,"expected x.y.z"),t}function Po(o,e){let t=le(o,e);return Pt.has(t)||F("invalid-profile",e,t),t}function bo(o,e){let t=le(o,e);return ht.test(t)||F("invalid-hash",e,"expected lowercase SHA-256"),t}function xt(o,e){return(typeof o!="number"||!Number.isSafeInteger(o)||o<0)&&F("invalid-bytes",e,"expected a non-negative safe integer"),o}function $t(o,e){let t=Ce(o,e,["bytes","mediaType","path","role","sha256"]),n=le(t.role,`${e}.role`);bt.has(n)||F("invalid-role",`${e}.role`,n);let r=le(t.mediaType,`${e}.mediaType`).toLowerCase();return(!Mt.test(r)||r!==t.mediaType)&&F("invalid-media-type",`${e}.mediaType`,"expected a normalized type/subtype"),n==="image"&&!r.startsWith("image/")&&F("invalid-media-type",`${e}.mediaType`,"image resources require an image media type"),{path:Xe(t.path,`${e}.path`),role:n,mediaType:r,bytes:xt(t.bytes,`${e}.bytes`),sha256:bo(t.sha256,`${e}.sha256`)}}function Qe(o,e){let t=new Set;for(let n of o)t.has(n)&&F("duplicate",e,n),t.add(n)}function xo(o,e){o.some((t,n)=>n>0&&t<=o[n-1])&&F("non-canonical-order",e,"entries must be unique and sorted")}function xe(o){let e=Ce(o,"$",["identity","modelPath","profile","resources","schema"]);e.schema!==ce&&F("invalid-schema","$.schema",`expected ${ce}`);let t=Ce(e.identity,"$.identity",["id","name","revision"]),n={id:Ke(t.id,"$.identity.id"),name:le(t.name,"$.identity.name"),revision:Mo(t.revision,"$.identity.revision")},r=go(e.resources,"$.resources").map((d,l)=>$t(d,`$.resources[${l}]`));r.length===0&&F("missing-resource","$.resources","expected at least the model resource");let a=r.map(d=>d.path);Qe(a,"$.resources"),xo(a,"$.resources");let i=Xe(e.modelPath,"$.modelPath"),s=r.filter(d=>d.role==="model");return(s.length!==1||s[0].path!==i)&&F("invalid-model-resource","$.resources","expected exactly one model resource matching modelPath"),s[0].mediaType!=="application/json"&&F("invalid-model-resource","$.resources","model resource must be application/json"),{schema:ce,identity:n,profile:Po(e.profile,"$.profile"),modelPath:i,resources:r}}function vt(o,e){let t=Ce(o,e,["id","manifestPath","manifestSha256","name","profile","revision"]),n=Xe(t.manifestPath,`${e}.manifestPath`);return n.endsWith("/manifest.json")||F("invalid-manifest-path",`${e}.manifestPath`,"expected a package manifest.json path"),{id:Ke(t.id,`${e}.id`),name:le(t.name,`${e}.name`),revision:Mo(t.revision,`${e}.revision`),profile:Po(t.profile,`${e}.profile`),manifestPath:n,manifestSha256:bo(t.manifestSha256,`${e}.manifestSha256`)}}function $e(o){let e=Ce(o,"$",["defaultId","packages","schema"]);e.schema!==de&&F("invalid-schema","$.schema",`expected ${de}`);let t=go(e.packages,"$.packages").map((a,i)=>vt(a,`$.packages[${i}]`));t.length===0&&F("missing-package","$.packages","expected at least one package");let n=t.map(a=>a.id);Qe(n,"$.packages"),xo(n,"$.packages"),Qe(t.map(a=>a.manifestPath),"$.packages[*].manifestPath");let r=Ke(e.defaultId,"$.defaultId");return n.includes(r)||F("unknown-default","$.defaultId",r),{schema:de,defaultId:r,packages:t}}var Ze="model.json";function wt(o){return[...new Set(o.render.leaves.flatMap(e=>[...e.atlas?[e.atlas.resourcePath]:[],...e.fallback?[e.fallback.atlas.resourcePath]:[]]))].sort()}async function $o(o,e=[]){let t=D(o),n=Pe(t),r=new Map([[Ze,n]]),a=[{path:Ze,role:"model",mediaType:"application/json",bytes:n.byteLength,sha256:await ie(n)}];for(let l of e){if(r.has(l.path))throw new k("duplicate",l.path,"resource path is already present");let c=Uint8Array.from(l.bytes);r.set(l.path,c),a.push({path:l.path,role:l.role,mediaType:l.mediaType,bytes:c.byteLength,sha256:await ie(c)})}for(let l of wt(t)){let c=a.find(p=>p.path===l);if(!c)throw new k("missing-resource",l,"model image is not included in the package");if(c.role!=="image")throw new k("invalid-role",l,"model image resource must use the image role")}a.sort((l,c)=>l.path<c.path?-1:l.path>c.path?1:0);let i=xe({schema:ce,identity:t.identity,profile:t.profile,modelPath:Ze,resources:a}),s=a.reduce((l,c)=>l+c.bytes,0);if(a.length>t.budgets.maxResources)throw new k("budget-exceeded","$.budgets.maxResources",`${a.length} resources exceed ${t.budgets.maxResources}`);if(s>t.budgets.maxBytes)throw new k("budget-exceeded","$.budgets.maxBytes",`${s} bytes exceed ${t.budgets.maxBytes}`);let d=Pe(i);return{manifest:i,manifestBytes:d,manifestSha256:await ie(d),files:r}}async function vo(o,e){let t=e.map(a=>({id:a.manifest.identity.id,name:a.manifest.identity.name,revision:a.manifest.identity.revision,profile:a.manifest.profile,manifestPath:a.manifestPath,manifestSha256:a.manifestSha256}));t.sort((a,i)=>a.id<i.id?-1:a.id>i.id?1:0);let n=$e({schema:de,defaultId:o,packages:t}),r=Pe(n);return{catalog:n,bytes:r,sha256:await ie(r)}}function Ee(o,e){if(e.identity.id!==o.identity.id||e.identity.name!==o.identity.name||e.identity.revision!==o.identity.revision||e.profile!==o.profile)throw new k("profile-mismatch","$.model","model identity or profile does not match its manifest")}var ko=64*1024*1024,kt=1024,It=128*1024*1024,Io=3e4;function ve(o,e,t){let n=o??e;if(!Number.isSafeInteger(n)||n<=0)throw new k("invalid-limit",t,"expected a positive safe integer");return n}function Ro(o){if(typeof o!="string"||o.length===0||o.includes("\\")||o.includes("#")||o.includes("?"))throw new k("invalid-base-url","$.baseUrl","expected a clean HTTP(S) base URL");let e;try{e=new URL(o,globalThis.location?.href??"https://polycss.invalid/")}catch{throw new k("invalid-base-url","$.baseUrl","expected a valid URL")}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new k("invalid-base-url","$.baseUrl","expected HTTP or HTTPS");return e.pathname.endsWith("/")||(e.pathname+="/"),e}async function Rt(o,e,t){let n=o.headers.get("content-length");if(n!==null){let a=Number(n);if(!Number.isSafeInteger(a)||a<0||a>t)throw new k("resource-too-large",e,`declared bytes exceed ${t}`)}if(o.body?.getReader){let a=o.body.getReader(),i=[],s=0;for(;;){let c=await a.read();if(c.done)break;if(s+=c.value.byteLength,s>t)throw await a.cancel(),new k("resource-too-large",e,`bytes exceed ${t}`);i.push(c.value)}let d=new Uint8Array(s),l=0;for(let c of i)d.set(c,l),l+=c.byteLength;return d}if(n===null)throw new k("resource-too-large",e,"content-length is required without a readable body");let r=new Uint8Array(await o.arrayBuffer());if(r.byteLength>t)throw new k("resource-too-large",e,`bytes exceed ${t}`);return r}async function eo(o,e,t,n,r){let a=n??AbortSignal.timeout(r),i;try{i=await o(e,{cache:"no-store",signal:a})}catch(s){throw a.aborted?s:new k("request-failed",e.pathname,"request failed",{cause:s})}if(!i.ok)throw new k("request-failed",e.pathname,`HTTP ${i.status}`);return Rt(i,e.pathname,t)}async function wo(o,e,t){let n=await ie(o);if(n!==e)throw new k("stale-hash",t,`expected ${e}, received ${n}`)}function St(o,e){let t=e.lastIndexOf("/");return Ue(o,e.slice(0,t+1))}function Ue(o,e){let t=new URL(e,o);if(t.origin!==o.origin||!t.href.startsWith(o.href))throw new k("invalid-path",e,"package path escapes its base URL");return t}async function oo(o,e={}){let t=Ro(o),n=ve(e.maxResourceBytes,ko,"$.maxResourceBytes"),r=e.fetchImpl??globalThis.fetch;if(typeof r!="function")throw new k("missing-fetch","$.fetchImpl","a fetch implementation is required");let a=ve(e.requestTimeoutMs,Io,"$.requestTimeoutMs"),i=await eo(r,Ue(t,"catalog.json"),n,e.signal,a);return{catalog:$e(be(i,"$.catalog")),bytes:i,sha256:await ie(i)}}async function So(o,e={}){let t=Ro(o),n=ve(e.maxResourceBytes,ko,"$.maxResourceBytes"),r=ve(e.maxResources,kt,"$.maxResources"),a=ve(e.maxTotalBytes,It,"$.maxTotalBytes"),i=ve(e.requestTimeoutMs,Io,"$.requestTimeoutMs"),s=e.fetchImpl??globalThis.fetch;if(typeof s!="function")throw new k("missing-fetch","$.fetchImpl","a fetch implementation is required");let d=await oo(t.href,{fetchImpl:s,maxResourceBytes:n,requestTimeoutMs:i,signal:e.signal}),l=e.modelId??d.catalog.defaultId,c=d.catalog.packages.find(x=>x.id===l);if(!c)throw new k("unknown-package","$.modelId",l);let p=await eo(s,Ue(t,c.manifestPath),n,e.signal,i);await wo(p,c.manifestSha256,c.manifestPath);let y=xe(be(p,"$.manifest"));if(y.identity.id!==c.id||y.identity.name!==c.name||y.identity.revision!==c.revision||y.profile!==c.profile)throw new k("profile-mismatch","$.manifest","catalog row does not match its manifest");let b=St(t,c.manifestPath);if(y.resources.length>r)throw new k("package-too-large","$.manifest.resources",`${y.resources.length} resources exceed ${r}`);let u=0;for(let x of y.resources){if(x.bytes>n)throw new k("resource-too-large",x.path,`declared bytes exceed ${n}`);if(u+=x.bytes,u>a)throw new k("package-too-large",x.path,`declared package bytes exceed ${a}`)}let M=new Map,$=async x=>{let w=await eo(s,Ue(b,x.path),Math.min(n,x.bytes),e.signal,i);if(w.byteLength!==x.bytes)throw new k("stale-size",x.path,`expected ${x.bytes}, received ${w.byteLength}`);return await wo(w,x.sha256,x.path),{descriptor:x,bytes:w}},h=y.resources.find(x=>x.path===y.modelPath),v=await $(h);M.set(h.path,v);let I=D(be(v.bytes,"$.model"));if(Ee(y,I),y.resources.length>I.budgets.maxResources)throw new k("budget-exceeded","$.budgets.maxResources",`${y.resources.length} resources exceed ${I.budgets.maxResources}`);if(u>I.budgets.maxBytes)throw new k("budget-exceeded","$.budgets.maxBytes",`${u} bytes exceed ${I.budgets.maxBytes}`);for(let x of y.resources)x!==h&&M.set(x.path,await $(x));let E=new Set(I.render.leaves.flatMap(x=>[...x.atlas?[x.atlas.resourcePath]:[],...x.fallback?[x.fallback.atlas.resourcePath]:[]]));for(let x of E){let w=M.get(x);if(!w)throw new k("missing-resource",x,"model image is not declared by the package");if(w.descriptor.role!=="image")throw new k("invalid-role",x,"model image resource must use the image role")}return{catalog:d.catalog,catalogSha256:d.sha256,catalogRow:c,manifest:y,manifestSha256:c.manifestSha256,model:I,resources:M}}var te=require("@layoutit/polycss");var we=class extends Error{constructor(e,t,n){super(`${t}: ${n}`),this.name="PolyMorphRenderError",this.code=e,this.path=t}};var jt={"atlas-slice":"s","direct-image":"s","solid-quad":"b","solid-triangle":"u"};function U(o,e,t){throw new we(o,e,t)}function no(o,e){return(!Array.isArray(o)||o.length!==16||o.some(t=>typeof t!="number"||!Number.isFinite(t)))&&U("invalid-matrix",e,"expected sixteen finite components"),o}function me(o){return`matrix3d(${(0,te.formatMatrix3dValues)(o)})`}function Ct(o,e){let t=new Array(16).fill(0);for(let n=0;n<4;n+=1)for(let r=0;r<4;r+=1){let a=0;for(let i=0;i<4;i+=1)a+=o[i*4+r]*e[n*4+i];t[n*4+r]=Object.is(a,-0)?0:a}return t}function to(o,e,t){return t&&o.fallback?Ct(e,o.fallback.matrixFromLeaf):e}function Ot(o){let[e,t,n,r]=o;return`rgba(${Math.round(e*255)}, ${Math.round(t*255)}, ${Math.round(n*255)}, ${r})`}function ro(o,e,t,n=[]){(!o||typeof o!="object"||Array.isArray(o))&&U("invalid-update",e,"expected an object");let r=new Set([...t,...n]),a=Object.keys(o);return(t.some(i=>!a.includes(i))||a.some(i=>!r.has(i)))&&U("invalid-update",e,`allowed keys are ${[...r].sort().join(", ")}`),o}function jo(o,e){let t=new Set;for(let n of o)t.has(n)&&U("duplicate-update",e,n),t.add(n)}function At(o,e){let t=ro(o,e,["matrix","shapeId"]);return typeof t.shapeId!="string"&&U("invalid-update",`${e}.shapeId`,"expected a string"),{shapeId:t.shapeId,matrix:no(t.matrix,`${e}.matrix`)}}function Lt(o,e){let t=ro(o,e,["leafId"],["atlasRow","matrix","opacity","visible"]);typeof t.leafId!="string"&&U("invalid-update",`${e}.leafId`,"expected a string");let n={leafId:t.leafId};return t.matrix!==void 0&&(n.matrix=no(t.matrix,`${e}.matrix`)),t.visible!==void 0&&(typeof t.visible!="boolean"&&U("invalid-update",`${e}.visible`,"expected a boolean"),n.visible=t.visible),t.opacity!==void 0&&((typeof t.opacity!="number"||!Number.isFinite(t.opacity)||t.opacity<0||t.opacity>1)&&U("invalid-update",`${e}.opacity`,"expected 0 <= opacity <= 1"),n.opacity=t.opacity),t.atlasRow!==void 0&&((!Number.isSafeInteger(t.atlasRow)||t.atlasRow<0)&&U("invalid-update",`${e}.atlasRow`,"expected a non-negative integer"),n.atlasRow=t.atlasRow),n}function Tt(o){let e=ro(o,"$",[],["leaves","modelMatrix","shapes"]),t=e.shapes===void 0?void 0:(()=>{Array.isArray(e.shapes)||U("invalid-update","$.shapes","expected an array");let r=e.shapes.map((a,i)=>At(a,`$.shapes[${i}]`));return jo(r.map(a=>a.shapeId),"$.shapes"),r})(),n=e.leaves===void 0?void 0:(()=>{Array.isArray(e.leaves)||U("invalid-update","$.leaves","expected an array");let r=e.leaves.map((a,i)=>Lt(a,`$.leaves[${i}]`));return jo(r.map(a=>a.leafId),"$.leaves"),r})();return{...e.modelMatrix===void 0?{}:{modelMatrix:no(e.modelMatrix,"$.modelMatrix")},...t===void 0?{}:{shapes:t},...n===void 0?{}:{leaves:n}}}function zt(o,e,t,n){o.style.setProperty("--polycss-atlas-width",`${e.width}px`),o.style.setProperty("--polycss-atlas-height",`${e.height}px`),o.style.backgroundImage=`url("${n.replace(/"/gu,"%22")}")`,o.style.backgroundPosition=`${-t.x}px ${-t.y}px`,o.style.backgroundSize=`${t.pageWidth}px ${t.pageHeight}px`}function Vt(o,e,t,n,r){let a=`url("${r.replace(/"/gu,"%22")}")`,i=`${-e.x}px ${-e.y}px`,s=`${e.pageWidth}px ${e.pageHeight}px`;o.style.width=`${t}px`,o.style.height=`${n}px`,o.style.backgroundColor="currentColor",o.style.setProperty("mask-image",a),o.style.setProperty("mask-mode","alpha"),o.style.setProperty("mask-position",i),o.style.setProperty("mask-repeat","no-repeat"),o.style.setProperty("mask-size",s),o.style.setProperty("-webkit-mask-image",a),o.style.setProperty("-webkit-mask-position",i),o.style.setProperty("-webkit-mask-repeat","no-repeat"),o.style.setProperty("-webkit-mask-size",s)}function Et(o,e,t,n,r){let a=r?e.fallback:null,i=o.createElement(a?"s":jt[e.strategy]);return i.className="polycss-morph-leaf",i.dataset.polyMorphLeaf=e.id,i.dataset.polyMorphStrategy=e.strategy,i.dataset.polyMorphResolvedStrategy=a?"atlas-slice":e.strategy,i.style.transform=me(to(e,e.matrix,a!==null)),i.style.color=Ot(t),i.style.backfaceVisibility="visible",i.style.backgroundRepeat="no-repeat",i.style.opacity="1",i.style.transformOrigin="0 0",i.style.visibility="visible",e.atlas?(i.style.width=`${e.width}px`,i.style.height=`${e.height}px`,zt(i,e,e.atlas,n(e.atlas.resourcePath,e.id))):a?Vt(i,a.atlas,a.width,a.height,n(a.atlas.resourcePath,e.id)):e.strategy==="solid-quad"&&(i.style.width=`${e.width}px`,i.style.height=`${e.height}px`),i}function Co(o,e,t={}){(!o||typeof o.appendChild!="function"||!o.ownerDocument)&&U("invalid-host","$.host","expected an HTMLElement");let n=D(e),r=o.ownerDocument,a=n.render.leaves.some(g=>g.strategy==="solid-triangle")&&!(0,te.isSolidTriangleSupported)(r),i=new Map,s=typeof r.defaultView?.URL?.createObjectURL=="function"?r.defaultView.URL:globalThis.URL,d=r.defaultView?.Blob??globalThis.Blob,l=()=>{for(let g of i.values())s.revokeObjectURL(g);i.clear()},c=(g,R)=>{let z=i.get(g);if(z)return z;let q=t.resources?.get(g);(!q||q.descriptor.path!==g||q.descriptor.role!=="image")&&U("missing-resource",R,"image-backed leaves require their verified package resource"),(typeof s?.createObjectURL!="function"||typeof s?.revokeObjectURL!="function"||typeof d!="function")&&U("missing-object-url",R,"this browser cannot mount verified image bytes");let ee=q.bytes.slice(),pe=s.createObjectURL(new d([ee.buffer],{type:q.descriptor.mediaType}));return i.set(g,pe),pe};try{for(let g of n.render.leaves)g.atlas&&c(g.atlas.resourcePath,g.id),a&&g.strategy==="solid-triangle"&&(g.fallback||U("missing-solid-triangle-fallback",`${g.id}.fallback`,"this browser requires a prepared per-polygon atlas slice"),c(g.fallback.atlas.resourcePath,g.id))}catch(g){throw l(),g}(0,te.injectPolyBaseStyles)(r);let p=r.defaultView?.getComputedStyle(o),y=o.style.position,b=!1;(!p||p.position==="static"||p.position==="")&&(o.style.position="relative",b=!0);let u=t.camera??(0,te.createPolyCamera)({zoom:1}),M=r.createElement("div");M.className="polycss-camera polycss-morph-camera";let $=(0,te.capturePolyCameraSnapshot)(u);M.style.perspective=$.appliedPerspectiveStyle,M.dataset.polycssCameraProjection=$.projection,o.appendChild(M);let h=r.createElement("div");h.className="polycss-scene polycss-morph-scene",h.setAttribute("aria-hidden","true");let v=(0,te.buildPolyCameraSceneTransform)(u.state);h.style.transform=v,M.appendChild(h);let I=r.createElement("div");I.className="polycss-mesh polycss-morph-model",I.dataset.polyMorphModel=n.identity.id;let E=me(n.render.modelMatrix);I.style.transform=E,h.appendChild(I);let x=new Map,w=new Map;for(let g of n.render.shapes){let R=r.createElement("div");R.className="polycss-mesh polycss-morph-shape",R.dataset.polyMorphShape=g.id;let z=me(g.matrix);R.style.transform=z,I.appendChild(R),x.set(g.id,R),w.set(g.id,z)}let W=new Map(n.materials.map(g=>[g.id,g])),V=new Map,B=new Map;for(let g of n.render.leaves){let R=x.get(g.shapeId),z=W.get(g.materialId);(!R||!z)&&U("mount-coverage",g.id,"leaf references are incomplete");let q=Et(r,g,z.color,c,a&&g.strategy==="solid-triangle");R.appendChild(q),V.set(g.id,{id:g.id,plan:g,element:q}),B.set(g.id,{transform:me(to(g,g.matrix,a&&g.strategy==="solid-triangle")),visible:!0,opacity:1,atlasRow:0})}let ne=[...x.entries()],O=[...V.entries()],T=!1,_=v,H={applyCount:0,totalTransformWrites:0,totalVisibilityWrites:0,totalOpacityWrites:0,totalAtlasRowWrites:0},P=()=>{T&&U("destroyed","$","mounted model is destroyed")},C=()=>{P(),(x.size!==ne.length||V.size!==O.length)&&U("identity-drift","$","retained handle maps changed");for(let[g,R]of ne)(x.get(g)!==R||R.parentElement!==I)&&U("identity-drift",g,"shape element identity changed");for(let[g,R]of O){let z=x.get(R.plan.shapeId);(V.get(g)!==R||R.element.parentElement!==z)&&U("identity-drift",g,"leaf element identity changed")}},S={model:n,camera:u,cameraElement:M,sceneElement:h,modelElement:I,shapeElements:x,leafHandles:V,get stats(){return{mountCount:1,shapeRoots:x.size,leafCount:V.size,topologyConstructions:1,atlasConstructions:0,schedulerCount:0,...H}},get destroyed(){return T},apply:g=>{P();let R=Tt(g),z=(R.shapes??[]).map(j=>{let Q=x.get(j.shapeId);return Q||U("unknown-shape",j.shapeId,"no retained shape handle"),{shape:j,element:Q}}),q=(R.leaves??[]).map(j=>{let Q=V.get(j.leafId),Y=B.get(j.leafId);(!Q||!Y)&&U("unknown-leaf",j.leafId,"no retained leaf handle");let Le;if(j.atlasRow!==void 0){let oe=Q.plan.atlas;oe||U("invalid-atlas-row",j.leafId,"leaf has no image rows");let yo=oe.y+j.atlasRow*oe.height;yo+oe.height>oe.pageHeight&&U("invalid-atlas-row",j.leafId,"row exceeds the image page"),Le=`${-oe.x}px ${-yo}px`}return{leaf:j,handle:Q,state:Y,atlasPosition:Le}});C();let ee=0,pe=0,fe=0,he=0,ye=0,Se=0;if(R.modelMatrix){let j=me(R.modelMatrix);E!==j&&(E=j,I.style.transform=j,ee+=1)}for(let{shape:j,element:Q}of z){let Y=me(j.matrix);w.get(j.shapeId)!==Y&&(w.set(j.shapeId,Y),Q.style.transform=Y,pe+=1)}for(let{leaf:j,handle:Q,state:Y,atlasPosition:Le}of q){if(j.matrix){let oe=me(to(Q.plan,j.matrix,a&&Q.plan.strategy==="solid-triangle"));Y.transform!==oe&&(Y.transform=oe,Q.element.style.transform=oe,fe+=1)}if(j.visible!==void 0){let oe=j.visible?"visible":"hidden";Y.visible!==j.visible&&(Y.visible=j.visible,Q.element.style.visibility=oe,he+=1)}if(j.opacity!==void 0){let oe=String(j.opacity);Y.opacity!==j.opacity&&(Y.opacity=j.opacity,Q.element.style.opacity=oe,ye+=1)}j.atlasRow!==void 0&&Y.atlasRow!==j.atlasRow&&(Y.atlasRow=j.atlasRow,Q.element.style.backgroundPosition=Le,Se+=1)}return C(),H.applyCount+=1,H.totalTransformWrites+=ee+pe+fe,H.totalVisibilityWrites+=he,H.totalOpacityWrites+=ye,H.totalAtlasRowWrites+=Se,{modelTransformWrites:ee,shapeTransformWrites:pe,leafTransformWrites:fe,visibilityWrites:he,opacityWrites:ye,atlasRowWrites:Se,dirtyLeavesVisited:R.leaves?.length??0,domCreations:0,domRemovals:0,topologyConstructions:0,atlasRedraws:0,schedulerCallbacks:0}},updateCamera(){P();let g=(0,te.buildPolyCameraSceneTransform)(u.state);if(_===g)return!1;_=g,h.style.transform=g;let R=(0,te.capturePolyCameraSnapshot)(u);return M.style.perspective=R.appliedPerspectiveStyle,M.dataset.polycssCameraProjection=R.projection,!0},assertStableDomIdentity:C,destroy(){T||(T=!0,M.remove(),x.clear(),V.clear(),B.clear(),w.clear(),l(),b&&o.style.position==="relative"&&(o.style.position=y))}};return S.assertStableDomIdentity(),S}var K=class extends Error{constructor(e,t,n){super(`${t}: ${n}`),this.name="PolyMorphRuntimeError",this.code=e,this.path=t}};function Oo(o,e,t){throw new K(o,e,t)}function Be(o){return Object.freeze([...o])}function Ut(o,e){let{timesMs:t,values:n}=o;if(e<=t[0])return Be(n[0]);for(let r=1;r<t.length;r+=1){let a=t[r];if(e>a)continue;let i=t[r-1],s=n[r-1],d=n[r];if(e===a)return Be(d);if(o.interpolation==="step")return Be(s);let l=(e-i)/(a-i);if(o.target==="joint-rotation"){let p=s.reduce((u,M,$)=>u+M*d[$],0)<0?-1:1,y=s.map((u,M)=>u+(d[M]*p-u)*l),b=Math.hypot(...y);return Object.freeze(y.map(u=>u/b))}return Object.freeze(s.map((c,p)=>c+(d[p]-c)*l))}return Be(n[n.length-1])}function Bt(o,e){if(o.loop){let t=e%o.durationMs;return Object.is(t,-0)?0:t}return Math.min(e,o.durationMs)}function _e(o){let e=D(o),t=new Map(e.animations.map(n=>[n.id,n]));return Object.freeze({model:e,clipIds:Object.freeze([...t.keys()]),sample(n,r){let a=t.get(n);a||Oo("unknown-clip","$.clipId",n),(!Number.isFinite(r)||r<0)&&Oo("invalid-time","$.timeMs","expected a finite non-negative time");let i=Bt(a,r),s={},d={},l=new Map,c=new Map;for(let p of a.channels){let y=Ut(p,i);if(p.target==="morph-weight"&&(s[p.targetId]=y[0]),p.target==="control-value"&&(d[p.targetId]=y[0]),p.target==="shape-matrix"&&c.set(p.targetId,y),p.target.startsWith("joint-")){let b=l.get(p.targetId)??{};p.target==="joint-translation"?b.translation=y:p.target==="joint-rotation"?b.rotation=y:b.scale=y,l.set(p.targetId,b)}}return{clipId:n,requestedTimeMs:r,sampledTimeMs:i,morphWeights:Object.freeze(s),controlValues:Object.freeze(d),jointTransforms:l,shapeMatrices:c}}})}function ao(o,e,t){throw new K(o,e,t)}function Ao(o){return o===null?null:((!Array.isArray(o)||o.length!==3||o.some(e=>typeof e!="number"||!Number.isFinite(e)))&&ao("invalid-point","$.point","expected three finite components or null"),[o[0],o[1],o[2]])}function _t(o){let e=Math.hypot(...o.axis);return[o.axis[0]/e,o.axis[1]/e,o.axis[2]/e]}function Lo(o){let e=D(o);return Object.freeze({model:e,controlIds:Object.freeze(e.controls.map(t=>t.id)),controls:new Map(e.controls.map(t=>[t.id,t]))})}function To(o){return Object.freeze({tick:-1,active:!1,heldControlId:null,holdStartPoint:null,holdStartValue:0,values:Object.freeze(Object.fromEntries(o.controlIds.map(e=>[e,o.controls.get(e).initial]))),frozenControlIds:Object.freeze([])})}function io(o,e){let t=Ao(e),n=null;for(let r of o.controlIds){let a=o.controls.get(r),i=Math.hypot(t[0]-a.anchor[0],t[1]-a.anchor[1],t[2]-a.anchor[2]);i<=a.radius&&(!n||i<n.distance)&&(n={id:r,distance:i})}return n?.id??null}function zo(o,e,t){(!e||!Number.isSafeInteger(e.tick)||e.tick<-1)&&ao("invalid-state","$.state","control state is invalid"),typeof t?.active!="boolean"&&ao("invalid-input","$.active","expected a boolean");let n=Ao(t.point),r=e.heldControlId,a=e.holdStartPoint,i=e.holdStartValue,s=null,d=null,l={...e.values},c=new Set(e.frozenControlIds),p=t.active&&!e.active,y=!t.active&&e.active;if(p&&n&&(r=io(o,n),r&&(s=r,a=n,i=l[r]??o.controls.get(r).initial,c.delete(r))),t.active&&r&&n&&a){let u=o.controls.get(r),M=_t(u),$=(n[0]-a[0])*M[0]+(n[1]-a[1])*M[1]+(n[2]-a[2])*M[2];l[r]=Math.max(u.minimum,Math.min(u.maximum,i+$))}y&&(d=r,r&&(t.freezeOnRelease===!0?c.add(r):c.delete(r)),r=null,a=null,i=0);let b=Object.freeze({tick:e.tick+1,active:t.active,heldControlId:r,holdStartPoint:a,holdStartValue:i,values:Object.freeze(l),frozenControlIds:Object.freeze([...c].sort())});return Object.freeze({state:b,pickedControlId:s,releasedControlId:d,heldTarget:t.active&&r?Object.freeze({controlId:r,value:l[r]}):null})}var ke=require("@layoutit/polycss");function re(o,e,t){throw new K(o,e,t)}function Ft(o,e){return(typeof o!="number"||!Number.isFinite(o))&&re("invalid-number",e,"expected a finite number"),Object.is(o,-0)?0:o}function Eo(o){let e=Math.hypot(...o);return e<=1e-12?[0,0,0]:[o[0]/e,o[1]/e,o[2]/e]}function Fe(o){return o.map(e=>[e[0],e[1],e[2]])}function He(o){for(let e of o)Object.freeze(e);return Object.freeze(o)}function Ht(o,e){let[t,n,r]=o.vertexIndices,a=e[t],i=e[n],s=e[r],d=(0,ke.computeSolidTrianglePlanFromCssPoints)(o.polygon,0,{seamBleed:0},{basis:o.basis??void 0,includeColor:!1,primitive:"corner-bevel"},a[0],a[1],a[2],i[0],i[1],i[2],s[0],s[1],s[2]);if(!d)return{matrix:null,visible:!1};let l=/^matrix3d\(([^)]+)\)$/u.exec(d.transformText);l||re("invalid-transform",o.leaf.id,"PolyCSS returned no matrix3d");let c=l[1].split(",").map(Number);(c.length!==16||c.some(b=>!Number.isFinite(b)))&&re("invalid-transform",o.leaf.id,"PolyCSS returned an invalid matrix3d");let p=ke.SOLID_TRIANGLE_CANONICAL_SIZE/o.leaf.width,y=ke.SOLID_TRIANGLE_CANONICAL_SIZE/o.leaf.height;for(let b of[0,1,2])c[b]*=p;for(let b of[4,5,6])c[b]*=y;return{matrix:c,visible:!0}}function Nt(o,e){let[t,n,r,a]=o.vertexIndices,i=e[t],s=e[n],d=e[r],l=e[a],c=[s[0]+l[0]-i[0],s[1]+l[1]-i[1],s[2]+l[2]-i[2]];Math.hypot(c[0]-d[0],c[1]-d[1],c[2]-d[2])>1e-6&&re("non-affine-polygon",o.leaf.id,"deformed quad is not a parallelogram");let p=[(s[0]-i[0])/o.leaf.width,(s[1]-i[1])/o.leaf.width,(s[2]-i[2])/o.leaf.width],y=[(l[0]-i[0])/o.leaf.height,(l[1]-i[1])/o.leaf.height,(l[2]-i[2])/o.leaf.height],b=[p[1]*y[2]-p[2]*y[1],p[2]*y[0]-p[0]*y[2],p[0]*y[1]-p[1]*y[0]],u=Eo(b);return Math.hypot(...u)<=1e-12&&re("degenerate-polygon",o.leaf.id,"deformed quad has no area"),{matrix:[p[0],p[1],p[2],0,y[0],y[1],y[2],0,u[0],u[1],u[2],0,i[0],i[1],i[2],1],visible:!0}}function so(o,e){if(o.vertexIndices.length===3)return Ht(o,e);if(o.vertexIndices.length===4)return Nt(o,e);re("unsupported-deformation",o.leaf.id,"caller-driven deformation supports prepared triangles and affine quads")}function lo(o,e){let t=o.topology.polygons.find(i=>i.id===e.polygonId);t||re("unknown-polygon",e.id,e.polygonId);let n=t.vertexIndices.map(i=>[...o.topology.vertices[i]]),r={vertices:n},a=null;if(n.length===3){let[i,s,d]=n,l=(0,ke.computeSolidTrianglePlanFromCssPoints)(r,0,{seamBleed:0},{includeColor:!1,primitive:"corner-bevel"},i[0],i[1],i[2],s[0],s[1],s[2],d[0],d[1],d[2]);l||re("degenerate-polygon",e.id,"base triangle has no area"),a=l.basis}return{leaf:e,vertexIndices:t.vertexIndices,polygon:r,basis:a}}function Vo(o,e,t,n){let r=o??{};(!r||typeof r!="object"||Array.isArray(r))&&re("invalid-input",t,"expected an object");let a=new Set(e),i=Object.keys(r).find(s=>!a.has(s));return i&&re("unknown-id",t,i),Object.fromEntries(e.map(s=>{let[d,l]=n.get(s)??[0,1],c=Ft(r[s]??0,`${t}.${s}`);return(c<d||c>l)&&re("out-of-range",`${t}.${s}`,`expected ${d} <= value <= ${l}`),[s,c]}))}function Dt(o){return new Map(o.deformation.kind==="morph-regions"?o.deformation.targets.map(e=>[e.id,e]):[])}function Uo(o){let e=D(o);e.deformation.kind==="joint-skin"&&re("profile-not-executable","$.profile","joint skin requires the skinning runtime");let t=Dt(e),n=[...t.keys()],r=e.controls.map(h=>h.id),a=new Map(n.map(h=>[h,[0,1]])),i=new Map(e.controls.map(h=>[h.id,[h.minimum,h.maximum]])),s=new Map(e.render.leaves.map(h=>[h.polygonId,h])),d=new Map;for(let h of e.topology.polygons)for(let v of h.vertexIndices){let I=d.get(v)??[];I.push(h.id),d.set(v,I)}let l=new Map;for(let h of t.values()){let v=new Set;for(let I of h.deltas)for(let E of d.get(I.vertexIndex)??[]){let x=s.get(E);x&&v.add(x.id)}l.set(h.id,v)}let c=new Map(e.render.leaves.map(h=>[h.id,lo(e,h)])),p=He(Fe(e.topology.vertices)),y=He(Fe(e.topology.normals)),b=Object.fromEntries(n.map(h=>[h,0])),u=p,M=y,$=h=>{(!h||!Number.isSafeInteger(h.tick)||h.tick<0)&&re("invalid-tick","$.tick","expected a non-negative safe integer");let v=Vo(h.morphWeights,n,"$.morphWeights",a),I=Vo(h.controlValues,r,"$.controlValues",i),E={...v};for(let O of e.controls){let T=I[O.id];for(let _ of O.targets)E[_.targetId]=Math.max(0,Math.min(1,(E[_.targetId]??0)+T*_.scale))}let x=n.filter(O=>E[O]!==b[O]),w=u,W=M;if(x.length>0){let O=Fe(p),T=Fe(y);for(let _ of n){let H=E[_];if(H!==0)for(let P of t.get(_).deltas){let C=O[P.vertexIndex];P.position&&(C[0]+=P.position[0]*H,C[1]+=P.position[1]*H,C[2]+=P.position[2]*H);let m=T[P.vertexIndex];P.normal&&(m[0]+=P.normal[0]*H,m[1]+=P.normal[1]*H,m[2]+=P.normal[2]*H)}}T=T.map(Eo),w=He(O),W=He(T)}let V=new Set;for(let O of x)for(let T of l.get(O)??[])V.add(T);let B=e.render.leaves.map(O=>O.id).filter(O=>V.has(O)),ne=B.map(O=>{let T=so(c.get(O),w);return{leafId:O,visible:T.visible,...T.matrix?{matrix:T.matrix}:{}}});return u=w,M=W,b={...E},{tick:h.tick,positions:w,normals:W,morphWeights:Object.freeze({...E}),controlValues:Object.freeze({...I}),dirtyLeafIds:Object.freeze(B),leafUpdates:Object.freeze(ne),runtimePolygonConstructions:0,runtimeTopologyConstructions:0,atlasRedraws:0}};return Object.freeze({model:e,targetIds:Object.freeze(n),controlIds:Object.freeze(r),basePositions:Object.freeze(p),baseNormals:Object.freeze(y),sample:$,reset(){b=Object.fromEntries(n.map(h=>[h,0])),u=p,M=y}})}function Oe(o,e,t){throw new K(o,e,t)}function Ie(o){return Object.freeze([...o])}function co(o,e){return o.every((t,n)=>t===e[n])}function Ne(o){let e=D(o);return Object.freeze({modelMatrix:Ie(e.render.modelMatrix),shapes:Object.freeze(e.render.shapes.map(t=>Object.freeze({shapeId:t.id,matrix:Ie(t.matrix)}))),leaves:Object.freeze(e.render.leaves.map(t=>Object.freeze({leafId:t.id,matrix:Ie(t.matrix),visible:!0,opacity:1,atlasRow:0})))})}function De(o,e){let t=new Map(e.shapes.map(r=>[r.shapeId,r])),n=new Map(e.leaves.map(r=>[r.leafId,r]));for(let r of t.keys())o.shapes.some(a=>a.shapeId===r)||Oe("unknown-shape","$.frame.shapes",r);for(let r of n.keys())o.leaves.some(a=>a.leafId===r)||Oe("unknown-leaf","$.frame.leaves",r);return Object.freeze({modelMatrix:e.modelMatrix===null?o.modelMatrix:Ie(e.modelMatrix),shapes:Object.freeze(o.shapes.map(r=>{let a=t.get(r.shapeId);return a?Object.freeze({shapeId:r.shapeId,matrix:Ie(a.matrix)}):r})),leaves:Object.freeze(o.leaves.map(r=>{let a=n.get(r.leafId);return a?Object.freeze({leafId:r.leafId,matrix:a.matrix===null?r.matrix:Ie(a.matrix),visible:a.visible??r.visible,opacity:a.opacity??r.opacity,atlasRow:a.atlasRow??r.atlasRow}):r}))})}function qe(o,e){(o.shapes.length!==e.shapes.length||o.leaves.length!==e.leaves.length)&&Oe("state-mismatch","$","prepared state topology differs");let t=!co(o.modelMatrix,e.modelMatrix),n=[];for(let a=0;a<e.shapes.length;a+=1){let i=o.shapes[a],s=e.shapes[a];i.shapeId!==s.shapeId&&Oe("state-mismatch","$.shapes","source order differs"),co(i.matrix,s.matrix)||n.push({shapeId:s.shapeId,matrix:s.matrix})}let r=[];for(let a=0;a<e.leaves.length;a+=1){let i=o.leaves[a],s=e.leaves[a];i.leafId!==s.leafId&&Oe("state-mismatch","$.leaves","source order differs");let d={leafId:s.leafId};co(i.matrix,s.matrix)||(d.matrix=s.matrix),i.visible!==s.visible&&(d.visible=s.visible),i.opacity!==s.opacity&&(d.opacity=s.opacity),i.atlasRow!==s.atlasRow&&(d.atlasRow=s.atlasRow),Object.keys(d).length>1&&r.push(d)}return Object.freeze({update:Object.freeze({...t?{modelMatrix:e.modelMatrix}:{},...n.length>0?{shapes:Object.freeze(n)}:{},...r.length>0?{leaves:Object.freeze(r)}:{}}),modelChanged:t,dirtyShapeIds:Object.freeze(n.map(a=>a.shapeId)),dirtyLeafIds:Object.freeze(r.map(a=>a.leafId))})}function Ae(o,e,t){throw new K(o,e,t)}function qt(o,e,t){if(e){let n=t%o;return Object.is(n,-0)?0:n}return Math.min(t,o)}function Jt(o,e){let t=0,n=o.length-1;for(;t<=n;){let r=Math.floor((t+n)/2);o[r]<=e?t=r+1:n=r-1}return Math.max(0,n)}function Bo(o){let e=D(o);(e.profile!=="prepared-playback"||!e.playback)&&Ae("profile-mismatch","$.profile","playback requires the prepared-playback profile");let t=e.playback,n=Ne(e),r=[],a=n,i=new Map(e.render.leaves.map(p=>[p.id,p]));for(let[p,y]of t.frames.entries()){for(let b of y.leaves){if(b.atlasRow===null)continue;let u=i.get(b.leafId);u.atlas||Ae("invalid-atlas-row",`$.playback.frames[${p}]`,`${u.id} has no image rows`),u.atlas.y+b.atlasRow*u.atlas.height+u.atlas.height>u.atlas.pageHeight&&Ae("invalid-atlas-row",`$.playback.frames[${p}]`,`${u.id} row exceeds its page`)}a=De(a,y),r.push(a)}let s=t.frames.map(p=>p.timeMs),d=n,l=null,c=p=>{(!Number.isFinite(p)||p<0)&&Ae("invalid-time","$.timeMs","expected a finite non-negative time");let y=qt(t.durationMs,t.loop,p),b=Jt(s,y),u=r[b],M=qe(d,u),$=Object.freeze({requestedTimeMs:p,sampledTimeMs:y,frameIndex:b,state:u,update:M.update,modelChanged:M.modelChanged,dirtyShapeIds:M.dirtyShapeIds,dirtyLeafIds:M.dirtyLeafIds,domCreations:0,domRemovals:0,topologyConstructions:0,atlasConstructions:0,atlasRedraws:0,schedulerCallbacks:0});return l=$,$};return Object.freeze({model:e,durationMs:t.durationMs,loop:t.loop,frameCount:t.frames.length,sample:c,commit(p){p!==l&&Ae("invalid-sample","$.sample","commit requires the latest unapplied playback sample"),d=p.state,l=null},reset(){d=n,l=null}})}var _o=Object.freeze(["joint-skin","morph-regions","prepared-playback","static-prepared"]);function ae(o,e,t){throw new K(o,e,t)}function Wt(){return[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}function po(o,e){let t=new Array(16).fill(0);for(let n=0;n<4;n+=1)for(let r=0;r<4;r+=1){let a=0;for(let i=0;i<4;i+=1)a+=o[i*4+r]*e[n*4+i];t[n*4+r]=Object.is(a,-0)?0:a}return Object.freeze(t)}function Yt(o,e){if(o===void 0)return[0,0,0,1];(!Array.isArray(o)||o.length!==4||o.some(n=>typeof n!="number"||!Number.isFinite(n)))&&ae("invalid-quaternion",e,"expected four finite components");let t=Math.hypot(...o);return t<=1e-12&&ae("invalid-quaternion",e,"quaternion must be non-zero"),[o[0]/t,o[1]/t,o[2]/t,o[3]/t]}function Fo(o,e,t,n=!1){return o===void 0?e:((!Array.isArray(o)||o.length!==3||o.some(r=>typeof r!="number"||!Number.isFinite(r)))&&ae("invalid-vector",t,"expected three finite components"),n&&o.some(r=>r<=0)&&ae("invalid-scale",t,"scale components must be positive"),[o[0],o[1],o[2]])}function Do(o,e){if(o===void 0)return Wt();(!o||typeof o!="object"||Array.isArray(o))&&ae("invalid-joint-transform",e,"expected an object"),Object.keys(o).some(v=>v!=="translation"&&v!=="rotation"&&v!=="scale")&&ae("invalid-joint-transform",e,"unknown transform field");let n=Fo(o.translation,[0,0,0],`${e}.translation`),r=Fo(o.scale,[1,1,1],`${e}.scale`,!0),[a,i,s,d]=Yt(o.rotation,`${e}.rotation`),l=a*a,c=i*i,p=s*s,y=a*i,b=a*s,u=i*s,M=d*a,$=d*i,h=d*s;return[(1-2*(c+p))*r[0],2*(y+h)*r[0],2*(b-$)*r[0],0,2*(y-h)*r[1],(1-2*(l+p))*r[1],2*(u+M)*r[1],0,2*(b+$)*r[2],2*(u-M)*r[2],(1-2*(l+c))*r[2],0,n[0],n[1],n[2],1]}function Gt(o,e){return[o[0]*e[0]+o[4]*e[1]+o[8]*e[2]+o[12],o[1]*e[0]+o[5]*e[1]+o[9]*e[2]+o[13],o[2]*e[0]+o[6]*e[1]+o[10]*e[2]+o[14]]}function Qt(o,e,t){let[n,r,a]=o,i=o[4],s=o[5],d=o[6],l=o[8],c=o[9],p=o[10],y=n*(s*p-c*d)-i*(r*p-c*a)+l*(r*d-s*a);return Math.abs(y)<=1e-12&&ae("invalid-normal-transform",t,"joint skin matrix is singular"),[((s*p-c*d)*e[0]+(c*a-r*p)*e[1]+(r*d-s*a)*e[2])/y,((l*d-i*p)*e[0]+(n*p-l*a)*e[1]+(i*a-n*d)*e[2])/y,((i*c-l*s)*e[0]+(l*r-n*c)*e[1]+(n*s-i*r)*e[2])/y]}function Kt(o){let e=Math.hypot(...o);return e<=1e-12?[0,0,0]:[o[0]/e,o[1]/e,o[2]/e]}function Re(o){for(let e of o)Object.freeze(e);return Object.freeze(o)}function Xt(o,e){return o.every((t,n)=>Math.abs(t-e[n])<=1e-12)}function Ho(o,e){let t=new Map(o.map(a=>[a.id,a])),n=new Map,r=a=>{let i=n.get(a.id);if(i)return i;let s=po(a.restMatrix,Do(e.get(a.id),`$.jointTransforms.${a.id}`)),d=a.parentId===null?s:po(r(t.get(a.parentId)),s);return n.set(a.id,d),d};for(let a of o)r(a);return n}function No(o,e){return new Map(o.map(t=>[t.id,po(e.get(t.id),t.inverseBindMatrix)]))}function Zt(o,e){let t=o??new Map;(!t||typeof t.entries!="function")&&ae("invalid-joint-transform","$.jointTransforms","expected a map");for(let[n,r]of t)e.has(n)||ae("unknown-joint","$.jointTransforms",n),Do(r,`$.jointTransforms.${n}`);return t}function qo(o){let e=D(o);e.deformation.kind!=="joint-skin"&&ae("profile-mismatch","$.profile","skinning requires the joint-skin profile");let t=e.deformation,n=t.joints.map(w=>w.id),r=new Set(n),a=Ho(t.joints,new Map),i=No(t.joints,a),s=Re(e.topology.vertices.map(w=>[...w])),d=Re(e.topology.normals.map(w=>[...w])),l=new Map(e.render.leaves.map(w=>[w.id,lo(e,w)])),c=new Map;for(let w of e.topology.polygons)for(let W of w.vertexIndices){let V=c.get(W)??[];V.push(w.id),c.set(W,V)}let p=new Map(e.render.leaves.map(w=>[w.polygonId,w.id])),y=new Map(t.vertices.map(w=>[w.vertexIndex,w])),b=w=>{let W=[],V=[];for(let B=0;B<s.length;B+=1){let ne=y.get(B),O=[0,0,0],T=[0,0,0];for(let _ of ne.influences){let H=w.get(_.jointId),P=Gt(H,s[B]),C=Qt(H,d[B],`$.skinMatrices.${_.jointId}`);O[0]+=P[0]*_.weight,O[1]+=P[1]*_.weight,O[2]+=P[2]*_.weight,T[0]+=C[0]*_.weight,T[1]+=C[1]*_.weight,T[2]+=C[2]*_.weight}W.push(O),V.push(Kt(T))}return{positions:W,normals:V}},u=b(i),M=Re(u.positions),$=Re(u.normals),h=new Map(i),v=M,I=$,E=_e(e),x=w=>{(!w||!Number.isSafeInteger(w.tick)||w.tick<0)&&ae("invalid-tick","$.tick","expected a non-negative safe integer");let W=Zt(w.jointTransforms,r),V=Ho(t.joints,W),B=No(t.joints,V),ne=new Set(n.filter(m=>!Xt(B.get(m),h.get(m)))),O=v,T=I;if(ne.size>0){let m=b(B);O=Re(m.positions),T=Re(m.normals)}let _=new Set;if(ne.size>0)for(let m of t.vertices)m.influences.some(S=>ne.has(S.jointId))&&_.add(m.vertexIndex);let H=new Set;for(let m of _)for(let S of c.get(m)??[]){let g=p.get(S);g&&H.add(g)}let P=e.render.leaves.map(m=>m.id).filter(m=>H.has(m)),C=P.map(m=>{let S=so(l.get(m),O);return{leafId:m,visible:S.visible,...S.matrix?{matrix:S.matrix}:{}}});return v=O,I=T,h=new Map(B),{tick:w.tick,positions:O,normals:T,globalJointMatrices:V,skinMatrices:B,dirtyLeafIds:Object.freeze(P),leafUpdates:Object.freeze(C),runtimePolygonConstructions:0,runtimeTopologyConstructions:0,atlasRedraws:0}};return Object.freeze({model:e,jointIds:Object.freeze(n),basePositions:Object.freeze(s),baseNormals:Object.freeze(d),sample:x,sampleClip(w,W,V){let B=E.sample(w,W);return x({tick:V,jointTransforms:B.jointTransforms})},reset(){h=new Map(i),v=M,I=$}})}function ue(o,e,t){throw new K(o,e,t)}function en(o,e,t,n,r){let a=n*n-4*t,i=1e-9*Math.max(1,n*n,t);if(Math.abs(a)<=i){let u=n/2,M=e+u*o,$=Math.exp(-u*r);return[$*(o+M*r),$*(e-u*M*r)]}if(a<0){let u=n/2,M=Math.sqrt(t-u*u),$=M*r,h=Math.cos($),v=Math.sin($),I=Math.exp(-u*r);return[I*(o*h+(e+u*o)/M*v),I*(e*h-(u*e+t*o)/M*v)]}let s=Math.sqrt(a),d=(-n+s)/2,l=(-n-s)/2,c=(e-l*o)/(d-l),p=o-c,y=c*Math.exp(d*r),b=p*Math.exp(l*r);return[y+b,d*y+l*b]}function Jo(o){let e=D(o),t=new Map;for(let n of e.springs)t.set(n.controlId,n);return Object.freeze({model:e,controlIds:Object.freeze(e.controls.map(n=>n.id)),controls:new Map(e.controls.map(n=>[n.id,n])),springs:t})}function Wo(o,e){let t=Object.keys(e??{}).find(r=>!o.controls.has(r));t&&ue("unknown-id","$.values",t);let n=Object.fromEntries(o.controlIds.map(r=>{let a=o.controls.get(r),i=e?.[r]??a.initial;return(!Number.isFinite(i)||i<a.minimum||i>a.maximum)&&ue("out-of-range",`$.values.${r}`,"value is outside control bounds"),[r,i]}));return Object.freeze({tick:-1,values:Object.freeze(n),velocities:Object.freeze(Object.fromEntries(o.controlIds.map(r=>[r,0]))),atRest:o.controlIds.every(r=>n[r]===o.controls.get(r).initial)})}function Yo(o,e,t){(!e||!Number.isSafeInteger(e.tick)||e.tick<-1)&&ue("invalid-state","$.state","spring state is invalid"),(!Number.isFinite(t?.deltaMs)||t.deltaMs<=0||t.deltaMs>1e3)&&ue("invalid-time","$.deltaMs","expected 0 < deltaMs <= 1000");let n=t.heldTarget??null;if(n){let l=o.controls.get(n.controlId);l||ue("unknown-id","$.heldTarget.controlId",n.controlId),(!Number.isFinite(n.value)||n.value<l.minimum||n.value>l.maximum)&&ue("out-of-range","$.heldTarget.value","value is outside control bounds")}let r=new Set(t.frozenControlIds??[]);for(let l of r)o.controls.has(l)||ue("unknown-id","$.frozenControlIds",l);let a=t.deltaMs/1e3,i={},s={},d=!0;for(let l of o.controlIds){let c=o.controls.get(l),p=e.values[l]??c.initial,y=e.velocities[l]??0;if(n?.controlId===l)i[l]=n.value,s[l]=0;else if(r.has(l)||!o.springs.has(l))i[l]=p,s[l]=0;else{let b=o.springs.get(l),u=p-c.initial,[M,$]=en(u,y,b.stiffness,b.damping,a),h=$,v=c.initial+M,I=Math.max(c.minimum,Math.min(c.maximum,v));I!==v&&(h=0),v=I,Math.abs(v-c.initial)<1e-6&&Math.abs(h)<1e-6&&(v=c.initial,h=0),i[l]=Object.is(v,-0)?0:v,s[l]=Object.is(h,-0)?0:h}(i[l]!==c.initial||s[l]!==0)&&(d=!1)}return Object.freeze({tick:e.tick+1,values:Object.freeze(i),velocities:Object.freeze(s),atRest:d})}0&&(module.exports={POLY_MORPH_CATALOG_SCHEMA,POLY_MORPH_EXECUTABLE_PROFILES,POLY_MORPH_MODEL_SCHEMA,POLY_MORPH_PACKAGE_SCHEMA,PolyMorphContractError,PolyMorphPackageError,PolyMorphRenderError,PolyMorphRuntimeError,applyPolyMorphPlaybackFrame,assertPolyMorphPackageModelBinding,buildPolyMorphCatalog,buildPolyMorphPackage,createPolyMorphAnimationRuntime,createPolyMorphControlRuntime,createPolyMorphControlState,createPolyMorphDeformationRuntime,createPolyMorphPlaybackRuntime,createPolyMorphPreparedState,createPolyMorphSkinningRuntime,createPolyMorphSpringRuntime,createPolyMorphSpringState,decodePolyMorphJson,diffPolyMorphPreparedStates,encodePolyMorphCanonicalJson,hashPolyMorphBytes,isPolyMorphId,isPolyMorphResourcePath,loadPolyMorphCatalog,loadPolyMorphPackage,mountPolyMorphModel,pickPolyMorphControl,stepPolyMorphControls,stepPolyMorphSprings,stringifyPolyMorphCanonicalJson,validatePolyMorphCatalog,validatePolyMorphModel,validatePolyMorphPackageManifest});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { P as PolyMorphCatalog, a as PolyMorphLoadedPackage, b as PolyMorphMat4, c as PolyMorphRenderLeaf, d as PolyMorphLoadedResource, e as PolyMorphModel, f as PolyMorphVec3, g as PolyMorphQuat, h as PolyMorphControl, i as PolyMorphPlaybackFrame, j as PolyMorphSpring } from './validation-CY2nydbS.cjs';
|
|
2
|
+
export { k as POLY_MORPH_CATALOG_SCHEMA, l as POLY_MORPH_MODEL_SCHEMA, m as POLY_MORPH_PACKAGE_SCHEMA, n as PolyMorphAnimationChannel, o as PolyMorphAnimationClip, p as PolyMorphAnimationTarget, q as PolyMorphAtlasSlice, r as PolyMorphBudgets, s as PolyMorphBuiltCatalog, t as PolyMorphBuiltPackage, u as PolyMorphCapability, v as PolyMorphCatalogRow, w as PolyMorphColor, x as PolyMorphContractError, y as PolyMorphControlTarget, z as PolyMorphDeformation, A as PolyMorphJoint, B as PolyMorphJointDeformation, C as PolyMorphJointInfluence, D as PolyMorphMaterial, E as PolyMorphModelIdentity, F as PolyMorphNoDeformation, G as PolyMorphPackageError, H as PolyMorphPackageManifest, I as PolyMorphPlayback, J as PolyMorphPlaybackLeafUpdate, K as PolyMorphPlaybackShapeUpdate, L as PolyMorphPolygon, M as PolyMorphProfile, N as PolyMorphProvenance, O as PolyMorphProvenanceSource, Q as PolyMorphRegionDeformation, R as PolyMorphRenderFallback, S as PolyMorphRenderPlan, T as PolyMorphRenderShape, U as PolyMorphRenderStrategy, V as PolyMorphResourceDescriptor, W as PolyMorphResourceInput, X as PolyMorphResourceRole, Y as PolyMorphSkinVertex, Z as PolyMorphSparseDelta, _ as PolyMorphTarget, $ as PolyMorphTopology, a0 as assertPolyMorphPackageModelBinding, a1 as buildPolyMorphCatalog, a2 as buildPolyMorphPackage, a3 as decodePolyMorphJson, a4 as encodePolyMorphCanonicalJson, a5 as hashPolyMorphBytes, a6 as isPolyMorphId, a7 as isPolyMorphResourcePath, a8 as stringifyPolyMorphCanonicalJson, a9 as validatePolyMorphCatalog, aa as validatePolyMorphModel, ab as validatePolyMorphPackageManifest } from './validation-CY2nydbS.cjs';
|
|
3
|
+
import { PolyOrthographicCameraHandle, PolyPerspectiveCameraHandle } from '@layoutit/polycss';
|
|
4
|
+
|
|
5
|
+
interface PolyMorphLoadOptions {
|
|
6
|
+
readonly fetchImpl?: typeof fetch;
|
|
7
|
+
readonly modelId?: string;
|
|
8
|
+
readonly maxResourceBytes?: number;
|
|
9
|
+
readonly maxResources?: number;
|
|
10
|
+
readonly maxTotalBytes?: number;
|
|
11
|
+
readonly requestTimeoutMs?: number;
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
declare function loadPolyMorphCatalog(baseUrl: string, options?: Omit<PolyMorphLoadOptions, "maxResources" | "maxTotalBytes" | "modelId">): Promise<{
|
|
15
|
+
readonly catalog: PolyMorphCatalog;
|
|
16
|
+
readonly bytes: Uint8Array;
|
|
17
|
+
readonly sha256: string;
|
|
18
|
+
}>;
|
|
19
|
+
declare function loadPolyMorphPackage(baseUrl: string, options?: PolyMorphLoadOptions): Promise<PolyMorphLoadedPackage>;
|
|
20
|
+
|
|
21
|
+
type PolyMorphCamera = PolyOrthographicCameraHandle | PolyPerspectiveCameraHandle;
|
|
22
|
+
interface PolyMorphMountOptions {
|
|
23
|
+
readonly camera?: PolyMorphCamera;
|
|
24
|
+
readonly resources?: ReadonlyMap<string, PolyMorphLoadedResource>;
|
|
25
|
+
}
|
|
26
|
+
interface PolyMorphShapeUpdate {
|
|
27
|
+
readonly shapeId: string;
|
|
28
|
+
readonly matrix: PolyMorphMat4;
|
|
29
|
+
}
|
|
30
|
+
interface PolyMorphLeafUpdate {
|
|
31
|
+
readonly leafId: string;
|
|
32
|
+
readonly matrix?: PolyMorphMat4;
|
|
33
|
+
readonly visible?: boolean;
|
|
34
|
+
readonly opacity?: number;
|
|
35
|
+
readonly atlasRow?: number;
|
|
36
|
+
}
|
|
37
|
+
interface PolyMorphRetainedUpdate {
|
|
38
|
+
readonly modelMatrix?: PolyMorphMat4;
|
|
39
|
+
readonly shapes?: readonly PolyMorphShapeUpdate[];
|
|
40
|
+
readonly leaves?: readonly PolyMorphLeafUpdate[];
|
|
41
|
+
}
|
|
42
|
+
interface PolyMorphApplyResult {
|
|
43
|
+
readonly modelTransformWrites: number;
|
|
44
|
+
readonly shapeTransformWrites: number;
|
|
45
|
+
readonly leafTransformWrites: number;
|
|
46
|
+
readonly visibilityWrites: number;
|
|
47
|
+
readonly opacityWrites: number;
|
|
48
|
+
readonly atlasRowWrites: number;
|
|
49
|
+
readonly dirtyLeavesVisited: number;
|
|
50
|
+
readonly domCreations: 0;
|
|
51
|
+
readonly domRemovals: 0;
|
|
52
|
+
readonly topologyConstructions: 0;
|
|
53
|
+
readonly atlasRedraws: 0;
|
|
54
|
+
readonly schedulerCallbacks: 0;
|
|
55
|
+
}
|
|
56
|
+
interface PolyMorphRenderStats {
|
|
57
|
+
readonly mountCount: 1;
|
|
58
|
+
readonly shapeRoots: number;
|
|
59
|
+
readonly leafCount: number;
|
|
60
|
+
readonly topologyConstructions: 1;
|
|
61
|
+
readonly atlasConstructions: 0;
|
|
62
|
+
readonly schedulerCount: 0;
|
|
63
|
+
readonly applyCount: number;
|
|
64
|
+
readonly totalTransformWrites: number;
|
|
65
|
+
readonly totalVisibilityWrites: number;
|
|
66
|
+
readonly totalOpacityWrites: number;
|
|
67
|
+
readonly totalAtlasRowWrites: number;
|
|
68
|
+
}
|
|
69
|
+
interface PolyMorphLeafHandle {
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly plan: PolyMorphRenderLeaf;
|
|
72
|
+
readonly element: HTMLElement;
|
|
73
|
+
}
|
|
74
|
+
interface PolyMorphMountedModel {
|
|
75
|
+
readonly model: PolyMorphModel;
|
|
76
|
+
readonly camera: PolyMorphCamera;
|
|
77
|
+
readonly cameraElement: HTMLElement;
|
|
78
|
+
readonly sceneElement: HTMLElement;
|
|
79
|
+
readonly modelElement: HTMLElement;
|
|
80
|
+
readonly shapeElements: ReadonlyMap<string, HTMLElement>;
|
|
81
|
+
readonly leafHandles: ReadonlyMap<string, PolyMorphLeafHandle>;
|
|
82
|
+
readonly stats: PolyMorphRenderStats;
|
|
83
|
+
readonly destroyed: boolean;
|
|
84
|
+
apply(update: PolyMorphRetainedUpdate): PolyMorphApplyResult;
|
|
85
|
+
updateCamera(): boolean;
|
|
86
|
+
assertStableDomIdentity(): void;
|
|
87
|
+
destroy(): void;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
declare function mountPolyMorphModel(host: HTMLElement, modelInput: unknown, options?: PolyMorphMountOptions): PolyMorphMountedModel;
|
|
91
|
+
|
|
92
|
+
declare class PolyMorphRenderError extends Error {
|
|
93
|
+
readonly code: string;
|
|
94
|
+
readonly path: string;
|
|
95
|
+
constructor(code: string, path: string, message: string);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface PolyMorphJointAnimationSample {
|
|
99
|
+
readonly translation?: PolyMorphVec3;
|
|
100
|
+
readonly rotation?: PolyMorphQuat;
|
|
101
|
+
readonly scale?: PolyMorphVec3;
|
|
102
|
+
}
|
|
103
|
+
interface PolyMorphAnimationSample {
|
|
104
|
+
readonly clipId: string;
|
|
105
|
+
readonly requestedTimeMs: number;
|
|
106
|
+
readonly sampledTimeMs: number;
|
|
107
|
+
readonly morphWeights: Readonly<Record<string, number>>;
|
|
108
|
+
readonly controlValues: Readonly<Record<string, number>>;
|
|
109
|
+
readonly jointTransforms: ReadonlyMap<string, PolyMorphJointAnimationSample>;
|
|
110
|
+
readonly shapeMatrices: ReadonlyMap<string, PolyMorphMat4>;
|
|
111
|
+
}
|
|
112
|
+
interface PolyMorphAnimationRuntime {
|
|
113
|
+
readonly model: PolyMorphModel;
|
|
114
|
+
readonly clipIds: readonly string[];
|
|
115
|
+
sample(clipId: string, timeMs: number): PolyMorphAnimationSample;
|
|
116
|
+
}
|
|
117
|
+
declare function createPolyMorphAnimationRuntime(modelInput: unknown): PolyMorphAnimationRuntime;
|
|
118
|
+
|
|
119
|
+
interface PolyMorphControlRuntime {
|
|
120
|
+
readonly model: PolyMorphModel;
|
|
121
|
+
readonly controlIds: readonly string[];
|
|
122
|
+
readonly controls: ReadonlyMap<string, PolyMorphControl>;
|
|
123
|
+
}
|
|
124
|
+
interface PolyMorphControlState {
|
|
125
|
+
readonly tick: number;
|
|
126
|
+
readonly active: boolean;
|
|
127
|
+
readonly heldControlId: string | null;
|
|
128
|
+
readonly holdStartPoint: PolyMorphVec3 | null;
|
|
129
|
+
readonly holdStartValue: number;
|
|
130
|
+
readonly values: Readonly<Record<string, number>>;
|
|
131
|
+
readonly frozenControlIds: readonly string[];
|
|
132
|
+
}
|
|
133
|
+
interface PolyMorphControlInput {
|
|
134
|
+
readonly point: PolyMorphVec3 | null;
|
|
135
|
+
readonly active: boolean;
|
|
136
|
+
readonly freezeOnRelease?: boolean;
|
|
137
|
+
}
|
|
138
|
+
interface PolyMorphControlStep {
|
|
139
|
+
readonly state: PolyMorphControlState;
|
|
140
|
+
readonly pickedControlId: string | null;
|
|
141
|
+
readonly releasedControlId: string | null;
|
|
142
|
+
readonly heldTarget: Readonly<{
|
|
143
|
+
controlId: string;
|
|
144
|
+
value: number;
|
|
145
|
+
}> | null;
|
|
146
|
+
}
|
|
147
|
+
declare function createPolyMorphControlRuntime(modelInput: unknown): PolyMorphControlRuntime;
|
|
148
|
+
declare function createPolyMorphControlState(runtime: PolyMorphControlRuntime): PolyMorphControlState;
|
|
149
|
+
declare function pickPolyMorphControl(runtime: PolyMorphControlRuntime, inputPoint: PolyMorphVec3): string | null;
|
|
150
|
+
declare function stepPolyMorphControls(runtime: PolyMorphControlRuntime, state: PolyMorphControlState, input: PolyMorphControlInput): PolyMorphControlStep;
|
|
151
|
+
|
|
152
|
+
interface PolyMorphDeformationInput {
|
|
153
|
+
readonly tick: number;
|
|
154
|
+
readonly morphWeights?: Readonly<Record<string, number>>;
|
|
155
|
+
readonly controlValues?: Readonly<Record<string, number>>;
|
|
156
|
+
}
|
|
157
|
+
interface PolyMorphDeformationFrame {
|
|
158
|
+
readonly tick: number;
|
|
159
|
+
readonly positions: readonly PolyMorphVec3[];
|
|
160
|
+
readonly normals: readonly PolyMorphVec3[];
|
|
161
|
+
readonly morphWeights: Readonly<Record<string, number>>;
|
|
162
|
+
readonly controlValues: Readonly<Record<string, number>>;
|
|
163
|
+
readonly dirtyLeafIds: readonly string[];
|
|
164
|
+
readonly leafUpdates: readonly PolyMorphLeafUpdate[];
|
|
165
|
+
readonly runtimePolygonConstructions: 0;
|
|
166
|
+
readonly runtimeTopologyConstructions: 0;
|
|
167
|
+
readonly atlasRedraws: 0;
|
|
168
|
+
}
|
|
169
|
+
interface PolyMorphDeformationRuntime {
|
|
170
|
+
readonly model: PolyMorphModel;
|
|
171
|
+
readonly targetIds: readonly string[];
|
|
172
|
+
readonly controlIds: readonly string[];
|
|
173
|
+
readonly basePositions: readonly PolyMorphVec3[];
|
|
174
|
+
readonly baseNormals: readonly PolyMorphVec3[];
|
|
175
|
+
sample(input: PolyMorphDeformationInput): PolyMorphDeformationFrame;
|
|
176
|
+
reset(): void;
|
|
177
|
+
}
|
|
178
|
+
interface PolyMorphPreparedLeafMatrix {
|
|
179
|
+
readonly leafId: string;
|
|
180
|
+
readonly matrix: PolyMorphMat4 | null;
|
|
181
|
+
readonly visible: boolean;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
declare function createPolyMorphDeformationRuntime(modelInput: unknown): PolyMorphDeformationRuntime;
|
|
185
|
+
|
|
186
|
+
interface PolyMorphPreparedShapeState {
|
|
187
|
+
readonly shapeId: string;
|
|
188
|
+
readonly matrix: PolyMorphMat4;
|
|
189
|
+
}
|
|
190
|
+
interface PolyMorphPreparedLeafState {
|
|
191
|
+
readonly leafId: string;
|
|
192
|
+
readonly matrix: PolyMorphMat4;
|
|
193
|
+
readonly visible: boolean;
|
|
194
|
+
readonly opacity: number;
|
|
195
|
+
readonly atlasRow: number;
|
|
196
|
+
}
|
|
197
|
+
interface PolyMorphPreparedState {
|
|
198
|
+
readonly modelMatrix: PolyMorphMat4;
|
|
199
|
+
readonly shapes: readonly PolyMorphPreparedShapeState[];
|
|
200
|
+
readonly leaves: readonly PolyMorphPreparedLeafState[];
|
|
201
|
+
}
|
|
202
|
+
interface PolyMorphPreparedStateDiff {
|
|
203
|
+
readonly update: PolyMorphRetainedUpdate;
|
|
204
|
+
readonly modelChanged: boolean;
|
|
205
|
+
readonly dirtyShapeIds: readonly string[];
|
|
206
|
+
readonly dirtyLeafIds: readonly string[];
|
|
207
|
+
}
|
|
208
|
+
declare function createPolyMorphPreparedState(modelInput: unknown): PolyMorphPreparedState;
|
|
209
|
+
declare function applyPolyMorphPlaybackFrame(state: PolyMorphPreparedState, frame: PolyMorphPlaybackFrame): PolyMorphPreparedState;
|
|
210
|
+
declare function diffPolyMorphPreparedStates(previous: PolyMorphPreparedState, next: PolyMorphPreparedState): PolyMorphPreparedStateDiff;
|
|
211
|
+
|
|
212
|
+
interface PolyMorphPlaybackSample {
|
|
213
|
+
readonly requestedTimeMs: number;
|
|
214
|
+
readonly sampledTimeMs: number;
|
|
215
|
+
readonly frameIndex: number;
|
|
216
|
+
readonly state: PolyMorphPreparedState;
|
|
217
|
+
readonly update: PolyMorphRetainedUpdate;
|
|
218
|
+
readonly modelChanged: boolean;
|
|
219
|
+
readonly dirtyShapeIds: readonly string[];
|
|
220
|
+
readonly dirtyLeafIds: readonly string[];
|
|
221
|
+
readonly domCreations: 0;
|
|
222
|
+
readonly domRemovals: 0;
|
|
223
|
+
readonly topologyConstructions: 0;
|
|
224
|
+
readonly atlasConstructions: 0;
|
|
225
|
+
readonly atlasRedraws: 0;
|
|
226
|
+
readonly schedulerCallbacks: 0;
|
|
227
|
+
}
|
|
228
|
+
interface PolyMorphPlaybackRuntime {
|
|
229
|
+
readonly model: PolyMorphModel;
|
|
230
|
+
readonly durationMs: number;
|
|
231
|
+
readonly loop: boolean;
|
|
232
|
+
readonly frameCount: number;
|
|
233
|
+
sample(timeMs: number): PolyMorphPlaybackSample;
|
|
234
|
+
commit(sample: PolyMorphPlaybackSample): void;
|
|
235
|
+
reset(): void;
|
|
236
|
+
}
|
|
237
|
+
declare function createPolyMorphPlaybackRuntime(modelInput: unknown): PolyMorphPlaybackRuntime;
|
|
238
|
+
|
|
239
|
+
declare const POLY_MORPH_EXECUTABLE_PROFILES: readonly ["joint-skin", "morph-regions", "prepared-playback", "static-prepared"];
|
|
240
|
+
|
|
241
|
+
declare class PolyMorphRuntimeError extends Error {
|
|
242
|
+
readonly code: string;
|
|
243
|
+
readonly path: string;
|
|
244
|
+
constructor(code: string, path: string, message: string);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
interface PolyMorphSkinningInput {
|
|
248
|
+
readonly tick: number;
|
|
249
|
+
readonly jointTransforms?: ReadonlyMap<string, PolyMorphJointAnimationSample>;
|
|
250
|
+
}
|
|
251
|
+
interface PolyMorphSkinningFrame {
|
|
252
|
+
readonly tick: number;
|
|
253
|
+
readonly positions: readonly PolyMorphVec3[];
|
|
254
|
+
readonly normals: readonly PolyMorphVec3[];
|
|
255
|
+
readonly globalJointMatrices: ReadonlyMap<string, PolyMorphMat4>;
|
|
256
|
+
readonly skinMatrices: ReadonlyMap<string, PolyMorphMat4>;
|
|
257
|
+
readonly dirtyLeafIds: readonly string[];
|
|
258
|
+
readonly leafUpdates: readonly PolyMorphLeafUpdate[];
|
|
259
|
+
readonly runtimePolygonConstructions: 0;
|
|
260
|
+
readonly runtimeTopologyConstructions: 0;
|
|
261
|
+
readonly atlasRedraws: 0;
|
|
262
|
+
}
|
|
263
|
+
interface PolyMorphSkinningRuntime {
|
|
264
|
+
readonly model: PolyMorphModel;
|
|
265
|
+
readonly jointIds: readonly string[];
|
|
266
|
+
readonly basePositions: readonly PolyMorphVec3[];
|
|
267
|
+
readonly baseNormals: readonly PolyMorphVec3[];
|
|
268
|
+
sample(input: PolyMorphSkinningInput): PolyMorphSkinningFrame;
|
|
269
|
+
sampleClip(clipId: string, timeMs: number, tick: number): PolyMorphSkinningFrame;
|
|
270
|
+
reset(): void;
|
|
271
|
+
}
|
|
272
|
+
declare function createPolyMorphSkinningRuntime(modelInput: unknown): PolyMorphSkinningRuntime;
|
|
273
|
+
|
|
274
|
+
interface PolyMorphSpringRuntime {
|
|
275
|
+
readonly model: PolyMorphModel;
|
|
276
|
+
readonly controlIds: readonly string[];
|
|
277
|
+
readonly controls: ReadonlyMap<string, PolyMorphControl>;
|
|
278
|
+
readonly springs: ReadonlyMap<string, PolyMorphSpring>;
|
|
279
|
+
}
|
|
280
|
+
interface PolyMorphSpringState {
|
|
281
|
+
readonly tick: number;
|
|
282
|
+
readonly values: Readonly<Record<string, number>>;
|
|
283
|
+
readonly velocities: Readonly<Record<string, number>>;
|
|
284
|
+
readonly atRest: boolean;
|
|
285
|
+
}
|
|
286
|
+
interface PolyMorphSpringStepOptions {
|
|
287
|
+
readonly deltaMs: number;
|
|
288
|
+
readonly heldTarget?: Readonly<{
|
|
289
|
+
controlId: string;
|
|
290
|
+
value: number;
|
|
291
|
+
}> | null;
|
|
292
|
+
readonly frozenControlIds?: readonly string[];
|
|
293
|
+
}
|
|
294
|
+
declare function createPolyMorphSpringRuntime(modelInput: unknown): PolyMorphSpringRuntime;
|
|
295
|
+
declare function createPolyMorphSpringState(runtime: PolyMorphSpringRuntime, values?: Readonly<Record<string, number>>): PolyMorphSpringState;
|
|
296
|
+
declare function stepPolyMorphSprings(runtime: PolyMorphSpringRuntime, state: PolyMorphSpringState, options: PolyMorphSpringStepOptions): PolyMorphSpringState;
|
|
297
|
+
|
|
298
|
+
export { POLY_MORPH_EXECUTABLE_PROFILES, type PolyMorphAnimationRuntime, type PolyMorphAnimationSample, type PolyMorphApplyResult, type PolyMorphCamera, PolyMorphCatalog, PolyMorphControl, type PolyMorphControlInput, type PolyMorphControlRuntime, type PolyMorphControlState, type PolyMorphControlStep, type PolyMorphDeformationFrame, type PolyMorphDeformationInput, type PolyMorphDeformationRuntime, type PolyMorphJointAnimationSample, type PolyMorphLeafHandle, type PolyMorphLeafUpdate, type PolyMorphLoadOptions, PolyMorphLoadedPackage, PolyMorphLoadedResource, PolyMorphMat4, PolyMorphModel, type PolyMorphMountOptions, type PolyMorphMountedModel, PolyMorphPlaybackFrame, type PolyMorphPlaybackRuntime, type PolyMorphPlaybackSample, type PolyMorphPreparedLeafMatrix, type PolyMorphPreparedLeafState, type PolyMorphPreparedShapeState, type PolyMorphPreparedState, type PolyMorphPreparedStateDiff, PolyMorphQuat, PolyMorphRenderError, PolyMorphRenderLeaf, type PolyMorphRenderStats, type PolyMorphRetainedUpdate, PolyMorphRuntimeError, type PolyMorphShapeUpdate, type PolyMorphSkinningFrame, type PolyMorphSkinningInput, type PolyMorphSkinningRuntime, PolyMorphSpring, type PolyMorphSpringRuntime, type PolyMorphSpringState, type PolyMorphSpringStepOptions, PolyMorphVec3, applyPolyMorphPlaybackFrame, createPolyMorphAnimationRuntime, createPolyMorphControlRuntime, createPolyMorphControlState, createPolyMorphDeformationRuntime, createPolyMorphPlaybackRuntime, createPolyMorphPreparedState, createPolyMorphSkinningRuntime, createPolyMorphSpringRuntime, createPolyMorphSpringState, diffPolyMorphPreparedStates, loadPolyMorphCatalog, loadPolyMorphPackage, mountPolyMorphModel, pickPolyMorphControl, stepPolyMorphControls, stepPolyMorphSprings };
|