@lovelace_lol/embody 0.0.6 → 0.0.8

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 (127) hide show
  1. package/README.md +541 -2394
  2. package/dist/index.d.ts +2 -100
  3. package/dist/index.js +7714 -12951
  4. package/dist/index.js.map +1 -1
  5. package/dist/three/annotations/DOMControls.d.ts +73 -0
  6. package/dist/three/annotations/DPthree.d.ts +113 -0
  7. package/dist/three/annotations/DPthree3DMarkers.d.ts +319 -0
  8. package/dist/three/annotations/DPthreeCameraController.d.ts +414 -0
  9. package/dist/three/annotations/DPthreeHTMLMarkers.d.ts +131 -0
  10. package/dist/three/annotations/DPthreeMarkers.d.ts +52 -0
  11. package/dist/three/annotations/adapter.d.ts +157 -0
  12. package/dist/three/annotations/animationFrameTaskScheduler.d.ts +18 -0
  13. package/dist/three/annotations/annotationAnchorModel.d.ts +16 -0
  14. package/dist/three/annotations/annotationCameraCore.d.ts +5 -0
  15. package/dist/three/annotations/boneResolutionProfile.d.ts +7 -0
  16. package/dist/three/annotations/index.d.ts +20 -0
  17. package/dist/three/annotations/loadFrame.d.ts +2 -0
  18. package/dist/three/annotations/markerSurfaceRaycast.d.ts +11 -0
  19. package/dist/three/annotations/markerVisibilityLifecycle.d.ts +21 -0
  20. package/dist/three/annotations/modelRenderPreparation.d.ts +6 -0
  21. package/dist/three/annotations/runtimeAnnotationPreview.d.ts +15 -0
  22. package/dist/three/annotations/runtimeAnnotationPreviewSide.d.ts +10 -0
  23. package/dist/three/annotations/runtimeAnnotationSidePreview.d.ts +5 -0
  24. package/dist/three/annotations/types.d.ts +262 -0
  25. package/dist/three/gaze.d.ts +122 -0
  26. package/dist/three/index.d.ts +147 -0
  27. package/dist/three/model.d.ts +31 -0
  28. package/dist/three/modelSkinning.d.ts +3 -0
  29. package/dist/three/reference-pose.d.ts +73 -0
  30. package/dist/three/scene.d.ts +253 -0
  31. package/dist/three/sceneRenderingBinding.d.ts +22 -0
  32. package/dist/three.js +7696 -8936
  33. package/dist/three.js.map +1 -1
  34. package/dist/wasm/README.md +551 -62
  35. package/dist/wasm/auto.d.ts +1 -0
  36. package/dist/wasm/embody_wasm.d.ts +388 -52
  37. package/dist/wasm/embody_wasm.js +1514 -119
  38. package/dist/wasm/embody_wasm_bg.wasm +0 -0
  39. package/dist/wasm/embody_wasm_bg.wasm.d.ts +115 -40
  40. package/dist/wasm/index.d.ts +126 -0
  41. package/dist/wasm.d.ts +1 -43
  42. package/dist/wasm.js +1043 -239
  43. package/dist/wasm.js.map +1 -1
  44. package/package.json +34 -39
  45. package/service-worker/character-asset-service-worker.js +295 -0
  46. package/dist/authoring/boneAuthoring.d.ts +0 -132
  47. package/dist/camera/annotationCameraAngles.d.ts +0 -28
  48. package/dist/camera/cameraRelativeGaze.d.ts +0 -15
  49. package/dist/camera/rustAnnotationCameraCore.d.ts +0 -136
  50. package/dist/cljs.cjs +0 -362
  51. package/dist/cljs.cjs.map +0 -1
  52. package/dist/cljs.d.ts +0 -5
  53. package/dist/cljs.js +0 -359
  54. package/dist/cljs.js.map +0 -1
  55. package/dist/core/TsClipCompiler.d.ts +0 -51
  56. package/dist/core/WasmRuntimeCore.d.ts +0 -41
  57. package/dist/core/compositeAxis.d.ts +0 -4
  58. package/dist/core/contracts/abi.d.ts +0 -70
  59. package/dist/core/contracts/clip.d.ts +0 -44
  60. package/dist/core/contracts/frame.d.ts +0 -27
  61. package/dist/core/contracts/host.d.ts +0 -28
  62. package/dist/core/contracts/ids.d.ts +0 -15
  63. package/dist/core/contracts/index.d.ts +0 -10
  64. package/dist/core/contracts/model.d.ts +0 -31
  65. package/dist/core/contracts/primitives.d.ts +0 -17
  66. package/dist/core/contracts/skeletonFit.d.ts +0 -41
  67. package/dist/core/index.d.ts +0 -6
  68. package/dist/core/types.d.ts +0 -472
  69. package/dist/core.cjs +0 -343
  70. package/dist/core.cjs.map +0 -1
  71. package/dist/core.js +0 -323
  72. package/dist/core.js.map +0 -1
  73. package/dist/engines/three/Embody.d.ts +0 -372
  74. package/dist/engines/three/ThreeAnimationRuntime.d.ts +0 -203
  75. package/dist/engines/three/ThreeClipAdapter.d.ts +0 -24
  76. package/dist/engines/three/ThreeFrameApplier.d.ts +0 -68
  77. package/dist/engines/three/ThreeModelInspector.d.ts +0 -54
  78. package/dist/engines/three/bakedClipPartitioning.d.ts +0 -16
  79. package/dist/engines/three/balanceUtils.d.ts +0 -3
  80. package/dist/engines/three/characterHost.d.ts +0 -80
  81. package/dist/engines/three/characterScene.d.ts +0 -98
  82. package/dist/engines/three/hair/HairPhysicsController.d.ts +0 -124
  83. package/dist/engines/three/index.d.ts +0 -20
  84. package/dist/engines/three/modelLoader.d.ts +0 -61
  85. package/dist/engines/three/profileTestScene.d.ts +0 -52
  86. package/dist/engines/three/types.d.ts +0 -20
  87. package/dist/hair/appearance.d.ts +0 -29
  88. package/dist/index.cjs +0 -14871
  89. package/dist/index.cjs.map +0 -1
  90. package/dist/interfaces/Animation.d.ts +0 -315
  91. package/dist/interfaces/EmbodyRuntime.d.ts +0 -90
  92. package/dist/interfaces/Hair.d.ts +0 -181
  93. package/dist/interfaces/HairPhysics.d.ts +0 -90
  94. package/dist/interfaces/index.d.ts +0 -11
  95. package/dist/mappings/extendPresetWithProfile.d.ts +0 -17
  96. package/dist/mappings/types.d.ts +0 -309
  97. package/dist/mappings/visemeSystem.d.ts +0 -26
  98. package/dist/physics/HairPhysics.d.ts +0 -86
  99. package/dist/physics/RustHairPhysics.d.ts +0 -18
  100. package/dist/physics/index.d.ts +0 -6
  101. package/dist/preset.cjs +0 -2005
  102. package/dist/preset.cjs.map +0 -1
  103. package/dist/preset.js +0 -2003
  104. package/dist/preset.js.map +0 -1
  105. package/dist/presets/bettaFish.d.ts +0 -328
  106. package/dist/presets/cc4.d.ts +0 -145
  107. package/dist/presets/index.d.ts +0 -30
  108. package/dist/presets/registry.d.ts +0 -57
  109. package/dist/profiles/resolveProfileConfig.d.ts +0 -36
  110. package/dist/profiles/rustResolvedProfile.d.ts +0 -31
  111. package/dist/profiles/types.d.ts +0 -118
  112. package/dist/regions/normalizeRegionTree.d.ts +0 -6
  113. package/dist/regions/regionMapping.d.ts +0 -17
  114. package/dist/regions/types.d.ts +0 -122
  115. package/dist/skeletonTemplates/humanoidSkeletonTemplates.d.ts +0 -32
  116. package/dist/test/setupWasm.d.ts +0 -1
  117. package/dist/three.cjs +0 -9550
  118. package/dist/three.cjs.map +0 -1
  119. package/dist/validation/analyzeModel.d.ts +0 -68
  120. package/dist/validation/extractModelData.d.ts +0 -90
  121. package/dist/validation/generateMappingCorrections.d.ts +0 -32
  122. package/dist/validation/geometryHelpers.d.ts +0 -66
  123. package/dist/validation/types.d.ts +0 -10
  124. package/dist/validation/validateMappings.d.ts +0 -77
  125. package/dist/wasm.cjs +0 -302
  126. package/dist/wasm.cjs.map +0 -1
  127. package/dist/wasmTypes.d.ts +0 -123
