@bitefoundry/retrieviewer 0.0.15 → 0.0.17
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/ASSET-PROVENANCE.md +13 -0
- package/ATTENTION-PAW.md +53 -0
- package/ATTENTION-WALL.md +58 -0
- package/ATTENTION.md +12 -1
- package/EMBEDDING.md +15 -9
- package/PUPPY-MEMORY.md +59 -0
- package/README.ko.md +7 -0
- package/README.md +8 -0
- package/RELEASING.md +34 -1
- package/integrations/stackbite/attention.mjs +20 -3
- package/package.json +19 -12
- package/pet-indexed-manifest.json +106 -0
- package/puppy-comfort-sprites.mjs +10 -4
- package/puppy-companion-comfort-q5.rvz +0 -0
- package/puppy-companion-comfort.json +818 -5
- package/puppy-companion-interactions-v3-q5.rvz +0 -0
- package/puppy-companion-life.mjs +11 -6
- package/puppy-frame-file.mjs +15 -0
- package/puppy-frame-indexed.mjs +78 -0
- package/puppy-frame-predictive.mjs +1 -1
- package/puppy-frame-store.mjs +6 -0
- package/puppy-motion-tables.generated.mjs +1 -1
- package/puppy-paper-actions-v9-q5.rvz +0 -0
- package/puppy-paper-approach-q5.rvz +0 -0
- package/puppy-paper-arrival-seat-q5.rvz +0 -0
- package/puppy-paper-behaviors-q5.rvz +0 -0
- package/puppy-paper-rear-gallop-q5.rvz +0 -0
- package/puppy-paper-seat-q5.rvz +0 -0
- package/puppy-paper.mjs +11 -3
- package/puppy-stride-tweens-q5.rvz +0 -0
- package/retrieviewer.d.mts +3 -3
- package/retrieviewer.mjs +22 -10
- package/puppy-companion-comfort-q5.bin.gz +0 -0
- package/puppy-companion-interactions-v3-q5.bin.gz +0 -0
- package/puppy-paper-actions-v9-q5.bin.gz +0 -0
- package/puppy-paper-approach-q5.bin.gz +0 -0
- package/puppy-paper-arrival-seat-q5.bin.gz +0 -0
- package/puppy-paper-behaviors-q5.bin.gz +0 -0
- package/puppy-paper-rear-gallop-q5.bin.gz +0 -0
- package/puppy-paper-seat-q5.bin.gz +0 -0
- package/puppy-stride-tweens-q5.bin.gz +0 -0
|
Binary file
|
package/puppy-companion-life.mjs
CHANGED
|
@@ -19,6 +19,7 @@ const CARRY_HEIGHT=.19,SETTLE_FALLBACK=.6,MAX_DT=.25,ARRIVE=.05;
|
|
|
19
19
|
// Active simulation seconds, never a wall-clock timer that wakes a hidden pet.
|
|
20
20
|
export const BUTTERFLY_RULES=Object.freeze({firstMin:240,firstSpread:240,cooldownMin:720,cooldownSpread:480,maxVisible:18});
|
|
21
21
|
const LABEL={
|
|
22
|
+
notifyWall:'뒷발로 서서 벽을 박박 긁는 중',
|
|
22
23
|
start:'기다리는 중',pause:'잠시 느긋하게 둘러보는 중',lie:'엎드리는 중',rest:'엎드려 쉬는 중',recover:'앉아서 기운 차리는 중',
|
|
23
24
|
sit:'앉는 중',watch:'앉아서 지켜보는 중',look:'고개를 돌려 살피는 중',observe:'가만히 주변 관찰 중',
|
|
24
25
|
stroll:'옆으로 살짝 걸어가는 중',sniff:'잠깐 멈춰 주변을 살피는 중',dash:'저 멀리 달려가는 중',far:'멀리서 둘러보는 중',home:'제자리로 돌아오는 중',nest:'쉴 자리를 찾아가는 중',
|
|
@@ -26,7 +27,7 @@ const LABEL={
|
|
|
26
27
|
belly:'배를 보이고 발라당 쉬는 중',sleep:'새근새근 잠자는 중',tug:'장난감을 물고 당기는 중',
|
|
27
28
|
butterflyNotice:'나비를 발견하고 귀를 쫑긋하는 중',butterfly:'나비를 폴짝폴짝 쫓는 중',butterflyBye:'날아가는 나비를 바라보는 중',
|
|
28
29
|
fetch:'공을 쫓아가는 중',miss:'굴러가는 공을 한 번 놓친 중',reChase:'공을 다시 쫓아가는 중',tumble:'우당탕 균형을 되찾는 중',pickup:'공을 무는 중',carry:'공을 물고 돌아오는 중',drop:'공을 내려놓는 중',offer:'공을 내려놓고 기다리는 중',
|
|
29
|
-
treatSit:'간식 앞에 앉는 중',chew:'간식 먹는 중',notifySit:'확인할 일을 발견하고 앉는 중',notifyContact:'확인할 일이 있어 사용자를 바라보는 중',notifyCome:'확인할 일을 알려주러 가까이 오는 중',notify:'확인할 일이 있는 쪽을 바라보는 중'
|
|
30
|
+
treatSit:'간식 앞에 앉는 중',chew:'간식 먹는 중',notifySit:'확인할 일을 발견하고 앉는 중',notifyContact:'확인할 일이 있어 사용자를 바라보는 중',notifyCome:'확인할 일을 알려주러 가까이 오는 중',notifyPaw:'앞발로 살살 관심을 끄는 중',notify:'확인할 일이 있는 쪽을 바라보는 중'
|
|
30
31
|
};
|
|
31
32
|
const PENDING_LABEL={treat:'곧 간식',tug:'곧 터그놀이'};
|
|
32
33
|
// Baked interaction clips, played only while holding at the shared seated endpoint.
|
|
@@ -62,7 +63,7 @@ export function createCompanionLife(actor,{seed=731,energy=.8,returnStyle='auto'
|
|
|
62
63
|
let clock=0,decisions=0,lastEpisode=null,quiet=0;
|
|
63
64
|
let queue=[],hold=0,holdIntent=null,waiting=null,gesture=null;
|
|
64
65
|
let intent='start',label=LABEL.start,pending=null,active=null,ball=null,treat=null;
|
|
65
|
-
let fetchPlan=null,notice=null;
|
|
66
|
+
let fetchPlan=null,notice=null,noticeCount=0;
|
|
66
67
|
|
|
67
68
|
const cmd=(name,args,step,when)=>({cmd:name,args,intent:step,label:LABEL[step],when});
|
|
68
69
|
const wait=(seconds,step)=>({hold:seconds,intent:step,label:LABEL[step]});
|
|
@@ -242,6 +243,7 @@ export function createCompanionLife(actor,{seed=731,energy=.8,returnStyle='auto'
|
|
|
242
243
|
queue=[sit('notifySit'),wait(.45,'notifyContact'),
|
|
243
244
|
fx(()=>{if(far())notice.phase='approaching';}),cmd('go',[HOME.x,HOME.z],'notifyCome',far),
|
|
244
245
|
sit('notifySit'),fx(()=>{notice.phase='showing';}),wait(.6,'notifyContact'),
|
|
246
|
+
...(notice.gesture==='wall'?[cmd('attentionWall',[],'notifyWall'),wait(.3,'notifyContact')]:actor.canAttentionPaw?[cmd('attentionPaw',[],'notifyPaw'),wait(.3,'notifyContact')]:[]),
|
|
245
247
|
cmd('look',[notice.side],'notify'),wait(2.5,'notify'),fx(()=>{notice=null;})];
|
|
246
248
|
}
|
|
247
249
|
// Run instant effects; stop at the first hold or issued command (at most one command per update).
|
|
@@ -318,14 +320,17 @@ export function createCompanionLife(actor,{seed=731,energy=.8,returnStyle='auto'
|
|
|
318
320
|
const approaching=notice.phase==='approaching';
|
|
319
321
|
notice=null;queue=[];hold=0;holdIntent=null;gesture=null;waiting=null;
|
|
320
322
|
intent='recover';label=LABEL.recover;
|
|
321
|
-
if(approaching)actor.attend?.();
|
|
323
|
+
if(approaching||actor.state==='attention-paw'||actor.state==='attention-wall')actor.attend?.();
|
|
322
324
|
// Let any connected head turn/sit finish naturally. No snap or new route.
|
|
323
325
|
}
|
|
324
|
-
function notify({kind,side='left'}={}){
|
|
325
|
-
if(!['approval','input'].includes(kind)||!['left','right'].includes(side))throw Error('Invalid pet notice');
|
|
326
|
+
function notify({kind,side='left',gesture='auto'}={}){
|
|
327
|
+
if(!['approval','input'].includes(kind)||!['left','right'].includes(side)||!['auto','paw','wall'].includes(gesture))throw Error('Invalid pet notice');
|
|
326
328
|
// Explicit play/feeding always wins. Notifications never queue a second pet.
|
|
327
329
|
if(active||pending||notice)return false;
|
|
328
|
-
|
|
330
|
+
if(gesture==='wall'&&!actor.canAttentionWall)return false;
|
|
331
|
+
const selected=gesture==='auto'?(actor.canAttentionWall&¬iceCount%2===1?'wall':'paw'):gesture;
|
|
332
|
+
noticeCount++;
|
|
333
|
+
notice={kind,side,gesture:selected,phase:'queued'};
|
|
329
334
|
butterfly=null;queue=[];hold=0;holdIntent=null;gesture=null;waiting=null;
|
|
330
335
|
actor.attend?.();
|
|
331
336
|
return true;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Loaded only by the default local Node host; browsers never import node:fs.
|
|
2
|
+
import {openSync,readSync,fstatSync,closeSync} from 'node:fs';
|
|
3
|
+
import {gunzipSync} from 'node:zlib';
|
|
4
|
+
import {indexedIndexLength,readIndexedIndex,createIndexedFrameStore} from './puppy-frame-indexed.mjs';
|
|
5
|
+
import {registerFrameStore} from './puppy-frame-store.mjs';
|
|
6
|
+
|
|
7
|
+
export function openFrameFile(url,options){
|
|
8
|
+
const fd=openSync(url,'r');let owned=true;
|
|
9
|
+
try{
|
|
10
|
+
const stat=fstatSync(fd);if(!stat.isFile())throw Error('Invalid frame file');
|
|
11
|
+
const read=(offset,size)=>{const out=new Uint8Array(size);let at=0;while(at<size){const n=readSync(fd,out,at,size-at,offset+at);if(!n)throw Error('Truncated frame file');at+=n;}return out;};
|
|
12
|
+
const header=read(0,20),length=indexedIndexLength(header),index=readIndexedIndex(read(0,length),stat.size);
|
|
13
|
+
const store=registerFrameStore(createIndexedFrameStore(index,{...options,read,expand:(b,n)=>gunzipSync(b,{maxOutputLength:Math.max(1,n)}),close:()=>closeSync(fd)}));owned=false;return store;
|
|
14
|
+
}finally{if(owned)closeSync(fd);}
|
|
15
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// RVZ5: the approved RVQ5 rows, independently gzip-compressed for random access.
|
|
2
|
+
// Header/map match RVQ5; each 24-byte crop record stores x,y,w,h,offset,gzipLength.
|
|
3
|
+
// Offsets are relative to the end of the index. No new quantization or resampling.
|
|
4
|
+
import {unfilterRow} from './puppy-frame-predictive.mjs';
|
|
5
|
+
const HEADER=20,RECORD=24,MAX_PIXELS=16_777_216,MAX_INDEX=64*1024*1024,MAX_EXPANDED=512*1024*1024;
|
|
6
|
+
const fail=why=>{throw Error('Invalid indexed frames: '+why);};
|
|
7
|
+
const viewOf=b=>new DataView(b.buffer,b.byteOffset,b.byteLength);
|
|
8
|
+
export function indexedIndexLength(header){
|
|
9
|
+
if(!(header instanceof Uint8Array)||header.length<HEADER||String.fromCharCode(...header.subarray(0,4))!=='RVZ5')fail('header');
|
|
10
|
+
const v=viewOf(header),width=v.getUint32(4,true),height=v.getUint32(8,true),frames=v.getUint32(12,true),unique=v.getUint32(16,true);
|
|
11
|
+
if(!width||!height||width>16384||height>16384||width*height>MAX_PIXELS||!frames||!unique||unique>frames)fail('shape');
|
|
12
|
+
const length=HEADER+4*frames+RECORD*unique;
|
|
13
|
+
if(length>MAX_INDEX)fail('index size');return length;
|
|
14
|
+
}
|
|
15
|
+
export function readIndexedIndex(bytes,fileSize=bytes.length){
|
|
16
|
+
const length=indexedIndexLength(bytes);if(bytes.length<length||!Number.isSafeInteger(fileSize)||fileSize<length)fail('truncated index');
|
|
17
|
+
const v=viewOf(bytes),width=v.getUint32(4,true),height=v.getUint32(8,true),frameCount=v.getUint32(12,true),uniqueCount=v.getUint32(16,true);
|
|
18
|
+
const map=new Uint32Array(frameCount),used=new Uint8Array(uniqueCount),rects=new Uint32Array(uniqueCount*6);let payload=0,expanded=0;
|
|
19
|
+
for(let i=0;i<frameCount;i++){const u=v.getUint32(HEADER+i*4,true);if(u>=uniqueCount)fail('map');map[i]=u;used[u]=1;}
|
|
20
|
+
if(used.includes(0))fail('unreferenced frame');
|
|
21
|
+
for(let u=0;u<uniqueCount;u++){
|
|
22
|
+
const at=HEADER+frameCount*4+u*RECORD,r=Array.from({length:6},(_,i)=>v.getUint32(at+i*4,true)),[x,y,w,h,offset,size]=r;
|
|
23
|
+
if((w===0)!==(h===0)||(!w&&(x||y))||x+w>width||y+h>height)fail('rectangle');
|
|
24
|
+
if(offset!==payload||size<20)fail('offset');payload+=size;expanded+=h*(w+1);
|
|
25
|
+
if(expanded>MAX_EXPANDED)fail('expanded size');rects.set(r,u*6);
|
|
26
|
+
}
|
|
27
|
+
if(length+payload!==fileSize)fail('file size');
|
|
28
|
+
return {width,height,frameCount,uniqueCount,map,rects,indexBytes:length,expandedBytes:expanded,fileSize};
|
|
29
|
+
}
|
|
30
|
+
const display=Uint8Array.from({length:32},(_,q)=>Math.round(q*255/31));
|
|
31
|
+
|
|
32
|
+
// The host provides bounded positional reads and a synchronous gzip decoder.
|
|
33
|
+
// Only two reconstructed frames survive; compressed art stays on disk.
|
|
34
|
+
export function createIndexedFrameStore(index,{read,expand,close=()=>{},frameIndices}={}){
|
|
35
|
+
if(typeof read!=='function'||typeof expand!=='function')fail('reader');
|
|
36
|
+
const {width,height,frameCount,uniqueCount,map,rects,indexBytes}=index,n=width*height;
|
|
37
|
+
const retained=frameIndices===undefined?null:new Uint8Array(frameCount);
|
|
38
|
+
if(retained){if(!Array.isArray(frameIndices)||!frameIndices.length)fail('retained frames');for(const i of frameIndices){if(!Number.isInteger(i)||i<0||i>=frameCount)fail('retained frame index');retained[i]=1;}}
|
|
39
|
+
const slots=[{unique:-1,frame:null},{unique:-1,frame:null}],cur=new Uint8Array(width),prev=new Uint8Array(width);
|
|
40
|
+
let closed=false,decodes=0,hits=0,diskBytes=0;
|
|
41
|
+
return Object.freeze({width,height,frameCount,uniqueCount,byteLength:n*frameCount,residentPixelBytes:0,
|
|
42
|
+
get residentBytes(){return closed?0:map.byteLength+rects.byteLength+cur.byteLength+prev.byteLength+(retained?.byteLength??0)+slots.reduce((s,e)=>s+(e.frame?.byteLength??0),0);},
|
|
43
|
+
stats(){return {decodes,hits,cachedFrames:slots.filter(s=>s.frame).length,diskReads:decodes,diskBytes,closed};},
|
|
44
|
+
getFrame(i){
|
|
45
|
+
if(closed)throw Error('Frame store is disposed');
|
|
46
|
+
if(!Number.isInteger(i)||i<0||i>=frameCount)fail('frame index');if(retained&&!retained[i])fail('frame was not retained');
|
|
47
|
+
const u=map[i];if(slots[0].unique===u){hits++;return slots[0].frame;}if(slots[1].unique===u){hits++;slots.reverse();return slots[0].frame;}
|
|
48
|
+
const k=u*6,x=rects[k],y=rects[k+1],w=rects[k+2],h=rects[k+3],offset=rects[k+4],size=rects[k+5],expected=h*(w+1);
|
|
49
|
+
const compressed=read(indexBytes+offset,size);if(!(compressed instanceof Uint8Array)||compressed.length!==size)fail('short read');
|
|
50
|
+
const rows=expand(compressed,expected);if(!(rows instanceof Uint8Array)||rows.length!==expected)fail('expanded length');
|
|
51
|
+
// Mark the evicted slot invalid before parsing: a failed decode is never a hit.
|
|
52
|
+
const slot=slots.pop();slots.unshift(slot);slot.unique=-1;const frame=slot.frame??=new Uint8Array(n);frame.fill(0);prev.fill(0);
|
|
53
|
+
for(let r=0,at=0;r<h;r++){
|
|
54
|
+
const type=rows[at++];if(type>4)fail('filter');
|
|
55
|
+
unfilterRow(type,rows,at,cur,prev,w);at+=w;
|
|
56
|
+
for(let c=0;c<w;c++){
|
|
57
|
+
const q=cur[c];if(q>31)fail('quantized value');frame[(y+r)*width+x+c]=display[q];
|
|
58
|
+
}
|
|
59
|
+
prev.set(cur.subarray(0,w));
|
|
60
|
+
}
|
|
61
|
+
slot.unique=u;decodes++;diskBytes+=size;return frame;
|
|
62
|
+
},
|
|
63
|
+
dispose(){if(closed)return;closed=true;for(const slot of slots){slot.frame=null;slot.unique=-1;}close();},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Portable/custom loaders retain the existing in-memory Q5 representation.
|
|
68
|
+
// The default local Node loader instead reads only the index and requested crops.
|
|
69
|
+
export async function expandIndexedArchive(bytes,expand){
|
|
70
|
+
const index=readIndexedIndex(bytes),{frameCount,uniqueCount,rects,indexBytes,expandedBytes}=index;
|
|
71
|
+
const out=new Uint8Array(indexBytes+expandedBytes);out.set(bytes.subarray(0,indexBytes));out.set([82,86,81,53]);const v=viewOf(out);let offset=0;
|
|
72
|
+
for(let u=0;u<uniqueCount;u++){
|
|
73
|
+
const k=u*6,size=rects[k+3]*(rects[k+2]+1),start=indexBytes+rects[k+4],rows=await expand(bytes.subarray(start,start+rects[k+5]),size);
|
|
74
|
+
if(!(rows instanceof Uint8Array)||rows.length!==size)fail('expanded length');
|
|
75
|
+
const at=HEADER+frameCount*4+u*RECORD;v.setUint32(at+16,offset,true);v.setUint32(at+20,size,true);out.set(rows,indexBytes+offset);offset+=size;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
@@ -68,7 +68,7 @@ export function encodePredictiveFrames(rvf1,{filter}={}){
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// Exact PNG inverse filter of one row into `cur` (bpp 1, integer arithmetic).
|
|
71
|
-
function unfilterRow(type,src,at,cur,prev,w){
|
|
71
|
+
export function unfilterRow(type,src,at,cur,prev,w){
|
|
72
72
|
switch(type){
|
|
73
73
|
case 0:for(let x=0;x<w;x++)cur[x]=src[at+x];return;
|
|
74
74
|
case 1:for(let x=0;x<w;x++)cur[x]=(src[at+x]+(x?cur[x-1]:0))&255;return;
|
package/puppy-frame-store.mjs
CHANGED
|
@@ -11,6 +11,12 @@ import {isPredictiveFrames,readPredictiveFrames} from './puppy-frame-predictive.
|
|
|
11
11
|
const MAGIC=[0x52,0x56,0x46,0x31],HEADER=20,RECORD=24,MAX_SIDE=16384;
|
|
12
12
|
const stores=new WeakSet();
|
|
13
13
|
|
|
14
|
+
// Indexed local files obey the same borrowed two-frame contract as memory stores.
|
|
15
|
+
export function registerFrameStore(store){
|
|
16
|
+
if(!store||typeof store.getFrame!=='function'||typeof store.stats!=='function'||!Number.isInteger(store.width)||!Number.isInteger(store.height)||!Number.isInteger(store.frameCount))throw Error('Invalid frame store');
|
|
17
|
+
stores.add(store);return store;
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
export function isPackedFrames(value){return stores.has(value);}
|
|
15
21
|
export function isGrayFrameSource(value){return value instanceof Uint8Array||stores.has(value);}
|
|
16
22
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Generated by tools/bake-pet-motion.mjs. Do not edit by hand.
|
|
2
2
|
// Source paw labels are image-space proxies, not anatomical motion capture.
|
|
3
3
|
const freeze=v=>{if(v&&typeof v==='object'){for(const x of Object.values(v))freeze(x);Object.freeze(v);}return v;};
|
|
4
|
-
export const BAKED_MOTION=freeze({"version":1,"sources":{"puppy-stride-meta.json":"30fd474f3ed9337851b2071037d88d60b37cb2bb1c12d48b28c34ebc126b7e3a","puppy-paper-rear-gallop.json":"fe9b1bf0b88f2a366f28deee6cb63964b8a94d6faa99b111524112832e80705d","puppy-paper-approach.json":"e7e02589622cecde679de79bb79c71b77494fd2fd850793c2fba9754b46aa474","puppy-paper-actions-v9.json":"38b35496c552443c7ea99beceac3cd25c670bc91836b22509b1cc97da3d0a9de","puppy-paper-behaviors.json":"67d8633bc61a2d1c46206969b9aeaaf30073fcc0f0ae7dc9954957d5522edb32","puppy-companion-comfort.json":"5234cf9566957c91ad0aa76c5dae4c9449f6c34171dcb581bf6d114b607c4a18","puppy-paper-actions-v9-q5.bin.gz":"abb4677468206c62937c0247dc4c5823e0a7c4a3a197da40194a08dd594aeef9","puppy-paper-rear-gallop-q5.bin.gz":"ca731e1979a37ec2e005a80365e3b58358f640b8b26e7036b0e931940a7b1264","puppy-companion-comfort-q5.bin.gz":"9f8c89bf4764eb2f1f17131e2413d941f1eae33ae9a15ffbe76cc33f2d18103a","puppy-paper-arrival-seat-q5.bin.gz":"7effa0a2150e8ef9ed37d5b6cb10089672e0ce32599c06db21ad4769144bf246","puppy-paper-seat-q5.bin.gz":"5480c994de0d034d70eff6ea86095f3722cf87bde72f364dd369b94b1ad66f84","puppy-paper-behaviors-q5.bin.gz":"e4b79387aca974ceec74a02dc3f02780eb53d38af6ec9ebd69994de744b39716"},"support":{"front":{"step":16,"period":128,"cyclic":true,"offsets":{"0":0,"1":16,"2":32,"3":48,"4":64,"5":80,"6":96,"7":112},"starts":{"hind-near":[123,123,123,123,123,123,123,123,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,123,123,123,123,123],"fore-far":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"fore-near":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"hind-far":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"rear":{"step":8,"period":64,"cyclic":true,"offsets":{"5":0,"6":8,"7":16,"8":24,"9":32,"10":40,"11":48,"12":56},"starts":{"hind-far":[60,60,60,60,60,60,60,60,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,60,60,60,60],"hind-near":[62,62,62,62,62,62,62,62,62,62,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,62]}},"approach":{"step":8,"period":64,"cyclic":true,"offsets":{"5":0,"6":8,"7":16,"8":24,"9":32,"10":40,"11":48,"12":56},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,39,39,39,39,39,39,-1,-1,-1,-1,-1,-1,-1,-1,-1,54,54,54,54,54,-1,-1,-1,-1,-1],"fore-right":[61,61,61,61,61,61,61,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,-1,-1,-1,-1,55,55,55,55,55,-1,61,61,61]}},"walk":{"step":8,"period":64,"cyclic":true,"offsets":{"42":0,"43":8,"44":16,"45":24,"46":32,"47":40,"48":48,"49":56},"starts":{"hind-far":[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,52,52,52,52,52,52,52,52,52,52,52,52],"hind-near":[58,58,58,58,58,58,58,58,58,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,24,24,24,24,24,24,24,24,24,24,24,24,24,24,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,58,58,58,58,58,58],"fore-far":[-1,-1,-1,3,3,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,21,21,21,21,-1,-1,-1,-1,-1,31,31,31,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,47,47,47,47,47,-1,-1,-1,-1,-1,-1,-1,59,59,59,-1,-1],"fore-near":[-1,-1,-1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,-1,-1,-1,-1,-1,-1,-1,33,-1,-1,-1,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,-1,-1]}},"behavior/walk":{"step":8,"period":32,"cyclic":true,"offsets":{"0":0,"1":8,"2":16,"3":24},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,24,24,-1,-1,-1,-1,-1,-1],"fore-right":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"behavior/walk-enter":{"step":8,"period":8,"cyclic":false,"offsets":{"4":0},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1],"fore-right":[-1,-1,-1,-1,4,4,4,4,4]}},"behavior/brake":{"step":8,"period":32,"cyclic":false,"offsets":{"5":0,"6":8,"7":16,"8":24},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,9,9,9,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,23,23,23,23,23,23,23,23,23],"fore-right":[0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"behavior/finish":{"step":8,"period":8,"cyclic":false,"offsets":{"9":0},"starts":{}},"behavior/watch-left":{"step":8,"period":16,"cyclic":false,"offsets":{"10":0,"11":8},"starts":{}},"behavior/watch-right":{"step":8,"period":16,"cyclic":false,"offsets":{"12":0,"13":8},"starts":{}},"behavior/rest":{"step":8,"period":32,"cyclic":false,"offsets":{"14":0,"15":8,"16":16,"17":24},"starts":{}}},"actionClips":{"spin":{"list":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"weights":[1.1168,0.8052,0.827,0.7936,1.3421,1.4204,0.9015,0.5275,1.1081,0.7701,0.723,1.0494,1.4422,1.3325,1.0787,0.8964,0.8655],"total":17},"roll":{"list":[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"weights":[1.122,1.4089,1.6479,0.6752,0.753,0.8756,0.9957,0.9586,0.7325,0.8218,1.0968,0.9962,0.8959,0.6589,1.0191,0.8352,0.4557,1.1818,1.1101,0.905,0.6752,1.6479,1.4089,1.122],"total":23.9999},"roll-down":{"list":[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"weights":[1.6886,0.6919,0.7717,0.8973,1.0203,0.9823,0.7506,0.8422,1.124,1.0208,0.918,0.6752,1.0443,0.8559,0.467,1.211,1.1376,0.9274,0.6919,1.6886,1.4438,1.1498],"total":22.0002},"lie-down":{"list":[17,18],"weights":[0.8866,1.1134],"total":2},"lie-up":{"list":[39,40],"weights":[1.1134,0.8866],"total":2},"walk-enter":{"list":[41],"weights":[1],"total":1},"walk":{"list":[42,43,44,45,46,47,48,49],"weights":[1,1,1,1,1,1,1,1],"total":8},"walk-exit":{"list":[50],"weights":[1],"total":1},"walk-face-front":{"list":[51],"weights":[1],"total":1},"walk-face-rear":{"list":[52],"weights":[1],"total":1},"walk-turn":{"list":[53,54,55,56,57,58,59,60,61,62,63,64,65],"weights":[1,1,1,1,1,1,1,1,1,1,1,1,1],"total":13}},"routes":{"maxPreparationSpeed":1e-8,"steps":[["ready"],["turn",true],["view-turn","rear"],["view-turn","approach"],["turn",false],["view-turn","front"],["rise"],["sit-down"]],"direction":[0,1,2,2,3,3,4,0,2,2,3,3,5,5,0,0,5,5,5,5,0,0,5,5,5,5,5,5,0,0,5,5,5,5,0,0],"action":[0,3,6,3,6,3,4,4,6,4,6,4,5,5,6,5,6,5,5,5,6,5,6,5,5,7,6,7,6,0,5,5,6,5,6,5]},"joins":{"walk-enter/walk":{"from":["puppy-paper-actions-v9",377],"to":["puppy-paper-actions-v9",378],"poseSha256":"81361614df56226b64be437f189c2e135c13498324286880db0fc06c5df3e86a","view":"front","speed":[0,0],"supportEvidence":"shared-pixels-with-labeled-walk-pose","supports":["hind-far","hind-near"],"phase":0},"walk/walk-exit":{"from":["puppy-paper-actions-v9",449],"to":["puppy-paper-actions-v9",450],"poseSha256":"81361614df56226b64be437f189c2e135c13498324286880db0fc06c5df3e86a","view":"front","speed":[0,0],"supportEvidence":"shared-pixels-with-labeled-walk-pose","supports":["hind-far","hind-near"],"phase":0},"rear-run/scramble":{"from":["puppy-paper-rear-gallop",63],"to":["puppy-companion-comfort",25],"poseSha256":"fa79a8762b57c0d5b70586a687f10e4a313e227e11e2435f6d7af0cd0866cc83","view":"rear","phase":0.25,"speed":[0,4.556913271064087],"positiveSpeed":true,"matchVelocity":true,"supports":[],"supportEvidence":"source-paw-proxies","airborne":true},"scramble/pickup-rear":{"from":["puppy-companion-comfort",36],"to":["puppy-companion-comfort",13],"poseSha256":"8192c504552a3984c80e1c3216e134605d4a930ec14cd7f778036e629e334601","view":"rear","speed":[0,0],"supports":["hind-far","hind-near"],"supportEvidence":"shared-pixels-with-labeled-rear-pose"},"carry-settle/arrival-seat":{"from":["puppy-companion-comfort",44],"to":["puppy-paper-arrival-seat",0],"poseSha256":"5ccf5acd9ca9ea81a0c9fc59d1ab2a2ddab148c942e31009f1a4c18de347fae8","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"tug/seat":{"from":["puppy-companion-comfort",0],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-90/seat":{"from":["puppy-paper-behaviors",90],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-107/seat":{"from":["puppy-paper-behaviors",107],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-108/seat":{"from":["puppy-paper-behaviors",108],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-125/seat":{"from":["puppy-paper-behaviors",125],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"}}});
|
|
4
|
+
export const BAKED_MOTION=freeze({"version":1,"sources":{"puppy-stride-meta.json":"30fd474f3ed9337851b2071037d88d60b37cb2bb1c12d48b28c34ebc126b7e3a","puppy-paper-rear-gallop.json":"fe9b1bf0b88f2a366f28deee6cb63964b8a94d6faa99b111524112832e80705d","puppy-paper-approach.json":"e7e02589622cecde679de79bb79c71b77494fd2fd850793c2fba9754b46aa474","puppy-paper-actions-v9.json":"38b35496c552443c7ea99beceac3cd25c670bc91836b22509b1cc97da3d0a9de","puppy-paper-behaviors.json":"67d8633bc61a2d1c46206969b9aeaaf30073fcc0f0ae7dc9954957d5522edb32","puppy-companion-comfort.json":"23ed137983ce5a653936a829932f41a16099378d7c0ad99b3f51a2e6091fc6bf","puppy-paper-actions-v9-q5.bin.gz":"abb4677468206c62937c0247dc4c5823e0a7c4a3a197da40194a08dd594aeef9","puppy-paper-rear-gallop-q5.bin.gz":"ca731e1979a37ec2e005a80365e3b58358f640b8b26e7036b0e931940a7b1264","puppy-companion-comfort-q5.bin.gz":"57942c55e9c467d973a08f1e23804b0f756eaed46dddfe3aba7e7c3621996236","puppy-paper-arrival-seat-q5.bin.gz":"7effa0a2150e8ef9ed37d5b6cb10089672e0ce32599c06db21ad4769144bf246","puppy-paper-seat-q5.bin.gz":"5480c994de0d034d70eff6ea86095f3722cf87bde72f364dd369b94b1ad66f84","puppy-paper-behaviors-q5.bin.gz":"e4b79387aca974ceec74a02dc3f02780eb53d38af6ec9ebd69994de744b39716"},"support":{"front":{"step":16,"period":128,"cyclic":true,"offsets":{"0":0,"1":16,"2":32,"3":48,"4":64,"5":80,"6":96,"7":112},"starts":{"hind-near":[123,123,123,123,123,123,123,123,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,123,123,123,123,123],"fore-far":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"fore-near":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"hind-far":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"rear":{"step":8,"period":64,"cyclic":true,"offsets":{"5":0,"6":8,"7":16,"8":24,"9":32,"10":40,"11":48,"12":56},"starts":{"hind-far":[60,60,60,60,60,60,60,60,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,60,60,60,60],"hind-near":[62,62,62,62,62,62,62,62,62,62,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,62]}},"approach":{"step":8,"period":64,"cyclic":true,"offsets":{"5":0,"6":8,"7":16,"8":24,"9":32,"10":40,"11":48,"12":56},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,39,39,39,39,39,39,-1,-1,-1,-1,-1,-1,-1,-1,-1,54,54,54,54,54,-1,-1,-1,-1,-1],"fore-right":[61,61,61,61,61,61,61,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,-1,-1,-1,-1,55,55,55,55,55,-1,61,61,61]}},"walk":{"step":8,"period":64,"cyclic":true,"offsets":{"42":0,"43":8,"44":16,"45":24,"46":32,"47":40,"48":48,"49":56},"starts":{"hind-far":[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,52,52,52,52,52,52,52,52,52,52,52,52],"hind-near":[58,58,58,58,58,58,58,58,58,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,24,24,24,24,24,24,24,24,24,24,24,24,24,24,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,58,58,58,58,58,58],"fore-far":[-1,-1,-1,3,3,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,21,21,21,21,-1,-1,-1,-1,-1,31,31,31,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,47,47,47,47,47,-1,-1,-1,-1,-1,-1,-1,59,59,59,-1,-1],"fore-near":[-1,-1,-1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,-1,-1,-1,-1,-1,-1,-1,33,-1,-1,-1,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,-1,-1]}},"behavior/walk":{"step":8,"period":32,"cyclic":true,"offsets":{"0":0,"1":8,"2":16,"3":24},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,24,24,-1,-1,-1,-1,-1,-1],"fore-right":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"behavior/walk-enter":{"step":8,"period":8,"cyclic":false,"offsets":{"4":0},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1],"fore-right":[-1,-1,-1,-1,4,4,4,4,4]}},"behavior/brake":{"step":8,"period":32,"cyclic":false,"offsets":{"5":0,"6":8,"7":16,"8":24},"starts":{"fore-left":[-1,-1,-1,-1,-1,-1,-1,-1,-1,9,9,9,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,23,23,23,23,23,23,23,23,23],"fore-right":[0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,15,15,15,15,15,15,15,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]}},"behavior/finish":{"step":8,"period":8,"cyclic":false,"offsets":{"9":0},"starts":{}},"behavior/watch-left":{"step":8,"period":16,"cyclic":false,"offsets":{"10":0,"11":8},"starts":{}},"behavior/watch-right":{"step":8,"period":16,"cyclic":false,"offsets":{"12":0,"13":8},"starts":{}},"behavior/rest":{"step":8,"period":32,"cyclic":false,"offsets":{"14":0,"15":8,"16":16,"17":24},"starts":{}}},"actionClips":{"spin":{"list":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"weights":[1.1168,0.8052,0.827,0.7936,1.3421,1.4204,0.9015,0.5275,1.1081,0.7701,0.723,1.0494,1.4422,1.3325,1.0787,0.8964,0.8655],"total":17},"roll":{"list":[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"weights":[1.122,1.4089,1.6479,0.6752,0.753,0.8756,0.9957,0.9586,0.7325,0.8218,1.0968,0.9962,0.8959,0.6589,1.0191,0.8352,0.4557,1.1818,1.1101,0.905,0.6752,1.6479,1.4089,1.122],"total":23.9999},"roll-down":{"list":[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"weights":[1.6886,0.6919,0.7717,0.8973,1.0203,0.9823,0.7506,0.8422,1.124,1.0208,0.918,0.6752,1.0443,0.8559,0.467,1.211,1.1376,0.9274,0.6919,1.6886,1.4438,1.1498],"total":22.0002},"lie-down":{"list":[17,18],"weights":[0.8866,1.1134],"total":2},"lie-up":{"list":[39,40],"weights":[1.1134,0.8866],"total":2},"walk-enter":{"list":[41],"weights":[1],"total":1},"walk":{"list":[42,43,44,45,46,47,48,49],"weights":[1,1,1,1,1,1,1,1],"total":8},"walk-exit":{"list":[50],"weights":[1],"total":1},"walk-face-front":{"list":[51],"weights":[1],"total":1},"walk-face-rear":{"list":[52],"weights":[1],"total":1},"walk-turn":{"list":[53,54,55,56,57,58,59,60,61,62,63,64,65],"weights":[1,1,1,1,1,1,1,1,1,1,1,1,1],"total":13}},"routes":{"maxPreparationSpeed":1e-8,"steps":[["ready"],["turn",true],["view-turn","rear"],["view-turn","approach"],["turn",false],["view-turn","front"],["rise"],["sit-down"]],"direction":[0,1,2,2,3,3,4,0,2,2,3,3,5,5,0,0,5,5,5,5,0,0,5,5,5,5,5,5,0,0,5,5,5,5,0,0],"action":[0,3,6,3,6,3,4,4,6,4,6,4,5,5,6,5,6,5,5,5,6,5,6,5,5,7,6,7,6,0,5,5,6,5,6,5]},"joins":{"walk-enter/walk":{"from":["puppy-paper-actions-v9",377],"to":["puppy-paper-actions-v9",378],"poseSha256":"81361614df56226b64be437f189c2e135c13498324286880db0fc06c5df3e86a","view":"front","speed":[0,0],"supportEvidence":"shared-pixels-with-labeled-walk-pose","supports":["hind-far","hind-near"],"phase":0},"walk/walk-exit":{"from":["puppy-paper-actions-v9",449],"to":["puppy-paper-actions-v9",450],"poseSha256":"81361614df56226b64be437f189c2e135c13498324286880db0fc06c5df3e86a","view":"front","speed":[0,0],"supportEvidence":"shared-pixels-with-labeled-walk-pose","supports":["hind-far","hind-near"],"phase":0},"rear-run/scramble":{"from":["puppy-paper-rear-gallop",63],"to":["puppy-companion-comfort",25],"poseSha256":"fa79a8762b57c0d5b70586a687f10e4a313e227e11e2435f6d7af0cd0866cc83","view":"rear","phase":0.25,"speed":[0,4.556913271064087],"positiveSpeed":true,"matchVelocity":true,"supports":[],"supportEvidence":"source-paw-proxies","airborne":true},"scramble/pickup-rear":{"from":["puppy-companion-comfort",36],"to":["puppy-companion-comfort",13],"poseSha256":"8192c504552a3984c80e1c3216e134605d4a930ec14cd7f778036e629e334601","view":"rear","speed":[0,0],"supports":["hind-far","hind-near"],"supportEvidence":"shared-pixels-with-labeled-rear-pose"},"carry-settle/arrival-seat":{"from":["puppy-companion-comfort",44],"to":["puppy-paper-arrival-seat",0],"poseSha256":"5ccf5acd9ca9ea81a0c9fc59d1ab2a2ddab148c942e31009f1a4c18de347fae8","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"tug/seat":{"from":["puppy-companion-comfort",0],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-90/seat":{"from":["puppy-paper-behaviors",90],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-107/seat":{"from":["puppy-paper-behaviors",107],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-108/seat":{"from":["puppy-paper-behaviors",108],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"},"watch-125/seat":{"from":["puppy-paper-behaviors",125],"to":["puppy-paper-seat",50],"poseSha256":"19f89a8bcb5a937e528593a8f36db846a0d45a5ee398f1b0873c056e5be2fa0a","view":"approach","speed":[0,0],"supportEvidence":"shared-pose-only"}}});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/puppy-paper.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import {createPaperAreaSampler} from './puppy-paper-area.mjs';
|
|
|
9
9
|
import {PAPER_ACTION_DURATIONS,createPaperActionSampler,paperActionPose} from './puppy-paper-actions.mjs';
|
|
10
10
|
import {createPawTransport} from './puppy-paper-paw-transport.mjs';
|
|
11
11
|
import {createCompanionSpriteSampler} from './puppy-companion-sprites.mjs';
|
|
12
|
-
import {createComfortSpriteSampler,comfortMotion,comfortMotionKey} from './puppy-comfort-sprites.mjs';
|
|
12
|
+
import {createComfortSpriteSampler,comfortMotion,comfortMotionKey,comfortProgress} from './puppy-comfort-sprites.mjs';
|
|
13
13
|
import {mouthSourceFrame,mouthAnchor,projectMouth} from './puppy-mouth-anchor.mjs';
|
|
14
14
|
import {trickClipEdges} from './puppy-paper-trick-timing.mjs';
|
|
15
15
|
|
|
@@ -70,7 +70,7 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
70
70
|
const launchSeconds=()=>snappyPreparation()?.10:.25;
|
|
71
71
|
const dispatch=(fn,{keepDown=false,urgent=false}={})=>{
|
|
72
72
|
if(urgent)preparationRate=3;
|
|
73
|
-
if(activeAction||state==='tug'||state==='scramble'||state==='pickup'||(movementMode==='walk'&&state==='run')){route=false;deferred=()=>dispatch(fn,{keepDown,urgent});hurryComfort();return true;}
|
|
73
|
+
if(activeAction||state==='tug'||state==='attention-paw'||state==='attention-wall'||state==='scramble'||state==='pickup'||(movementMode==='walk'&&state==='run')){route=false;deferred=()=>dispatch(fn,{keepDown,urgent});hurryComfort();return true;}
|
|
74
74
|
// The calibrated trick down pose has its own byte-shared recovery; never
|
|
75
75
|
// jump back into the older/larger rest illustration on another command.
|
|
76
76
|
if(manualDown&&!keepDown){route=false;deferred=fn;playAction('lie-up',()=>{manualDown=false;view='approach';seatProgress=1;seatVariant='default';enter('idle');drain();},.55);return true;}
|
|
@@ -94,6 +94,7 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
94
94
|
const t=activeAction?.timing;
|
|
95
95
|
if(t?.comfort==='belly'&&age<t.hold[1]){t.hold[1]=Math.max(t.hold[0],age);t.duration=activeAction.duration=t.hold[1]+bellyTiming.exit;}
|
|
96
96
|
else if(state==='tug'&&comfort&&!comfort.hurry){const progress=tugProgress();comfort.hurry={progress,age,length:Math.min(comfortTimings.tugExit,(1-progress)*comfort.seconds)};}
|
|
97
|
+
else if((state==='attention-paw'||state==='attention-wall')&&comfort&&!comfort.hurry){const motion=state==='attention-wall'?fetchMotions.attentionWall:fetchMotions.attentionPaw,progress=held?.comfortPose?.clip===state?held.comfortPose.progress:Math.min(1,age/comfort.seconds),from=motion.frames[comfortMotionKey(progress,motion)];comfort.hurry={from,age,length:motion.releases[from].duration};}
|
|
97
98
|
}
|
|
98
99
|
const playAction=(name,done,duration=PAPER_ACTION_DURATIONS[name])=>{const timing=trickTimings?.[name];duration=timing?.duration??duration;if(!Number.isFinite(duration)||duration<=0)throw Error('Invalid paper action duration');activeAction={name,duration,timing};actionDone=done;stop();enter('action');};
|
|
99
100
|
const finishTrick=name=>{if(name!=='spin'){view='approach';flip=false;seatProgress=1;seatVariant='default';enter('idle');}else{view='front';flip=false;seatProgress=0;enter('settle');}drain();};
|
|
@@ -143,6 +144,7 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
143
144
|
if(name==='belly'){const seconds=comfortSeconds;playAction('lie-down',()=>startBelly(seconds),.65);return;}
|
|
144
145
|
if(name==='sleep'){stayDown=false;sleepLook={...nextSleepLook};comfort={kind:'sleep',seconds:comfortSeconds};enter('recline');return;}
|
|
145
146
|
if(name==='tug'){stop();comfort={kind:'tug',seconds:comfortSeconds};enter('tug');return;}
|
|
147
|
+
if(name==='attention-paw'||name==='attention-wall'){stop();held=null;comfort={kind:name,seconds:(name==='attention-wall'?fetchMotions.attentionWall:fetchMotions.attentionPaw).duration};enter(name);return;}
|
|
146
148
|
if(name==='lie'){
|
|
147
149
|
if(manualTricks){playAction('lie-down',()=>{manualDown=true;enter('down');drain();},.65);}
|
|
148
150
|
else{stayDown=true;enter('recline');}
|
|
@@ -228,6 +230,10 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
228
230
|
belly(seconds=6){comfortDuration('belly',seconds);return dispatch(()=>{comfortSeconds=seconds;return requestAction('belly');},{keepDown:true});},
|
|
229
231
|
sleep(seconds=25,variant='side',right=false){comfortDuration('sleep',seconds);if(!['side','belly','curl','chin'].includes(variant)||typeof right!=='boolean')throw Error('Invalid sleep pose');return dispatch(()=>{comfortSeconds=seconds;nextSleepLook={variant,right};return requestAction('sleep');});},
|
|
230
232
|
tug(seconds=6){comfortDuration('tug',seconds);return dispatch(()=>{comfortSeconds=seconds;return requestAction('tug');});},
|
|
233
|
+
attentionPaw(){if(!fetchMotions?.attentionPaw)return false;return dispatch(()=>requestAction('attention-paw'));},
|
|
234
|
+
get canAttentionPaw(){return !!fetchMotions?.attentionPaw;},
|
|
235
|
+
attentionWall(){if(!fetchMotions?.attentionWall)return false;return dispatch(()=>requestAction('attention-wall'));},
|
|
236
|
+
get canAttentionWall(){return !!fetchMotions?.attentionWall;},
|
|
231
237
|
get canScramble(){return scrambleSeconds>0;},
|
|
232
238
|
get canMovingScramble(){return !!fetchMotions;},
|
|
233
239
|
get canSinglePassScramble(){return fetchMotions?.scramble.trajectory==='single-pass-target';},
|
|
@@ -292,6 +298,7 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
292
298
|
else if(state==='recline'){const end=stayDown?.25:1;restProgress=Math.min(end,restProgress+dt/1.8);if(restProgress===end)enter(stayDown?'down':comfort?.kind==='sleep'?'sleep':'nap');}
|
|
293
299
|
else if(state==='sleep'&&age>=comfort.seconds){comfort=null;enter('wake');}
|
|
294
300
|
else if(state==='tug'&&tugProgress()>=1){comfort=null;enter('idle');drain();}
|
|
301
|
+
else if((state==='attention-paw'||state==='attention-wall')&&(comfort.hurry?age-comfort.hurry.age>=comfort.hurry.length:age>=comfort.seconds)){comfort=null;enter('idle');drain();}
|
|
295
302
|
else if((state==='scramble'||state==='pickup')&&age>=comfort.seconds){comfort=null;movingScramble=null;stop();enter('idle');drain();}
|
|
296
303
|
else if(state==='nap'&&age>=5&&!stayDown){enter('wake');}
|
|
297
304
|
else if(state==='wake'){restProgress=Math.max(0,restProgress-prepareDt/1.2);if(restProgress===0){if(pendingAction)prepareDirection();else if(target)enter('rise');else enter('idle');}}
|
|
@@ -304,6 +311,7 @@ export function createPaperActor(animal,info,{manualTricks=false,trickTimings=nu
|
|
|
304
311
|
let seat=state==='sit-down'||state==='rise'||seatProgress>0?Math.round(seatProgress*48)/48:null;
|
|
305
312
|
if(restProgress===0&&state!=='recline')sleepLook=null;
|
|
306
313
|
let behavior=null,behaviorProgress=0,comfortPose=state==='scramble'?{clip:'scramble',view,progress:Math.min(1,age/comfort.seconds)}:state==='pickup'?{clip:'pickup',view,progress:Math.min(1,age/comfort.seconds)}:state==='tug'?{clip:'tug',progress:tugProgress()}:sleepLook&&restProgress>.72?{clip:'sleep',...sleepLook,blend:comfortEase((restProgress-.72)/.28)}:null;
|
|
314
|
+
if(state==='attention-paw'||state==='attention-wall')comfortPose={clip:state,progress:Math.min(1,age/comfort.seconds),...comfort.hurry?{release:{from:comfort.hurry.from,progress:Math.min(1,(age-comfort.hurry.age)/comfort.hurry.length)}}:{}};
|
|
307
315
|
if(activeAction?.comfort)kind=activeAction.comfort;
|
|
308
316
|
let actionName=activeAction?.name??(state==='run'&&movementMode==='walk'?'walk':null),actionProgress=activeAction?(activeAction.timing?activeAction.timing.progressAt(age):Math.min(1,age/activeAction.duration)):phase;
|
|
309
317
|
if(manualDown&&state==='down'){actionName='lie-down';actionProgress=1;}
|
|
@@ -386,7 +394,7 @@ export function createPaperRenderer(cache,info,meta,width,height,{rear,approach,
|
|
|
386
394
|
// Quantize source lookup only, never the projected rectangle. Rounding side,
|
|
387
395
|
// left and top first introduced whole-body scale/position jumps at thresholds.
|
|
388
396
|
const motion=isComfort?comfortMotion(state.comfortPose,comfort.info):null;
|
|
389
|
-
const left=width*x-sideX/2,floor=motion?(motion.floorOffsets?.[comfortMotionKey(state.comfortPose
|
|
397
|
+
const left=width*x-sideX/2,floor=motion?(motion.floorOffsets?.[comfortMotionKey(comfortProgress(state.comfortPose),motion)]??motion.floorOffset??0):isInteraction||isAction||isBehavior||isSeat||isRear||isApproach?0:cleanGroundOffset(state,renderMeta),top=height*y-(300-floor)/320*side;
|
|
390
398
|
let feet=[];
|
|
391
399
|
if(contactEnabled&&isComfort&&state.comfortPose.clip==='carry-trot'){
|
|
392
400
|
const k=comfortMotionKey(state.comfortPose.progress,motion);
|
|
Binary file
|
package/retrieviewer.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** A headless pet: the host owns input, time and terminal rendering. */
|
|
2
2
|
export type FetchReturnStyle = 'auto' | 'brake' | 'trot' | 'run-trot';
|
|
3
3
|
export interface PetOptions {
|
|
4
|
-
/**
|
|
4
|
+
/** Relative names; return unchanged .rvz/.gz file bytes. Custom loaders use memory-backed art. */
|
|
5
5
|
loadAsset?: (name: string) => Promise<ArrayBuffer | ArrayBufferView>;
|
|
6
6
|
seed?: number;
|
|
7
7
|
energy?: number;
|
|
@@ -41,7 +41,7 @@ export interface PetState {
|
|
|
41
41
|
}
|
|
42
42
|
export interface LifeReport {
|
|
43
43
|
/** Metadata-triggered visual cue only. No host input or approval authority. */
|
|
44
|
-
attention: {kind: 'approval' | 'input'; side: 'left' | 'right'; phase: 'queued' | 'approaching' | 'showing'} | null;
|
|
44
|
+
attention: {kind: 'approval' | 'input'; side: 'left' | 'right'; gesture: 'paw' | 'wall'; phase: 'queued' | 'approaching' | 'showing'} | null;
|
|
45
45
|
/** Last selected autonomous episode; null before the first decision. */
|
|
46
46
|
episode: string | null;
|
|
47
47
|
intent: string;
|
|
@@ -96,7 +96,7 @@ export interface Pet {
|
|
|
96
96
|
/** False when busy or cooling down. */
|
|
97
97
|
interact(kind: 'ball' | 'treat' | 'tug'): boolean;
|
|
98
98
|
/** False during direct play/feeding or another cue. Does not operate the host. */
|
|
99
|
-
notify(notice: {kind: 'approval' | 'input'; side?: 'left' | 'right'}): boolean;
|
|
99
|
+
notify(notice: {kind: 'approval' | 'input'; side?: 'left' | 'right'; gesture?: 'auto' | 'paw' | 'wall'}): boolean;
|
|
100
100
|
/** Cancel the cue, preserving any in-progress connected pose recovery. */
|
|
101
101
|
clearNotice(): void;
|
|
102
102
|
/** Sets the next throw's return style. Does not interrupt a fetch in progress. */
|
package/retrieviewer.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import {createSnappyTrickTimings} from './puppy-paper-trick-timing.mjs';
|
|
|
5
5
|
import {createCompanionLife,FETCH_RETURN_STYLES} from './puppy-companion-life.mjs';
|
|
6
6
|
import {paintCompanionObjects} from './puppy-companion-objects.mjs';
|
|
7
7
|
import {readPackedFrames} from './puppy-frame-store.mjs';
|
|
8
|
+
import {expandIndexedArchive} from './puppy-frame-indexed.mjs';
|
|
8
9
|
import {BAKED_MOTION} from './puppy-motion-tables.generated.mjs';
|
|
9
10
|
|
|
10
11
|
// Embeddable autonomous puppy. Importing or creating has no DOM, timer, stdin/stdout
|
|
@@ -19,12 +20,12 @@ export const ART_PROFILES=Object.freeze(['original','q5']);
|
|
|
19
20
|
export const PET_ASSETS=Object.freeze({
|
|
20
21
|
// Kept as a legacy identifier only; createPet/getPetAssetFiles no longer load it.
|
|
21
22
|
animal:'locomotion-puppy.animal',
|
|
22
|
-
stride:'puppy-stride-tweens-q5.
|
|
23
|
+
stride:'puppy-stride-tweens-q5.rvz',strideInfo:'puppy-stride-meta.json',stableInfo:'puppy-stable-meta.json',
|
|
23
24
|
rear:'puppy-paper-rear-gallop',approach:'puppy-paper-approach',seat:'puppy-paper-seat',arrivalSeat:'puppy-paper-arrival-seat',
|
|
24
25
|
behaviors:'puppy-paper-behaviors',actions:'puppy-paper-actions-v9',interactions:'puppy-companion-interactions-v3',comfort:'puppy-companion-comfort',
|
|
25
26
|
});
|
|
26
27
|
const BUNDLES=['rear','approach','seat','arrivalSeat','behaviors','actions','interactions','comfort'];
|
|
27
|
-
const frameFile=(base,profile)=>base+(profile==='q5'?'-q5.
|
|
28
|
+
const frameFile=(base,profile)=>base+(profile==='q5'?'-q5.rvz':'-compact.bin.gz');
|
|
28
29
|
/** Exact files a host/bundler must copy, including metadata. Never loads assets. */
|
|
29
30
|
export function getPetAssetFiles(artProfile=DEFAULT_ART_PROFILE){
|
|
30
31
|
if(!ART_PROFILES.includes(artProfile))throw RangeError('artProfile must be original or q5');
|
|
@@ -50,9 +51,9 @@ const bytesOf=(name,value)=>{
|
|
|
50
51
|
if(ArrayBuffer.isView(value))return new Uint8Array(value.buffer,value.byteOffset,value.byteLength);
|
|
51
52
|
throw TypeError(`loadAsset(${name}) must return an ArrayBuffer or typed bytes`);
|
|
52
53
|
};
|
|
53
|
-
async function gunzip(bytes){
|
|
54
|
+
async function gunzip(bytes,size){
|
|
54
55
|
// Native Node gzip avoids Blob/Response/stream copies of every large cache.
|
|
55
|
-
if(typeof process!=='undefined'&&process.versions?.node){const {gunzipSync}=await import('node:zlib');return gunzipSync(bytes);}
|
|
56
|
+
if(typeof process!=='undefined'&&process.versions?.node){const {gunzipSync}=await import('node:zlib');return gunzipSync(bytes,size===undefined?undefined:{maxOutputLength:Math.max(1,size)});}
|
|
56
57
|
if(typeof DecompressionStream!=='undefined')return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream('gzip'))).arrayBuffer());
|
|
57
58
|
throw Error('This browser needs DecompressionStream for pet assets');
|
|
58
59
|
}
|
|
@@ -75,8 +76,8 @@ function heldFrameKey(state,report,{columns,rows,cellAspect=.5,camera,poseFps=24
|
|
|
75
76
|
report.ball,report.treat]);
|
|
76
77
|
}
|
|
77
78
|
async function loadPetAssets(loadAsset,artProfile){
|
|
78
|
-
// Node
|
|
79
|
-
//
|
|
79
|
+
// Default local Node hosts keep art on disk and reconstruct two frames per
|
|
80
|
+
// family. Custom/browser loaders retain the compatible memory-backed store.
|
|
80
81
|
let codec;
|
|
81
82
|
if(typeof process!=='undefined'&&process.versions?.node){
|
|
82
83
|
const {deflateRawSync,inflateRawSync}=await import('node:zlib');
|
|
@@ -86,9 +87,18 @@ async function loadPetAssets(loadAsset,artProfile){
|
|
|
86
87
|
}
|
|
87
88
|
const load=async name=>bytesOf(name,await loadAsset(name));
|
|
88
89
|
const json=async name=>JSON.parse(new TextDecoder().decode(await load(name)));
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
let openFrameFile;
|
|
91
|
+
if(artProfile==='q5'&&loadAsset===defaultLoadAsset&&new URL('.',import.meta.url).protocol==='file:'&&typeof process!=='undefined'&&process.versions?.node)({openFrameFile}=await import('./puppy-frame-file.mjs'));
|
|
92
|
+
const frames=async (name,options)=>{
|
|
93
|
+
if(name.endsWith('.rvz')){
|
|
94
|
+
if(openFrameFile)return openFrameFile(new URL(name,import.meta.url),options);
|
|
95
|
+
return readPackedFrames(await expandIndexedArchive(await load(name),gunzip),{...options,codec});
|
|
96
|
+
}
|
|
97
|
+
return readPackedFrames(await gunzip(await load(name)),{...options,codec});
|
|
98
|
+
};
|
|
99
|
+
// Read small indices locally; expand portable archives one family at a time.
|
|
91
100
|
const data={assets:{}};
|
|
101
|
+
try{
|
|
92
102
|
data.info=await json(PET_ASSETS.strideInfo);data.meta=await json(PET_ASSETS.stableInfo);
|
|
93
103
|
data.cache=await frames(frameFile('puppy-stride-tweens',artProfile));
|
|
94
104
|
for(const key of BUNDLES){
|
|
@@ -100,15 +110,17 @@ async function loadPetAssets(loadAsset,artProfile){
|
|
|
100
110
|
data.assets[key]={info,bytes:await frames(frameFile(base,artProfile),options)};
|
|
101
111
|
}
|
|
102
112
|
return data;
|
|
113
|
+
}catch(error){disposeAssets(data);throw error;}
|
|
103
114
|
}
|
|
115
|
+
function disposeAssets(data){data?.cache?.dispose?.();for(const family of Object.values(data?.assets??{}))family.bytes?.dispose?.();}
|
|
104
116
|
async function acquireAssets(loadAsset,artProfile){
|
|
105
117
|
let entry;
|
|
106
118
|
if(loadAsset===defaultLoadAsset){entry=sharedAssets.get(artProfile);if(!entry){entry={users:0,promise:loadPetAssets(loadAsset,artProfile)};sharedAssets.set(artProfile,entry);}}
|
|
107
119
|
else entry={users:0,promise:loadPetAssets(loadAsset,artProfile)};
|
|
108
120
|
entry.users++;
|
|
109
121
|
let released=false;
|
|
110
|
-
const release=()=>{if(released)return;released=true;const previous=entry;entry=null;if(--previous.users===0
|
|
111
|
-
try{
|
|
122
|
+
const release=()=>{if(released)return;released=true;const previous=entry;entry=null;if(--previous.users===0){if(sharedAssets.get(artProfile)===previous)sharedAssets.delete(artProfile);disposeAssets(previous.data);}};
|
|
123
|
+
try{const data=await entry.promise;entry.data=data;return{data,release};}catch(error){release();throw error;}
|
|
112
124
|
}
|
|
113
125
|
|
|
114
126
|
export async function createPet({loadAsset=defaultLoadAsset,seed,energy,pawTransport=true,artProfile=DEFAULT_ART_PROFILE,returnStyle='auto'}={}){
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|