@limrun/ui 0.16.0 → 0.17.0-rc.2

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 (73) hide show
  1. package/README.md +64 -0
  2. package/dist/GLTFLoader-Cami_vza.mjs +1679 -0
  3. package/dist/GLTFLoader-DeCLxW_q.js +1 -0
  4. package/dist/components/duo-button-hinge.d.ts +16 -0
  5. package/dist/components/duo-controls.d.ts +21 -0
  6. package/dist/components/duo-flat-frame.d.ts +7 -0
  7. package/dist/components/duo-flat-geometry.d.ts +52 -0
  8. package/dist/components/duo-fold-motion.d.ts +27 -0
  9. package/dist/components/duo-fold-renderer.d.ts +19 -0
  10. package/dist/components/duo-fold-timing.d.ts +1 -0
  11. package/dist/components/duo-frame.d.ts +16 -0
  12. package/dist/components/duo-hardware.d.ts +20 -0
  13. package/dist/components/duo-loading.d.ts +8 -0
  14. package/dist/components/duo-model.d.ts +19 -0
  15. package/dist/components/duo-screen-handoff.d.ts +4 -0
  16. package/dist/components/duo-view.d.ts +9 -0
  17. package/dist/components/remote-control.d.ts +5 -1
  18. package/dist/core/duo.d.ts +63 -0
  19. package/dist/duo-fold-renderer-BXejNHcY.mjs +257 -0
  20. package/dist/duo-fold-renderer-DdltAnF7.js +53 -0
  21. package/dist/duo-frame-Cmw4p2uN.mjs +26767 -0
  22. package/dist/duo-frame-iMtrvx_a.js +4059 -0
  23. package/dist/duo-view-BAh-w2Kz.js +1 -0
  24. package/dist/duo-view-D9Ae00rj.mjs +512 -0
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.css +1 -1
  27. package/dist/index.js +2 -2
  28. package/dist/lite.cjs +1 -1
  29. package/dist/lite.js +1 -1
  30. package/dist/remote-control-B2jZpf3c.js +1 -0
  31. package/dist/remote-control-DiddxS8l.mjs +2883 -0
  32. package/package.json +8 -2
  33. package/dist/demo.d.ts +0 -1
  34. package/dist/remote-control-BRgbD7yo.mjs +0 -2516
  35. package/dist/remote-control-VISrP1zI.js +0 -1
  36. package/index.html +0 -199
  37. package/src/assets/Apple_logo_white.svg +0 -4
  38. package/src/assets/android_boot.gif +0 -0
  39. package/src/assets/android_boot.webp +0 -0
  40. package/src/assets/iphone16pro_black.webp +0 -0
  41. package/src/assets/iphone16pro_black_bg.webp +0 -0
  42. package/src/assets/iphone16pro_black_landscape.webp +0 -0
  43. package/src/assets/iphone16pro_black_landscape_bg.webp +0 -0
  44. package/src/assets/pixel9_black.webp +0 -0
  45. package/src/assets/pixel9_black_landscape.webp +0 -0
  46. package/src/assets/pixel_tablet_landscape.webp +0 -0
  47. package/src/assets/pixel_tablet_portrait.webp +0 -0
  48. package/src/components/device-install/index.ts +0 -1
  49. package/src/components/inspect-overlay.css +0 -223
  50. package/src/components/inspect-overlay.tsx +0 -437
  51. package/src/components/remote-control-framed.tsx +0 -14
  52. package/src/components/remote-control.css +0 -131
  53. package/src/components/remote-control.test.ts +0 -34
  54. package/src/components/remote-control.tsx +0 -3853
  55. package/src/core/ax-fetcher.test.ts +0 -418
  56. package/src/core/ax-fetcher.ts +0 -387
  57. package/src/core/ax-tree.test.ts +0 -491
  58. package/src/core/ax-tree.ts +0 -416
  59. package/src/core/camera.test.ts +0 -155
  60. package/src/core/camera.ts +0 -133
  61. package/src/core/constants.ts +0 -344
  62. package/src/core/webrtc-messages.ts +0 -148
  63. package/src/demo.tsx +0 -269
  64. package/src/frame-assets.ts +0 -22
  65. package/src/hooks/index.ts +0 -1
  66. package/src/index.ts +0 -29
  67. package/src/lite.test.ts +0 -30
  68. package/src/lite.ts +0 -30
  69. package/src/vite-env.d.ts +0 -1
  70. package/tsconfig.json +0 -26
  71. package/tsconfig.node.json +0 -26
  72. package/vite.config.ts +0 -35
  73. package/vitest.config.ts +0 -24