package/package.json CHANGED
@@ -1,75 +1,69 @@
1
1
  {
2
2
  "name": "@lovelace_lol/embody",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Renderer-agnostic character animation runtime for facial AUs, visemes, and bone-driven motion",
5
5
  "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.js",
6
+ "main": "./dist/index.js",
8
7
  "types": "./dist/index.d.ts",
9
8
  "exports": {
10
9
  ".": {
11
10
  "types": "./dist/index.d.ts",
12
11
  "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
14
- },
15
- "./core": {
16
- "types": "./dist/core/index.d.ts",
17
- "import": "./dist/core.js",
18
- "require": "./dist/core.cjs"
12
+ "default": "./dist/index.js"
19
13
  },
20
14
  "./three": {
21
- "types": "./dist/engines/three/index.d.ts",
15
+ "types": "./dist/three/index.d.ts",
22
16
  "import": "./dist/three.js",
23
- "require": "./dist/three.cjs"
24
- },
25
- "./cljs": {
26
- "types": "./dist/cljs.d.ts",
27
- "import": "./dist/cljs.js",
28
- "require": "./dist/cljs.cjs"
17
+ "default": "./dist/three.js"
29
18
  },
30
19
  "./wasm": {
31
- "types": "./dist/wasm.d.ts",
20
+ "types": "./dist/wasm/index.d.ts",
32
21
  "import": "./dist/wasm.js",
33
- "require": "./dist/wasm.cjs"
34
- }
22
+ "default": "./dist/wasm.js"
23
+ },
24
+ "./character-asset-service-worker.js": "./service-worker/character-asset-service-worker.js"
35
25
  },
