sindicate 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/assets.js +18 -0
- package/src/core/retarget.js +4 -1
package/package.json
CHANGED
package/src/core/assets.js
CHANGED
|
@@ -13,6 +13,12 @@ export function setAtlasEmissiveHook(fn) { atlasEmissiveHook = fn; }
|
|
|
13
13
|
// it), not the engine — register per game: setClipCacheVersion(2). Defaults to 2
|
|
14
14
|
// (western's current rebake generation).
|
|
15
15
|
export function setClipCacheVersion(v) { CLIP_JSON_VER = v; }
|
|
16
|
+
|
|
17
|
+
// A registered CLIP PACK (e.g. Accentimations) is consulted BEFORE the per-game cooked
|
|
18
|
+
// cache: registerClipPack({ urlFor: (sourceStem) => url|null }). Misses fall through to
|
|
19
|
+
// the cooked cache, then the FBX parse — fully backwards compatible.
|
|
20
|
+
let clipPack = null;
|
|
21
|
+
export function registerClipPack(pack) { clipPack = pack; }
|
|
16
22
|
// Patched loader from vendor/ — merges ALL FBX animation layers per stack. The
|
|
17
23
|
// engine does NOT depend on a node_modules postinstall patch.
|
|
18
24
|
import { FBXLoader } from '../vendor/FBXLoader.js';
|
|
@@ -547,6 +553,18 @@ export async function loadClip(url, name) {
|
|
|
547
553
|
if (!clipCache.has(url)) {
|
|
548
554
|
const jsonName = clipJsonName(url);
|
|
549
555
|
const p = (async () => {
|
|
556
|
+
const packUrl = clipPack?.urlFor?.(url.split('/').pop().replace(/\.fbx$/i, ''));
|
|
557
|
+
if (packUrl) {
|
|
558
|
+
try {
|
|
559
|
+
const r = await fetch(packUrl);
|
|
560
|
+
if (r.ok) {
|
|
561
|
+
const clip = THREE.AnimationClip.parse(await r.json());
|
|
562
|
+
clip.name = name ?? url.split('/').pop().replace('.fbx', '');
|
|
563
|
+
tick(clip.name);
|
|
564
|
+
return clip;
|
|
565
|
+
}
|
|
566
|
+
} catch (e) { /* pack miss — fall through to the cooked cache */ }
|
|
567
|
+
}
|
|
550
568
|
try {
|
|
551
569
|
const r = await fetch(`/assets/clips/${jsonName}`);
|
|
552
570
|
if (r.ok) {
|
package/src/core/retarget.js
CHANGED
|
@@ -193,7 +193,10 @@ export function buildRetargetContext(targetRoot, rigKey = null) {
|
|
|
193
193
|
// Synty rigs, where Root and Hips are coincident) used to yield posScale = 0, which
|
|
194
194
|
// multiplied every Hips.position key by ZERO: the pelvis got pinned to the root and the
|
|
195
195
|
// character sank into the ground. Only rescale when BOTH hip heights are real; else 1:1.
|
|
196
|
-
|
|
196
|
+
// BOUNDS: a metre-scale target fed cm clips has posScale ≈ 0.01 EXACTLY (fable's modular
|
|
197
|
+
// hero — the old `> 0.01` guard rejected its own legitimate ratio and the pelvis flew
|
|
198
|
+
// 87m up). 0.002 still excludes the genuine degenerate-bind zero case.
|
|
199
|
+
if (!(posScale > 0.002 && posScale < 500)) posScale = 1;
|
|
197
200
|
|
|
198
201
|
// Same bone NAMES don't guarantee the same bind POSE: the Fantasy Rivals bosses each carry a
|
|
199
202
|
// custom rest stance (bent legs, etc.) on anim-rig bone names. The clip can only be used as-is
|