@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.
- package/README.md +541 -2394
- package/dist/index.d.ts +2 -100
- package/dist/index.js +7714 -12951
- package/dist/index.js.map +1 -1
- package/dist/three/annotations/DOMControls.d.ts +73 -0
- package/dist/three/annotations/DPthree.d.ts +113 -0
- package/dist/three/annotations/DPthree3DMarkers.d.ts +319 -0
- package/dist/three/annotations/DPthreeCameraController.d.ts +414 -0
- package/dist/three/annotations/DPthreeHTMLMarkers.d.ts +131 -0
- package/dist/three/annotations/DPthreeMarkers.d.ts +52 -0
- package/dist/three/annotations/adapter.d.ts +157 -0
- package/dist/three/annotations/animationFrameTaskScheduler.d.ts +18 -0
- package/dist/three/annotations/annotationAnchorModel.d.ts +16 -0
- package/dist/three/annotations/annotationCameraCore.d.ts +5 -0
- package/dist/three/annotations/boneResolutionProfile.d.ts +7 -0
- package/dist/three/annotations/index.d.ts +20 -0
- package/dist/three/annotations/loadFrame.d.ts +2 -0
- package/dist/three/annotations/markerSurfaceRaycast.d.ts +11 -0
- package/dist/three/annotations/markerVisibilityLifecycle.d.ts +21 -0
- package/dist/three/annotations/modelRenderPreparation.d.ts +6 -0
- package/dist/three/annotations/runtimeAnnotationPreview.d.ts +15 -0
- package/dist/three/annotations/runtimeAnnotationPreviewSide.d.ts +10 -0
- package/dist/three/annotations/runtimeAnnotationSidePreview.d.ts +5 -0
- package/dist/three/annotations/types.d.ts +262 -0
- package/dist/three/gaze.d.ts +122 -0
- package/dist/three/index.d.ts +147 -0
- package/dist/three/model.d.ts +31 -0
- package/dist/three/modelSkinning.d.ts +3 -0
- package/dist/three/reference-pose.d.ts +73 -0
- package/dist/three/scene.d.ts +253 -0
- package/dist/three/sceneRenderingBinding.d.ts +22 -0
- package/dist/three.js +7696 -8936
- package/dist/three.js.map +1 -1
- package/dist/wasm/README.md +551 -62
- package/dist/wasm/auto.d.ts +1 -0
- package/dist/wasm/embody_wasm.d.ts +388 -52
- package/dist/wasm/embody_wasm.js +1514 -119
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/dist/wasm/embody_wasm_bg.wasm.d.ts +115 -40
- package/dist/wasm/index.d.ts +126 -0
- package/dist/wasm.d.ts +1 -43
- package/dist/wasm.js +1043 -239
- package/dist/wasm.js.map +1 -1
- package/package.json +34 -39
- package/service-worker/character-asset-service-worker.js +295 -0
- package/dist/authoring/boneAuthoring.d.ts +0 -132
- package/dist/camera/annotationCameraAngles.d.ts +0 -28
- package/dist/camera/cameraRelativeGaze.d.ts +0 -15
- package/dist/camera/rustAnnotationCameraCore.d.ts +0 -136
- package/dist/cljs.cjs +0 -362
- package/dist/cljs.cjs.map +0 -1
- package/dist/cljs.d.ts +0 -5
- package/dist/cljs.js +0 -359
- package/dist/cljs.js.map +0 -1
- package/dist/core/TsClipCompiler.d.ts +0 -51
- package/dist/core/WasmRuntimeCore.d.ts +0 -41
- package/dist/core/compositeAxis.d.ts +0 -4
- package/dist/core/contracts/abi.d.ts +0 -70
- package/dist/core/contracts/clip.d.ts +0 -44
- package/dist/core/contracts/frame.d.ts +0 -27
- package/dist/core/contracts/host.d.ts +0 -28
- package/dist/core/contracts/ids.d.ts +0 -15
- package/dist/core/contracts/index.d.ts +0 -10
- package/dist/core/contracts/model.d.ts +0 -31
- package/dist/core/contracts/primitives.d.ts +0 -17
- package/dist/core/contracts/skeletonFit.d.ts +0 -41
- package/dist/core/index.d.ts +0 -6
- package/dist/core/types.d.ts +0 -472
- package/dist/core.cjs +0 -343
- package/dist/core.cjs.map +0 -1
- package/dist/core.js +0 -323
- package/dist/core.js.map +0 -1
- package/dist/engines/three/Embody.d.ts +0 -372
- package/dist/engines/three/ThreeAnimationRuntime.d.ts +0 -203
- package/dist/engines/three/ThreeClipAdapter.d.ts +0 -24
- package/dist/engines/three/ThreeFrameApplier.d.ts +0 -68
- package/dist/engines/three/ThreeModelInspector.d.ts +0 -54
- package/dist/engines/three/bakedClipPartitioning.d.ts +0 -16
- package/dist/engines/three/balanceUtils.d.ts +0 -3
- package/dist/engines/three/characterHost.d.ts +0 -80
- package/dist/engines/three/characterScene.d.ts +0 -98
- package/dist/engines/three/hair/HairPhysicsController.d.ts +0 -124
- package/dist/engines/three/index.d.ts +0 -20
- package/dist/engines/three/modelLoader.d.ts +0 -61
- package/dist/engines/three/profileTestScene.d.ts +0 -52
- package/dist/engines/three/types.d.ts +0 -20
- package/dist/hair/appearance.d.ts +0 -29
- package/dist/index.cjs +0 -14871
- package/dist/index.cjs.map +0 -1
- package/dist/interfaces/Animation.d.ts +0 -315
- package/dist/interfaces/EmbodyRuntime.d.ts +0 -90
- package/dist/interfaces/Hair.d.ts +0 -181
- package/dist/interfaces/HairPhysics.d.ts +0 -90
- package/dist/interfaces/index.d.ts +0 -11
- package/dist/mappings/extendPresetWithProfile.d.ts +0 -17
- package/dist/mappings/types.d.ts +0 -309
- package/dist/mappings/visemeSystem.d.ts +0 -26
- package/dist/physics/HairPhysics.d.ts +0 -86
- package/dist/physics/RustHairPhysics.d.ts +0 -18
- package/dist/physics/index.d.ts +0 -6
- package/dist/preset.cjs +0 -2005
- package/dist/preset.cjs.map +0 -1
- package/dist/preset.js +0 -2003
- package/dist/preset.js.map +0 -1
- package/dist/presets/bettaFish.d.ts +0 -328
- package/dist/presets/cc4.d.ts +0 -145
- package/dist/presets/index.d.ts +0 -30
- package/dist/presets/registry.d.ts +0 -57
- package/dist/profiles/resolveProfileConfig.d.ts +0 -36
- package/dist/profiles/rustResolvedProfile.d.ts +0 -31
- package/dist/profiles/types.d.ts +0 -118
- package/dist/regions/normalizeRegionTree.d.ts +0 -6
- package/dist/regions/regionMapping.d.ts +0 -17
- package/dist/regions/types.d.ts +0 -122
- package/dist/skeletonTemplates/humanoidSkeletonTemplates.d.ts +0 -32
- package/dist/test/setupWasm.d.ts +0 -1
- package/dist/three.cjs +0 -9550
- package/dist/three.cjs.map +0 -1
- package/dist/validation/analyzeModel.d.ts +0 -68
- package/dist/validation/extractModelData.d.ts +0 -90
- package/dist/validation/generateMappingCorrections.d.ts +0 -32
- package/dist/validation/geometryHelpers.d.ts +0 -66
- package/dist/validation/types.d.ts +0 -10
- package/dist/validation/validateMappings.d.ts +0 -77
- package/dist/wasm.cjs +0 -302
- package/dist/wasm.cjs.map +0 -1
- 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.
|
|
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.
|
|
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
|
-
"
|
|
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/
|
|
15
|
+
"types": "./dist/three/index.d.ts",
|
|
22
16
|
"import": "./dist/three.js",
|
|
23
|
-
"
|
|
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
|
-
"
|
|
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.
|
|
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
|
-
"
|
|
49
|
-
"test": "
|
|
50
|
-
"test:
|
|
51
|
-
"test:
|
|
52
|
-
"test:
|
|
53
|
-
"test:
|
|
54
|
-
"
|
|
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
|
-
"
|
|
57
|
-
"rust:
|
|
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
|
-
"
|
|
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.
|
|
57
|
+
"three": ">=0.184.0"
|
|
64
58
|
},
|
|
65
59
|
"devDependencies": {
|
|
66
60
|
"@types/node": "^26.1.1",
|
|
67
|
-
"@types/three": "
|
|
68
|
-
"
|
|
69
|
-
"three": "
|
|
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.
|
|
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;
|