36
26
  "files": [
37
27
  "dist",
28
+ "service-worker",
38
29
  "README.md",
39
30
  "LICENSE"
40
31
  ],
41
32
  "publishConfig": {
42
- "access": "public"
33
+ "access": "public",
34
+ "provenance": false
43
35
  },
44
36
  "scripts": {
45
- "build": "tsup --config tsup.wasm.config.ts && tsup --config tsup.config.ts && tsc -p tsconfig.declarations.json && node scripts/export-preset-json.mjs --check && npm run wasm:build",
46
- "dev": "tsup --watch",
37
+ "build": "tsup --config tsup.config.mjs && npm run wasm:build && tsc -p tsconfig.declarations.json",
38
+ "dev": "tsup --config tsup.config.mjs --watch",
47
39
  "typecheck": "tsc --noEmit",
48
- "pretest": "npm run wasm:build",
49
- "test": "vitest run",
50
- "test:watch": "vitest",
51
- "test:coverage": "vitest run --coverage",
52
- "test:exports": "npm run build && node scripts/smoke/package-exports.mjs && node scripts/smoke/package-declarations.mjs",
53
- "test:pack": "npm run build && npm pack --dry-run",
54
- "preset:export": "tsup --config tsup.config.ts && node scripts/export-preset-json.mjs",
40
+ "test": "npm run rust:test && npm run typecheck && npm run test:annotations",
41
+ "test:service-worker": "node --test scripts/test/character-asset-service-worker.test.mjs",
42
+ "test:scene": "node --test scripts/test/character-scene.test.mjs",
43
+ "test:exports": "node scripts/smoke/package-exports.mjs && node scripts/smoke/body-controls.mjs && node scripts/smoke/semantic-pose.mjs && node scripts/smoke/morph-authoring.mjs && node scripts/smoke/mesh-profile.mjs && node scripts/smoke/inherited-starts.mjs && node scripts/smoke/bilateral-channels.mjs && node scripts/smoke/viseme-state.mjs && node scripts/smoke/reference-pose.mjs && node scripts/smoke/clip-interpolation.mjs && node scripts/smoke/gaze-focus.mjs && node scripts/smoke/package-declarations.mjs",
44
+ "test:pack": "node scripts/smoke/package-contents.mjs",
45
+ "test:package": "npm run check:dist && npm run test:exports && npm run test:scene && npm run test:pack && npm run test:annotations",
46
+ "check:dist": "node scripts/ci/check-built-package.mjs",
47
+ "check:generated": "node scripts/ci/check-no-tracked-generated.mjs",
55
48
  "extract:humanoid-skeleton-template": "node scripts/extract-humanoid-skeleton-template.cjs",
56
- "bench:runtime": "npm run build && node scripts/bench/runtime.mjs",
57
- "rust:test": "RUSTC=$(rustup which rustc) RUSTDOC=$(rustup which rustdoc) rustup run stable cargo test --manifest-path rust/embody-wasm/Cargo.toml",
58
- "rust:wasm-build": "RUSTC=$(rustup which rustc) RUSTDOC=$(rustup which rustdoc) rustup run stable cargo build --manifest-path rust/embody-wasm/Cargo.toml --target wasm32-unknown-unknown --release",
49
+ "rust:test": "RUSTC=$(rustup which rustc) RUSTDOC=$(rustup which rustdoc) rustup run stable cargo test",
50
+ "rust:wasm-build": "RUSTC=$(rustup which rustc) RUSTDOC=$(rustup which rustdoc) rustup run stable cargo build --target wasm32-unknown-unknown --release",
59
51
  "wasm:build": "node scripts/build-wasm.mjs",
60
- "prepublishOnly": "npm run build"
52
+ "prepack": "npm run check:dist",
53
+ "prepublishOnly": "npm run check:dist",
54
+ "test:annotations": "vitest run --config vitest.config.ts"
61
55
  },