@@ -0,0 +1,257 @@
1
+ const C = 1200;
2
+ function U(p, l, T, e, t = 0) {
3
+ const o = [];
4
+ for (const [u, r, c, h] of [
5
+ [p / 2 - e, l / 2 - e, e, 0],
6
+ [-p / 2 + T, l / 2 - T, T, Math.PI / 2],
7
+ [-p / 2 + T, -l / 2 + T, T, Math.PI],
8
+ [p / 2 - e, -l / 2 + e, e, Math.PI * 1.5]
9
+ ])
10
+ for (let n = 0; n <= 8; n++) {
11
+ const i = h + n * Math.PI / 16, a = Math.cos(i), s = Math.sin(i);
12
+ o.push({ x: u + (c - t) * a, y: r + (c - t) * s, nx: a, ny: s });
13
+ }
14
+ return o;
15
+ }
16
+ function B() {
17
+ const p = [], l = (t, o, u) => p.push({ side: t, kind: o, vertices: new Float32Array(u) }), T = (t, o, u, r, c, h, n, i, a, s) => {
18
+ const x = [], d = (m, g, v, _) => x.push(m.x + u, m.y + r, g, m.nx * _, m.ny * _, v, 0, 0), E = Math.min(0.32, i / 3, a / 2, s / 2), I = [
19
+ [E, n, 0.707, 0.707],
20
+ [0, n - E, 0, 1],
21
+ [0, n - i + E, 0, 1],
22
+ [E, n - i, -0.707, 0.707]
23
+ ];
24
+ for (let m = 0; m < I.length - 1; m++) {
25
+ const g = I[m], v = I[m + 1], _ = U(c, h, a, s, g[0]), H = U(c, h, a, s, v[0]);
26
+ for (let F = 0; F < _.length; F++) {
27
+ const L = (F + 1) % _.length;
28
+ for (const [D, M] of [
29
+ [_[F], g],
30
+ [H[F], v],
31
+ [_[L], g],
32
+ [_[L], g],
33
+ [H[F], v],
34
+ [H[L], v]
35
+ ])
36
+ d(D, M[1], M[2], M[3]);
37
+ }
38
+ }
39
+ const A = U(c, h, a, s, E);
40
+ for (const [m, g] of [
41
+ [n, 1],
42
+ [n - i, -1]
43
+ ])
44
+ for (let v = 0; v < A.length; v++)
45
+ x.push(u, r, m, 0, 0, g, 0, 0), d(A[v], m, g, 0), d(A[(v + 1) % A.length], m, g, 0);
46
+ l(t, o, x);
47
+ }, e = (t, o, u, r, c, h, n, i) => {
48
+ const a = [], s = U(r, c, n, i), x = (d, E) => {
49
+ const I = d + u;
50
+ let A = 0, m = 0;
51
+ o === "inner" && (A = 0.5 - E / 110.8, m = 0.5 + I / 157.5), o === "outer" && (A = 0.5 - d / r, m = 0.5 + E / c), a.push(I, E, h, 0, 0, o === "outer" || o === "back" ? -1 : 1, A, m);
52
+ };
53
+ for (let d = 0; d < s.length; d++)
54
+ x(0, 0), x(s[d].x, s[d].y), x(s[(d + 1) % s.length].x, s[(d + 1) % s.length].y);
55
+ l(t, o, a);
56
+ };
57
+ for (const t of [-1, 1]) {
58
+ const o = t === -1 ? 8.4 : 1.25, u = t === 1 ? 8.4 : 1.25;
59
+ T(t, "metal", t * 82.3 / 2, 0, 82.3, 117.8, 0, 5.2, o, u), e(
60
+ t,
61
+ "seal",
62
+ t * 82.3 / 2,
63
+ 82.3 - 2.24,
64
+ 117.8 - 2.24,
65
+ 0.12,
66
+ t === -1 ? 7.15 : 0.2,
67
+ t === 1 ? 7.15 : 0.2
68
+ ), e(
69
+ t,
70
+ "inner",
71
+ t * (157.5 / 4 + 0.55),
72
+ 157.5 / 2 - 1.1,
73
+ 110.8,
74
+ 0.24,
75
+ t === -1 ? 5.3 : 0,
76
+ t === 1 ? 5.3 : 0
77
+ );
78
+ }
79
+ for (const [t, o, u] of [
80
+ ["metal", 117.8, -0.12],
81
+ ["seal", 117.8 - 2.24, 0.12],
82
+ ["inner", 110.8, 0.24]
83
+ ]) {
84
+ const r = [], c = (h, n) => r.push(h, n, u, 0, 0, 1, 0.5 - n / 110.8, 0.5 + h / 157.5);
85
+ for (let h = 0; h < 6; h++) {
86
+ const n = -1.1 + h * 2.2 / 6, i = n + 2.2 / 6;
87
+ for (const [a, s] of [
88
+ [n, -o / 2],
89
+ [i, -o / 2],
90
+ [n, o / 2],
91
+ [n, o / 2],
92
+ [i, -o / 2],
93
+ [i, o / 2]
94
+ ])
95
+ c(a, s);
96
+ }
97
+ l(0, t, r);
98
+ }
99
+ e(-1, "seal", -82.3 / 2, 82.3 - 2.24, 117.8 - 2.24, -5.2 - 0.12, 7.15, 0.65), e(-1, "outer", -82.3 / 2, 77.1, 112.2, -5.2 - 0.24, 6.6, 0.8), e(1, "back", 82.3 / 2, 82.3 - 1, 117.8 - 1, -5.2 - 0.12, 0.8, 8);
100
+ for (const t of [82.3 - 37, 82.3 - 25])
101
+ T(1, "metal", t, 117.8 / 2 + 0.4, 9.5, 0.8, -1.4, 2, 0.35, 0.35);
102
+ return T(1, "metal", 82.3 + 0.4, 21, 0.8, 13, -1.4, 2, 0.35, 0.35), p;
103
+ }
104
+ function N(p) {
105
+ const l = [
106
+ [0, 180, 0, -0.5],
107
+ [0.12, 176, -4, -0.46],
108
+ [0.24, 150, -8, -0.4],
109
+ [0.35, 90, -12, -0.32],
110
+ [0.48, 48, -22, -0.14],
111
+ [0.62, 30, -20, -0.04],
112
+ [0.8, 14, -10, 0],
113
+ [1, 0, 0, 0]
114
+ ], T = Math.max(0, Math.min(1, p)), e = Math.max(0, l.findIndex((c) => c[0] >= T) - 1), t = l[e], o = l[e + 1], u = Math.max(0, Math.min(1, (T - t[0]) / (o[0] - t[0]))), r = (c) => t[c] + (o[c] - t[c]) * u;
115
+ return { left: r(1) * Math.PI / 180, right: r(2) * Math.PI / 180, shift: r(3) * 82.3 };
116
+ }
117
+ const k = `
118
+ attribute vec3 position;
119
+ attribute vec3 normal;
120
+ attribute vec2 uv;
121
+ uniform vec2 viewport;
122
+ uniform float scale;
123
+ uniform vec2 leaf;
124
+ uniform vec2 roll;
125
+ uniform vec4 hinge;
126
+ uniform int bend;
127
+ uniform float shift;
128
+ uniform float level;
129
+ varying vec3 worldPosition;
130
+ varying vec3 worldNormal;
131
+ varying vec2 texcoord;
132
+ void main() {
133
+ vec3 p = position - vec3(0.,0.,${0.6});
134
+ p = vec3(leaf.x*p.x + leaf.y*p.z, p.y, -leaf.y*p.x + leaf.x*p.z);
135
+ if (bend==1) {
136
+ vec2 a=vec2(-1.1*hinge.x+(position.z-${0.6})*hinge.y,1.1*hinge.y+(position.z-${0.6})*hinge.x);
137
+ vec2 b=vec2(1.1*hinge.z+(position.z-${0.6})*hinge.w,-1.1*hinge.w+(position.z-${0.6})*hinge.z);
138
+ p.xz=mix(a,b,(position.x+1.1)/2.2);
139
+ }
140
+ p += vec3(shift,0.,${0.6});
141
+ vec3 n = vec3(leaf.x*normal.x + leaf.y*normal.z, normal.y, -leaf.y*normal.x + leaf.x*normal.z);
142
+ p.xy = vec2(roll.x*p.x-roll.y*p.y, roll.y*p.x+roll.x*p.y);
143
+ n.xy = vec2(roll.x*n.x-roll.y*n.y, roll.y*n.x+roll.x*n.y);
144
+ p.z -= level;
145
+ worldPosition=p; worldNormal=n; texcoord=uv;
146
+ float w = 1. - p.z/600.;
147
+ gl_Position=vec4(p.xy*scale*2./viewport, -p.z/180., w);
148
+ }`, X = `
149
+ precision highp float;
150
+ uniform int kind;
151
+ uniform sampler2D screen;
152
+ varying vec3 worldPosition;
153
+ varying vec3 worldNormal;
154
+ varying vec2 texcoord;
155
+ void main() {
156
+ if (kind==2) { gl_FragColor=texture2D(screen,texcoord); return; }
157
+ vec3 n=normalize(worldNormal);
158
+ vec3 eye=normalize(vec3(0.,0.,600.)-worldPosition);
159
+ vec3 r=normalize(reflect(-eye,n)+worldPosition/190.);
160
+ float longitude=atan(r.z,r.x);
161
+ float latitude=asin(clamp(r.y,-1.,1.));
162
+ float strip=pow(.5+.5*sin(4.*longitude+1.8*sin(latitude)),12.);
163
+ float fill=pow(.5+.5*cos(2.*longitude-3.*latitude),5.);
164
+ float highlight=pow(max(0.,dot(n,normalize(vec3(-.4,.65,1.)))),90.);
165
+ vec3 silver=vec3(.30,.32,.34)+vec3(.85,.86,.87)*strip+vec3(.48)*fill+vec3(.7)*highlight;
166
+ if(kind==1) silver=vec3(.022,.026,.030)+silver*.035;
167
+ if(kind==3) silver=vec3(.93,.93,.91)*(0.88+.12*max(n.z,0.));
168
+ gl_FragColor=vec4(clamp(silver,0.,1.),1.);
169
+ }`;
170
+ function V(p, l, T) {
171
+ const e = p.getContext("webgl", { alpha: !0, antialias: !0, powerPreference: "low-power" });
172
+ if (!e) throw new Error("Fold animation WebGL unavailable");
173
+ const t = [], o = [], u = [];
174
+ let r = null, c = 0, h = !1;
175
+ const n = () => {
176
+ if (!h) {
177
+ h = !0, cancelAnimationFrame(c);
178
+ for (const i of o) e.deleteBuffer(i);
179
+ for (const i of u) e.deleteTexture(i);
180
+ for (const i of t) e.deleteShader(i);
181
+ r && e.deleteProgram(r), e.getExtension("WEBGL_lose_context")?.loseContext();
182
+ }
183
+ };
184
+ try {
185
+ for (const [f, P] of [
186
+ [e.VERTEX_SHADER, k],
187
+ [e.FRAGMENT_SHADER, X]
188
+ ]) {
189
+ const R = e.createShader(f);
190
+ if (t.push(R), e.shaderSource(R, P), e.compileShader(R), !e.getShaderParameter(R, e.COMPILE_STATUS))
191
+ throw new Error("Fold shader compilation failed");
192
+ }
193
+ r = e.createProgram();
194
+ for (const f of t) e.attachShader(r, f);
195
+ if (e.linkProgram(r), !e.getProgramParameter(r, e.LINK_STATUS)) throw new Error("Fold shader link failed");
196
+ e.useProgram(r);
197
+ const i = (f) => e.getUniformLocation(r, f), a = Object.fromEntries(
198
+ ["viewport", "scale", "leaf", "roll", "shift", "level", "kind", "screen", "hinge", "bend"].map((f) => [
199
+ f,
200
+ i(f)
201
+ ])
202
+ ), s = l.to.inner, x = s ? l.to : l.from, d = s ? l.from : l.to, E = x.frame.rect.min.x + x.frame.rect.max.x, I = x.frame.rect.min.y + x.frame.rect.max.y, A = Math.min(window.devicePixelRatio || 1, 1.5, 1280 / Math.max(E, I));
203
+ p.width = Math.round(E * A), p.height = Math.round(I * A), e.viewport(0, 0, p.width, p.height), e.uniform2f(a.viewport, E, I), e.uniform1i(a.screen, 0), e.enable(e.DEPTH_TEST), e.clearColor(0, 0, 0, 0);
204
+ const m = {
205
+ inner: s ? l.after : l.before,
206
+ outer: s ? l.before : l.after
207
+ }, g = {};
208
+ for (const f of ["inner", "outer"]) {
209
+ const P = e.createTexture();
210
+ u.push(P), g[f] = P, e.bindTexture(e.TEXTURE_2D, P), e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL, 1), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, m[f]), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE);
211
+ }
212
+ const v = ["position", "normal", "uv"].map((f) => e.getAttribLocation(r, f)), _ = B().map((f) => {
213
+ const P = e.createBuffer();
214
+ return o.push(P), e.bindBuffer(e.ARRAY_BUFFER, P), e.bufferData(e.ARRAY_BUFFER, f.vertices, e.STATIC_DRAW), { ...f, buffer: P };
215
+ }), H = performance.now(), F = d.frame.turns * -Math.PI / 2, L = (x.frame.turns * -Math.PI / 2 - F + Math.PI * 3) % (Math.PI * 2) - Math.PI;
216
+ let D = -1 / 0;
217
+ const M = (f) => {
218
+ if (h) return;
219
+ if (f - D < 1e3 / 60 - 0.5 && f - H < 1200) {
220
+ c = requestAnimationFrame(M);
221
+ return;
222
+ }
223
+ D = f;
224
+ const P = Math.min(1, (f - H) / 1200), R = s ? P : 1 - P, b = N(R), z = R * R * (3 - 2 * R), O = F + L * z;
225
+ e.clear(e.COLOR_BUFFER_BIT | e.DEPTH_BUFFER_BIT), e.uniform1f(a.scale, d.frame.scale + (x.frame.scale - d.frame.scale) * z), e.uniform2f(a.roll, Math.cos(O), Math.sin(O)), e.uniform1f(a.shift, b.shift), e.uniform1f(a.level, (5.2 + 0.6 * 2 + 0.24) * (1 - z)), e.uniform4f(
226
+ a.hinge,
227
+ Math.cos(b.left),
228
+ Math.sin(b.left),
229
+ Math.cos(b.right),
230
+ Math.sin(b.right)
231
+ );
232
+ for (const y of _) {
233
+ e.uniform1i(a.bend, y.side === 0 ? 1 : 0);
234
+ const S = y.side === -1 ? b.left : b.right;
235
+ e.uniform2f(a.leaf, Math.cos(S), Math.sin(S));
236
+ const G = y.kind === "inner" || y.kind === "outer";
237
+ e.uniform1i(
238
+ a.kind,
239
+ G ? 2 : y.kind === "metal" ? 0 : y.kind === "seal" ? 1 : 3
240
+ ), G && e.bindTexture(e.TEXTURE_2D, g[y.kind]), e.bindBuffer(e.ARRAY_BUFFER, y.buffer);
241
+ for (let w = 0; w < v.length; w++)
242
+ e.enableVertexAttribArray(v[w]), e.vertexAttribPointer(v[w], w === 2 ? 2 : 3, e.FLOAT, !1, 32, w === 2 ? 24 : w * 12);
243
+ e.drawArrays(e.TRIANGLES, 0, y.vertices.length / 8);
244
+ }
245
+ P < 1 ? c = requestAnimationFrame(M) : (n(), T());
246
+ };
247
+ return M(H), n;
248
+ } catch (i) {
249
+ throw n(), i;
250
+ }
251
+ }
252
+ export {
253
+ C as FOLD_DURATION,
254
+ B as foldMeshes,
255
+ N as foldPose,
256
+ V as renderFold
257
+ };
@@ -0,0 +1,53 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const G=1200,y=82.3,U=117.8,B=5.2,S=.6;function N(p,l,v,e,t=0){const o=[];for(const[u,r,c,h]of[[p/2-e,l/2-e,e,0],[-p/2+v,l/2-v,v,Math.PI/2],[-p/2+v,-l/2+v,v,Math.PI],[p/2-e,-l/2+e,e,Math.PI*1.5]])for(let n=0;n<=8;n++){const i=h+n*Math.PI/16,a=Math.cos(i),s=Math.sin(i);o.push({x:u+(c-t)*a,y:r+(c-t)*s,nx:a,ny:s})}return o}function W(){const p=[],l=(t,o,u)=>p.push({side:t,kind:o,vertices:new Float32Array(u)}),v=(t,o,u,r,c,h,n,i,a,s)=>{const g=[],d=(m,T,x,R)=>g.push(m.x+u,m.y+r,T,m.nx*R,m.ny*R,x,0,0),E=Math.min(.32,i/3,a/2,s/2),M=[[E,n,.707,.707],[0,n-E,0,1],[0,n-i+E,0,1],[E,n-i,-.707,.707]];for(let m=0;m<M.length-1;m++){const T=M[m],x=M[m+1],R=N(c,h,a,s,T[0]),I=N(c,h,a,s,x[0]);for(let b=0;b<R.length;b++){const L=(b+1)%R.length;for(const[k,F]of[[R[b],T],[I[b],x],[R[L],T],[R[L],T],[I[b],x],[I[L],x]])d(k,F[1],F[2],F[3])}}const _=N(c,h,a,s,E);for(const[m,T]of[[n,1],[n-i,-1]])for(let x=0;x<_.length;x++)g.push(u,r,m,0,0,T,0,0),d(_[x],m,T,0),d(_[(x+1)%_.length],m,T,0);l(t,o,g)},e=(t,o,u,r,c,h,n,i)=>{const a=[],s=N(r,c,n,i),g=(d,E)=>{const M=d+u;let _=0,m=0;o==="inner"&&(_=.5-E/110.8,m=.5+M/157.5),o==="outer"&&(_=.5-d/r,m=.5+E/c),a.push(M,E,h,0,0,o==="outer"||o==="back"?-1:1,_,m)};for(let d=0;d<s.length;d++)g(0,0),g(s[d].x,s[d].y),g(s[(d+1)%s.length].x,s[(d+1)%s.length].y);l(t,o,a)};for(const t of[-1,1]){const o=t===-1?8.4:1.25,u=t===1?8.4:1.25;v(t,"metal",t*y/2,0,y,U,0,B,o,u),e(t,"seal",t*y/2,y-2.24,U-2.24,.12,t===-1?7.15:.2,t===1?7.15:.2),e(t,"inner",t*(157.5/4+.55),157.5/2-1.1,110.8,.24,t===-1?5.3:0,t===1?5.3:0)}for(const[t,o,u]of[["metal",U,-.12],["seal",U-2.24,.12],["inner",110.8,.24]]){const r=[],c=(h,n)=>r.push(h,n,u,0,0,1,.5-n/110.8,.5+h/157.5);for(let h=0;h<6;h++){const n=-1.1+h*2.2/6,i=n+2.2/6;for(const[a,s]of[[n,-o/2],[i,-o/2],[n,o/2],[n,o/2],[i,-o/2],[i,o/2]])c(a,s)}l(0,t,r)}e(-1,"seal",-y/2,y-2.24,U-2.24,-B-.12,7.15,.65),e(-1,"outer",-y/2,77.1,112.2,-B-.24,6.6,.8),e(1,"back",y/2,y-1,U-1,-B-.12,.8,8);for(const t of[y-37,y-25])v(1,"metal",t,U/2+.4,9.5,.8,-1.4,2,.35,.35);return v(1,"metal",y+.4,21,.8,13,-1.4,2,.35,.35),p}function $(p){const l=[[0,180,0,-.5],[.12,176,-4,-.46],[.24,150,-8,-.4],[.35,90,-12,-.32],[.48,48,-22,-.14],[.62,30,-20,-.04],[.8,14,-10,0],[1,0,0,0]],v=Math.max(0,Math.min(1,p)),e=Math.max(0,l.findIndex(c=>c[0]>=v)-1),t=l[e],o=l[e+1],u=Math.max(0,Math.min(1,(v-t[0])/(o[0]-t[0]))),r=c=>t[c]+(o[c]-t[c])*u;return{left:r(1)*Math.PI/180,right:r(2)*Math.PI/180,shift:r(3)*y}}const Y=`
2
+ attribute vec3 position;
3
+ attribute vec3 normal;
4
+ attribute vec2 uv;
5
+ uniform vec2 viewport;
6
+ uniform float scale;
7
+ uniform vec2 leaf;
8
+ uniform vec2 roll;
9
+ uniform vec4 hinge;
10
+ uniform int bend;
11
+ uniform float shift;
12
+ uniform float level;
13
+ varying vec3 worldPosition;
14
+ varying vec3 worldNormal;
15
+ varying vec2 texcoord;
16
+ void main() {
17
+ vec3 p = position - vec3(0.,0.,${S});
18
+ p = vec3(leaf.x*p.x + leaf.y*p.z, p.y, -leaf.y*p.x + leaf.x*p.z);
19
+ if (bend==1) {
20
+ vec2 a=vec2(-1.1*hinge.x+(position.z-${S})*hinge.y,1.1*hinge.y+(position.z-${S})*hinge.x);
21
+ vec2 b=vec2(1.1*hinge.z+(position.z-${S})*hinge.w,-1.1*hinge.w+(position.z-${S})*hinge.z);
22
+ p.xz=mix(a,b,(position.x+1.1)/2.2);
23
+ }
24
+ p += vec3(shift,0.,${S});
25
+ vec3 n = vec3(leaf.x*normal.x + leaf.y*normal.z, normal.y, -leaf.y*normal.x + leaf.x*normal.z);
26
+ p.xy = vec2(roll.x*p.x-roll.y*p.y, roll.y*p.x+roll.x*p.y);
27
+ n.xy = vec2(roll.x*n.x-roll.y*n.y, roll.y*n.x+roll.x*n.y);
28
+ p.z -= level;
29
+ worldPosition=p; worldNormal=n; texcoord=uv;
30
+ float w = 1. - p.z/600.;
31
+ gl_Position=vec4(p.xy*scale*2./viewport, -p.z/180., w);
32
+ }`,j=`
33
+ precision highp float;
34
+ uniform int kind;
35
+ uniform sampler2D screen;
36
+ varying vec3 worldPosition;
37
+ varying vec3 worldNormal;
38
+ varying vec2 texcoord;
39
+ void main() {
40
+ if (kind==2) { gl_FragColor=texture2D(screen,texcoord); return; }
41
+ vec3 n=normalize(worldNormal);
42
+ vec3 eye=normalize(vec3(0.,0.,600.)-worldPosition);
43
+ vec3 r=normalize(reflect(-eye,n)+worldPosition/190.);
44
+ float longitude=atan(r.z,r.x);
45
+ float latitude=asin(clamp(r.y,-1.,1.));
46
+ float strip=pow(.5+.5*sin(4.*longitude+1.8*sin(latitude)),12.);
47
+ float fill=pow(.5+.5*cos(2.*longitude-3.*latitude),5.);
48
+ float highlight=pow(max(0.,dot(n,normalize(vec3(-.4,.65,1.)))),90.);
49
+ vec3 silver=vec3(.30,.32,.34)+vec3(.85,.86,.87)*strip+vec3(.48)*fill+vec3(.7)*highlight;
50
+ if(kind==1) silver=vec3(.022,.026,.030)+silver*.035;
51
+ if(kind==3) silver=vec3(.93,.93,.91)*(0.88+.12*max(n.z,0.));
52
+ gl_FragColor=vec4(clamp(silver,0.,1.),1.);
53
+ }`;function V(p,l,v){const e=p.getContext("webgl",{alpha:!0,antialias:!0,powerPreference:"low-power"});if(!e)throw new Error("Fold animation WebGL unavailable");const t=[],o=[],u=[];let r=null,c=0,h=!1;const n=()=>{if(!h){h=!0,cancelAnimationFrame(c);for(const i of o)e.deleteBuffer(i);for(const i of u)e.deleteTexture(i);for(const i of t)e.deleteShader(i);r&&e.deleteProgram(r),e.getExtension("WEBGL_lose_context")?.loseContext()}};try{for(const[f,P]of[[e.VERTEX_SHADER,Y],[e.FRAGMENT_SHADER,j]]){const A=e.createShader(f);if(t.push(A),e.shaderSource(A,P),e.compileShader(A),!e.getShaderParameter(A,e.COMPILE_STATUS))throw new Error("Fold shader compilation failed")}r=e.createProgram();for(const f of t)e.attachShader(r,f);if(e.linkProgram(r),!e.getProgramParameter(r,e.LINK_STATUS))throw new Error("Fold shader link failed");e.useProgram(r);const i=f=>e.getUniformLocation(r,f),a=Object.fromEntries(["viewport","scale","leaf","roll","shift","level","kind","screen","hinge","bend"].map(f=>[f,i(f)])),s=l.to.inner,g=s?l.to:l.from,d=s?l.from:l.to,E=g.frame.rect.min.x+g.frame.rect.max.x,M=g.frame.rect.min.y+g.frame.rect.max.y,_=Math.min(window.devicePixelRatio||1,1.5,1280/Math.max(E,M));p.width=Math.round(E*_),p.height=Math.round(M*_),e.viewport(0,0,p.width,p.height),e.uniform2f(a.viewport,E,M),e.uniform1i(a.screen,0),e.enable(e.DEPTH_TEST),e.clearColor(0,0,0,0);const m={inner:s?l.after:l.before,outer:s?l.before:l.after},T={};for(const f of["inner","outer"]){const P=e.createTexture();u.push(P),T[f]=P,e.bindTexture(e.TEXTURE_2D,P),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,1),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,m[f]),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE)}const x=["position","normal","uv"].map(f=>e.getAttribLocation(r,f)),R=W().map(f=>{const P=e.createBuffer();return o.push(P),e.bindBuffer(e.ARRAY_BUFFER,P),e.bufferData(e.ARRAY_BUFFER,f.vertices,e.STATIC_DRAW),{...f,buffer:P}}),I=performance.now(),b=d.frame.turns*-Math.PI/2,L=(g.frame.turns*-Math.PI/2-b+Math.PI*3)%(Math.PI*2)-Math.PI;let k=-1/0;const F=f=>{if(h)return;if(f-k<1e3/60-.5&&f-I<G){c=requestAnimationFrame(F);return}k=f;const P=Math.min(1,(f-I)/G),A=s?P:1-P,D=$(A),O=A*A*(3-2*A),X=b+L*O;e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.uniform1f(a.scale,d.frame.scale+(g.frame.scale-d.frame.scale)*O),e.uniform2f(a.roll,Math.cos(X),Math.sin(X)),e.uniform1f(a.shift,D.shift),e.uniform1f(a.level,(B+S*2+.24)*(1-O)),e.uniform4f(a.hinge,Math.cos(D.left),Math.sin(D.left),Math.cos(D.right),Math.sin(D.right));for(const w of R){e.uniform1i(a.bend,w.side===0?1:0);const C=w.side===-1?D.left:D.right;e.uniform2f(a.leaf,Math.cos(C),Math.sin(C));const H=w.kind==="inner"||w.kind==="outer";e.uniform1i(a.kind,H?2:w.kind==="metal"?0:w.kind==="seal"?1:3),H&&e.bindTexture(e.TEXTURE_2D,T[w.kind]),e.bindBuffer(e.ARRAY_BUFFER,w.buffer);for(let z=0;z<x.length;z++)e.enableVertexAttribArray(x[z]),e.vertexAttribPointer(x[z],z===2?2:3,e.FLOAT,!1,32,z===2?24:z*12);e.drawArrays(e.TRIANGLES,0,w.vertices.length/8)}P<1?c=requestAnimationFrame(F):(n(),v())};return F(I),n}catch(i){throw n(),i}}exports.FOLD_DURATION=G;exports.foldMeshes=W;exports.foldPose=$;exports.renderFold=V;