62
56
  "peerDependencies": {
63
- "three": ">=0.150.0"
57
+ "three": ">=0.184.0"
64
58
  },
65
59
  "devDependencies": {
66
60
  "@types/node": "^26.1.1",
67
- "@types/three": "^0.170.0",
68
- "@vitest/coverage-v8": "^3.2.4",
69
- "three": "^0.170.0",
61
+ "@types/three": "0.184.0",
62
+ "pkg-pr-new": "0.0.87",
63
+ "three": "0.184.0",
70
64
  "tsup": "^8.0.0",
71
65
  "typescript": "^5.9.0",
72
- "vitest": "^3.2.4",
66
+ "vitest": "^3.2.7",
73
67
  "wasm-pack": "^0.15.0"
74
68
  },
75
69
  "keywords": [
@@ -96,5 +90,6 @@
96
90
  "homepage": "https://github.com/meekmachine/embody#readme",
97
91
  "author": "Jonathan Sutton Fields",
98
92
  "license": "MIT",
99
- "packageManager": "npm@10.9.2"
93
+ "packageManager": "npm@10.9.2",
94
+ "gitHead": "a55e89edbb22b26059a63ce002a2c3e25caf0cf0"
100
95
  }
@@ -0,0 +1,295 @@
1
+ // Character asset cache service worker.
2
+ //
3
+ // Embody owns character loading, so it also ships this worker. Hosts copy the
4
+ // file to their web root (it must be served same-origin at or above the page
5
+ // scope) and register it, e.g.:
6
+ //
7
+ // navigator.serviceWorker.register(`${BASE_URL}service-worker.js`);
8
+ //
9
+ // Caching policy: character assets (models, textures, thumbnails, preview
10
+ // clips) are cache-first on deployed origins and network-first on localhost,
11
+ // keyed by a stable origin-independent object path so preview deploys share
12
+ // one cache.
13
+ const SW_VERSION = 'v1';
14
+ const CHARACTER_CACHE = `embody-character-assets-${SW_VERSION}`;
15
+ const LEGACY_CACHE_PREFIXES = ['embody-character-assets-', 'loomlarge-character-assets-'];
16
+ const SHARED_CACHE_DOMAINS = ['web.app'];
17
+ const STABLE_ASSET_CACHE_ORIGIN = 'https://embody.asset-cache.local';
18
+ const ASSET_SOURCE_HEADER = 'X-Embody-Asset-Source';
19
+ const ASSET_PATH_PREFIXES = [
20
+ 'characters',
21
+ 'thumbnails',
22
+ 'preview-clips',
23
+ 'previews',
24
+ 'textures',
25
+ 'models',
26
+ 'animations',
27
+ ];
28
+
29
+ function isCharacterAssetRequest(url) {
30
+ const pathname = url.pathname || '';
31
+ return (
32
+ ASSET_PATH_PREFIXES.some((prefix) => pathname.includes(`/${prefix}/`)) ||
33
+ /\.(glb|gltf|bin|fbx|ktx2?|basis|png|jpe?g|webp|gif|avif|webm)(?:$|\?)/i.test(pathname)
34
+ );
35
+ }
36
+
37
+ function isLocalhost(url) {
38
+ return (
39
+ url.hostname === 'localhost' ||
40
+ url.hostname === '127.0.0.1' ||
41
+ url.hostname === '0.0.0.0'
42
+ );
43
+ }
44
+
45
+ function isCacheableResponse(response) {
46
+ if (!response) {
47
+ return false;
48
+ }
49
+
50
+ if (response.status !== 200) {
51
+ return false;
52
+ }
53
+
54
+ if (response.type === 'opaque') {
55
+ return false;
56
+ }
57
+
58
+ if (!response.ok) {
59
+ return false;
60
+ }
61
+
62
+ const contentType = response.headers.get('content-type') || '';
63
+ return !contentType.toLowerCase().includes('text/html');
64
+ }
65
+
66
+ // Identify the branch that served this response without reading or buffering
67
+ // its body. "network" means fetch(), which can still revalidate the browser's
68
+ // HTTP cache; "cache" means a response from our CacheStorage.
69
+ function withAssetSource(response, source) {
70
+ // Opaque and error responses have status 0 and cannot be reconstructed.
71
+ if (response.status < 200 || response.status > 599) {
72
+ return response;
73
+ }
74
+
75
+ const headers = new Headers(response.headers);
76
+ headers.set(ASSET_SOURCE_HEADER, source);
77
+ const exposedHeaders = headers.get('Access-Control-Expose-Headers');
78
+ headers.set(
79
+ 'Access-Control-Expose-Headers',
80
+ exposedHeaders ? `${exposedHeaders}, ${ASSET_SOURCE_HEADER}` : ASSET_SOURCE_HEADER,
81
+ );
82
+
83
+ return new Response(response.body, {
84
+ status: response.status,
85
+ statusText: response.statusText,
86
+ headers,
87
+ });
88
+ }
89
+
90
+ // `response` must be a dedicated clone: cache.put consumes its body.
91
+ async function putInCache(cacheName, request, response) {
92
+ if (!isCacheableResponse(response)) {
93
+ return;
94
+ }
95
+
96
+ try {
97
+ const cache = await caches.open(cacheName);
98
+ await cache.put(request, response);
99
+ } catch (error) {
100
+ console.warn('[ServiceWorker] Failed to cache character asset:', error);
101
+ }
102
+ }
103
+
104
+ // Avoid rewriting multi-hundred-megabyte cache entries when the network
105
+ // response is byte-identical to what we already stored (localhost reloads
106
+ // re-fetch every time, so this runs on every page load).
107
+ async function hasSameCachedEntry(cacheKey, response) {
108
+ try {
109
+ const cache = await caches.open(CHARACTER_CACHE);
110
+ const cached = await cache.match(cacheKey);
111
+ if (!cached) {
112
+ return false;
113
+ }
114
+
115
+ const etag = response.headers.get('etag');
116
+ if (etag) {
117
+ return cached.headers.get('etag') === etag;
118
+ }
119
+
120
+ const contentLength = response.headers.get('content-length');
121
+ return Boolean(contentLength) && cached.headers.get('content-length') === contentLength;
122
+ } catch {
123
+ return false;
124
+ }
125
+ }
126
+
127
+ function normalizeCacheKey(url) {
128
+ const cacheUrl = new URL(url.toString());
129
+ cacheUrl.search = '';
130
+ cacheUrl.hash = '';
131
+ const sharedDomain = SHARED_CACHE_DOMAINS.find(
132
+ (domain) => cacheUrl.hostname === domain || cacheUrl.hostname.endsWith(`.${domain}`),
133
+ );
134
+
135
+ if (sharedDomain) {
136
+ cacheUrl.hostname = sharedDomain;
137
+ cacheUrl.port = '';
138
+ }
139
+
140
+ return cacheUrl.toString();
141
+ }
142
+
143
+ function normalizeAssetObjectPath(url) {
144
+ let decodedPathname = url.pathname || '';
145
+ try {
146
+ decodedPathname = decodeURIComponent(decodedPathname);
147
+ } catch {
148
+ // Keep the raw path if the URL contains a malformed escape sequence.
149
+ }
150
+
151
+ const pathname = decodedPathname.replace(/^\/+/, '');
152
+ const pathParts = pathname.split('/').filter(Boolean);
153
+ const supportedPrefixIndex = pathParts.findIndex((part) =>
154
+ ASSET_PATH_PREFIXES.includes(part),
155
+ );
156
+
157
+ if (supportedPrefixIndex >= 0) {
158
+ return pathParts.slice(supportedPrefixIndex).join('/');
159
+ }
160
+
161
+ if (pathParts[0] === 'assets' && pathParts.length > 1) {
162
+ return pathParts.slice(1).join('/');
163
+ }
164
+
165
+ return pathname || null;
166
+ }
167
+
168
+ function stableAssetCacheKey(url) {
169
+ const objectPath = normalizeAssetObjectPath(url);
170
+ if (!objectPath) {
171
+ return normalizeCacheKey(url);
172
+ }
173
+
174
+ return `${STABLE_ASSET_CACHE_ORIGIN}/${objectPath}`;
175
+ }
176
+
177
+ async function matchCachedAsset(cache, url) {
178
+ const cacheKey = stableAssetCacheKey(url);
179
+ const cached = await cache.match(cacheKey);
180
+ if (cached) {
181
+ return cached;
182
+ }
183
+
184
+ const objectPath = normalizeAssetObjectPath(url);
185
+ if (!objectPath) {
186
+ return null;
187
+ }
188
+
189
+ const cachedRequests = await cache.keys();
190
+ for (const request of cachedRequests) {
191
+ try {
192
+ const cachedUrl = new URL(request.url);
193
+ if (normalizeAssetObjectPath(cachedUrl) !== objectPath) {
194
+ continue;
195
+ }
196
+
197
+ const legacyCached = await cache.match(request);
198
+ if (legacyCached) {
199
+ await cache.put(cacheKey, legacyCached.clone());
200
+ return legacyCached;
201
+ }
202
+ } catch {
203
+ // Ignore malformed legacy cache entries.
204
+ }
205
+ }
206
+
207
+ return null;
208
+ }
209
+
210
+ // Cache in the background so the page starts consuming the response
211
+ // immediately instead of waiting for the full body to be written to disk.
212
+ function cacheInBackground(event, cacheKey, response, { skipIfUnchanged = false } = {}) {
213
+ if (!isCacheableResponse(response)) {
214
+ return;
215
+ }
216
+
217
+ const copy = response.clone();
218
+ event.waitUntil(
219
+ (async () => {
220
+ if (skipIfUnchanged && (await hasSameCachedEntry(cacheKey, copy))) {
221
+ return;
222
+ }
223
+ await putInCache(CHARACTER_CACHE, cacheKey, copy);
224
+ })(),
225
+ );
226
+ }
227
+
228
+ async function cacheFirstAsset(event, url) {
229
+ const cache = await caches.open(CHARACTER_CACHE);
230
+ const cached = await matchCachedAsset(cache, url);
231
+ if (cached) {
232
+ return withAssetSource(cached, 'cache');
233
+ }
234
+
235
+ const response = await fetch(event.request);
236
+ cacheInBackground(event, stableAssetCacheKey(url), response);
237
+ return withAssetSource(response, 'network');
238
+ }
239
+
240
+ async function networkFirst(event, url) {
241
+ const cacheKey = normalizeCacheKey(url);
242
+
243
+ try {
244
+ const response = await fetch(event.request);
245
+ cacheInBackground(event, cacheKey, response, { skipIfUnchanged: true });
246
+ return withAssetSource(response, 'network');
247
+ } catch (error) {
248
+ const cache = await caches.open(CHARACTER_CACHE);
249
+ const cached = await cache.match(cacheKey);
250
+ if (cached) {
251
+ return withAssetSource(cached, 'cache');
252
+ }
253
+ throw error;
254
+ }
255
+ }
256
+
257
+ self.addEventListener('install', (event) => {
258
+ event.waitUntil(self.skipWaiting());
259
+ });
260
+
261
+ self.addEventListener('activate', (event) => {
262
+ event.waitUntil(
263
+ (async () => {
264
+ const keys = await caches.keys();
265
+ await Promise.all(
266
+ keys
267
+ .filter(
268
+ (key) =>
269
+ LEGACY_CACHE_PREFIXES.some((prefix) => key.startsWith(prefix)) &&
270
+ key !== CHARACTER_CACHE,
271
+ )
272
+ .map((key) => caches.delete(key)),
273
+ );
274
+ await self.clients.claim();
275
+ })(),
276
+ );
277
+ });
278
+
279
+ self.addEventListener('fetch', (event) => {
280
+ if (event.request.method !== 'GET') {
281
+ return;
282
+ }
283
+
284
+ const url = new URL(event.request.url);
285
+ if (!isCharacterAssetRequest(url)) {
286
+ return;
287
+ }
288
+
289
+ if (isLocalhost(url)) {
290
+ event.respondWith(networkFirst(event, url));
291
+ return;
292
+ }
293
+
294
+ event.respondWith(cacheFirstAsset(event, url));
295
+ });
@@ -1,132 +0,0 @@
1
- import type { AUInfo } from '../core/types';
2
- import type { Profile } from '../mappings/types';
3
- export declare const JOINT_CONTROL_SECTION = "Joint Controls";
4
- export type BoneAxisKey = 'pitch' | 'yaw' | 'roll';
5
- export type RotationChannel = 'rx' | 'ry' | 'rz';
6
- export type BoneAxisDirection = 'negative' | 'positive';
7
- export type BoneAxisDirectionScale = -1 | 1;
8
- export interface BilateralAxisDirectionScaleState {
9
- left: BoneAxisDirectionScale | null;
10
- right: BoneAxisDirectionScale | null;
11
- }
12
- export interface BoneAxisBindingState {
13
- axis: BoneAxisKey;
14
- channel: RotationChannel;
15
- nodeKey: string;
16
- positiveAuId: number | null;
17
- negativeAuId: number | null;
18
- positiveMaxDegrees: number | null;
19
- negativeMaxDegrees: number | null;
20
- positiveScale: BoneAxisDirectionScale | null;
21
- negativeScale: BoneAxisDirectionScale | null;
22
- }
23
- export interface BoneAxisBindingUpdate {
24
- channel?: RotationChannel;
25
- positiveAuId?: number | null;
26
- negativeAuId?: number | null;
27
- positiveMaxDegrees?: number | null;
28
- negativeMaxDegrees?: number | null;
29
- positiveScale?: BoneAxisDirectionScale | null;
30
- negativeScale?: BoneAxisDirectionScale | null;
31
- positiveLeftScale?: BoneAxisDirectionScale | null;
32
- positiveRightScale?: BoneAxisDirectionScale | null;
33
- negativeLeftScale?: BoneAxisDirectionScale | null;
34
- negativeRightScale?: BoneAxisDirectionScale | null;
35
- }
36
- export declare function isMaxDegreesOnlyAxisBindingUpdate(update: BoneAxisBindingUpdate): boolean;
37
- export interface AUBoneBindingState {
38
- auId: number;
39
- boneName: string | null;
40
- nodeKey: string | null;
41
- axis: BoneAxisKey;
42
- direction: BoneAxisDirection;
43
- channel: RotationChannel | null;
44
- maxDegrees: number | null;
45
- oppositeAuId: number | null;
46
- oppositeMaxDegrees: number | null;
47
- hasBinding: boolean;
48
- hasMultipleBindings: boolean;
49
- }
50
- export interface CreatedBoneAxisAu {
51
- auId: number;
52
- profile: Profile;
53
- }
54
- export interface ChiralBoneNamePair {
55
- leftBoneName: string;
56
- rightBoneName: string;
57
- selectedSide: 'left' | 'right';
58
- familyLabel: string;
59
- }
60
- export type BoneControlScope = 'Left Eye Only' | 'Right Eye Only' | 'Both Eyes';
61
- export type BoneControlFamily = 'Horizontal Gaze' | 'Vertical Gaze';
62
- export type BilateralBoneAxisScope = 'shared' | 'left' | 'right';
63
- export interface BilateralAxisScopeBindingState {
64
- scope: BilateralBoneAxisScope;
65
- label: string;
66
- negativeAuId: number | null;
67
- positiveAuId: number | null;
68
- negativeMaxDegrees: number | null;
69
- positiveMaxDegrees: number | null;
70
- negativeScale: BilateralAxisDirectionScaleState;
71
- positiveScale: BilateralAxisDirectionScaleState;
72
- }
73
- export interface BilateralAxisBindingState {
74
- axis: BoneAxisKey;
75
- familyLabel: string;
76
- leftBoneName: string;
77
- leftNodeKey: string;
78
- rightBoneName: string;
79
- rightNodeKey: string;
80
- selectedSide: 'left' | 'right';
81
- shared: BilateralAxisScopeBindingState;
82
- left: BilateralAxisScopeBindingState;
83
- right: BilateralAxisScopeBindingState;
84
- }
85
- export declare const DEFAULT_AXIS_TO_CHANNEL: Record<BoneAxisKey, RotationChannel>;
86
- export declare const DEFAULT_BONE_MAX_DEGREES = 60;
87
- export declare function inferChiralBoneNamePair(boneNames: string[], selectedBoneName: string): ChiralBoneNamePair | null;
88
- export declare function formatAxisLabel(axis: BoneAxisKey): string;
89
- export declare function formatAxisDirectionLabel(axis: BoneAxisKey, direction: BoneAxisDirection): string;
90
- export declare function stripConfiguredBoneAffixes(profile: {
91
- bonePrefix?: string;
92
- boneSuffix?: string;
93
- } | null | undefined, boneName: string): string;
94
- export declare function findNodeKeyForBone(boneName: string, profile: Profile | null): string | null;
95
- export declare function ensureBoneNodeKey(profile: Profile, boneName: string): {
96
- nodeKey: string;
97
- boneNodes: Record<string, string>;
98
- };
99
- export declare function ensureBilateralBoneNodeKeys(profile: Profile, leftBoneName: string, rightBoneName: string): Profile;
100
- export declare function resolveBoneNameForNodeKey(profile: Profile, nodeKey: string): string | null;
101
- export declare function inferEyeControlScope(profile: Pick<Profile, 'auToBones'>, binding: Pick<BoneAxisBindingState, 'nodeKey' | 'negativeAuId' | 'positiveAuId'>): BoneControlScope | null;
102
- export declare function inferEyeControlFamily(binding: Pick<BoneAxisBindingState, 'nodeKey' | 'axis'>): BoneControlFamily | null;
103
- export declare function resolveBoneAxisChannel(profile: Profile, boneName: string, axis: BoneAxisKey): RotationChannel;
104
- export declare function getBoneAxisBindingState(profile: Profile, boneName: string, axis: BoneAxisKey): BoneAxisBindingState;
105
- export declare function getBilateralAxisBindingState(profile: Profile, boneName: string, axis: BoneAxisKey): BilateralAxisBindingState | null;
106
- export declare function getAUBoneBindingState(profile: Profile, auId: number): AUBoneBindingState;
107
- export declare function applyAUBoneBindingUpdate(profile: Profile, auId: number, update: {
108
- boneName: string | null;
109
- axis: BoneAxisKey;
110
- direction: BoneAxisDirection;
111
- maxDegrees: number | null;
112
- }): Profile;
113
- export declare function resolveContinuumDisplayLabel(profile: Pick<Profile, 'continuumPairs' | 'continuumLabels' | 'auInfo' | 'boneNodes' | 'bonePrefix' | 'boneSuffix'>, negativeAuId: number, positiveAuId: number): string;
114
- export declare function applyBoneAxisBindingUpdate(profile: Profile, boneName: string, axis: BoneAxisKey, update: BoneAxisBindingUpdate): Profile;
115
- export declare function applyBilateralAxisBindingUpdate(profile: Profile, boneName: string, axis: BoneAxisKey, scope: BilateralBoneAxisScope, update: BoneAxisBindingUpdate): Profile;
116
- export declare function isJointControlAuInfo(info: Pick<AUInfo, 'facePart'> | null | undefined): boolean;
117
- export declare function classifyAuAsJointControl(profile: Profile, auId: number, options?: {
118
- boneName?: string | null;
119
- nodeKey?: string | null;
120
- }): Profile;
121
- export declare function createBoneAxisAu(profile: Profile, boneName: string, axis: BoneAxisKey, direction: BoneAxisDirection, options?: {
122
- name?: string;
123
- }): CreatedBoneAxisAu;
124
- export declare function createBilateralBoneAxisAu(profile: Profile, boneName: string, axis: BoneAxisKey, scope: BilateralBoneAxisScope, direction: BoneAxisDirection, options?: {
125
- name?: string;
126
- }): CreatedBoneAxisAu;
127
- export declare function buildBoneAuOptions(profile: Profile): Array<{
128
- value: string;
129
- label: string;
130
- detail?: string;
131
- }>;
132
- export declare function getAxisFromChannel(channel: string | undefined): BoneAxisKey | null;
@@ -1,28 +0,0 @@
1
- import * as THREE from 'three';
2
- import type { BoneResolutionProfile } from '../regions/regionMapping';
3
- import type { Region } from '../regions/types';
4
- type SemanticSide = 'left' | 'right';
5
- export interface AnnotationLaterality {
6
- leftSideX: 1 | -1;
7
- confidence: number;
8
- evidence: string[];
9
- }
10
- type LateralityRegion = Pick<Region, 'name' | 'cameraAngle' | 'parent'>;
11
- export declare function getDefaultAnnotationLaterality(): AnnotationLaterality;
12
- export declare function normalizeCameraAngle(angle: number): number;
13
- export declare function getRegionSemanticSide(regionName?: string): SemanticSide | null;
14
- export declare function getSemanticHorizontalSign(regionName: string, laterality: AnnotationLaterality): 1 | -1 | null;
15
- export declare function getSemanticHorizontalSignForSide(side: SemanticSide, laterality: AnnotationLaterality): 1 | -1;
16
- export declare function detectAnnotationLaterality(model: THREE.Object3D | null, regions: Region[], characterConfig: BoneResolutionProfile | null): AnnotationLaterality;
17
- export declare function resolveRegionCameraAngle(region: LateralityRegion, laterality: AnnotationLaterality): number | undefined;
18
- export declare function resolveRegionVisibilityCameraAngle(region: LateralityRegion, laterality: AnnotationLaterality): number | undefined;
19
- export declare function toWorldDirection(model: THREE.Object3D | null, localDirection: THREE.Vector3): THREE.Vector3;
20
- export declare function toModelLocalDirection(model: THREE.Object3D | null, worldDirection: THREE.Vector3): THREE.Vector3;
21
- export declare function getWorldDirectionForCameraAngle(model: THREE.Object3D | null, cameraAngle: number): THREE.Vector3;
22
- export declare function getModelLocalOrbitAngle(model: THREE.Object3D | null, modelCenter: THREE.Vector3, worldPosition: THREE.Vector3): number;
23
- export declare function passesMarkerCameraAngleGate(params: {
24
- markerAngle?: number;
25
- currentCameraAngle?: number;
26
- rangeDegrees?: number;
27
- }): boolean;
28
- export {};
@@ -1,15 +0,0 @@
1
- import * as THREE from 'three';
2
- export type CameraRelativeGazeOffset = {
3
- x: number;
4
- y: number;
5
- };
6
- export interface CameraRelativeGazeOptions {
7
- yawWeight?: number;
8
- pitchWeight?: number;
9
- epsilon?: number;
10
- }
11
- /**
12
- * Convert the current camera position into a normalized gaze offset in model-local space.
13
- * This is intentionally pure so apps can cache or subscribe to camera changes however they want.
14
- */
15
- export declare function computeCameraRelativeGazeOffset(model: THREE.Object3D | null, cameraPosition: THREE.Vector3, targetPosition: THREE.Vector3, options?: CameraRelativeGazeOptions): CameraRelativeGazeOffset;