@bitefoundry/retrieviewer 0.0.11 → 0.0.13
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/INSTALLING.md +25 -0
- package/MOTION-TABLES.md +63 -0
- package/RELEASING.md +45 -1
- package/integrations/windows-overlay/Overlay.cs +14 -4
- package/integrations/windows-overlay/desktop.mjs +9 -3
- package/integrations/windows-overlay/worker.mjs +18 -10
- package/package.json +8 -3
- package/puppy-companion-interactions-v3.json +1 -1
- package/puppy-motion-lookup.mjs +20 -0
- package/puppy-motion-tables.generated.mjs +4 -0
- package/puppy-paper-actions-v9.json +1 -1
- package/puppy-paper-actions.mjs +5 -4
- package/puppy-paper-approach.json +1 -1
- package/puppy-paper-arrival-seat.json +1 -1
- package/puppy-paper-behaviors.json +1 -1
- package/puppy-paper-contact.mjs +10 -0
- package/puppy-paper-rear-gallop.json +1 -1
- package/puppy-paper-seat.json +14 -14
- package/puppy-paper.mjs +30 -16
- package/puppy-stable-meta.json +1606 -1606
- package/puppy-stride-meta.json +343 -343
- package/retrieviewer-config.mjs +14 -3
- package/retrieviewer-plugin.d.mts +1 -1
- package/retrieviewer-plugin.mjs +1 -1
- package/retrieviewer.mjs +6 -2
package/INSTALLING.md
CHANGED
|
@@ -99,6 +99,31 @@ Inside OpenCode, `/retrieviewer enable`, `/retrieviewer disable`,
|
|
|
99
99
|
`/retrieviewer ball`, `/retrieviewer treat`, `/retrieviewer status` control the native
|
|
100
100
|
pet. The adapter owns no raw keyboard or stdout; the host owns drawing and layout.
|
|
101
101
|
|
|
102
|
+
## Recovering an interrupted settings change
|
|
103
|
+
|
|
104
|
+
Settings writes use an exclusive `settings.lock`. New locks record the owning
|
|
105
|
+
PID, hostname, start time and a random token. A busy error prints the exact lock
|
|
106
|
+
path and PID when known. An old or empty lock may have no owner information.
|
|
107
|
+
Locks are deliberately **not** deleted just because they are old or a PID probe
|
|
108
|
+
fails: a long operation, PID reuse or a shared directory can make that unsafe.
|
|
109
|
+
|
|
110
|
+
If an operation crashed:
|
|
111
|
+
|
|
112
|
+
1. Stop all Retrieviewer enable/disable/disconnect commands and close all host
|
|
113
|
+
agents that can change its settings. If the directory is shared, stop writers
|
|
114
|
+
on every machine. Inspect the exact lock named in the error; an active owner
|
|
115
|
+
must finish first. Do not kill an unrelated process just because its PID matches.
|
|
116
|
+
2. With **all writers stopped**, move only that `settings.lock` aside in the same
|
|
117
|
+
directory (for example to `settings.lock.recovered`). Keep it as a backup;
|
|
118
|
+
do not overwrite an existing backup, touch `settings.json`, remove the whole
|
|
119
|
+
directory, or follow a symlink. Then retry the original command. A fresh lock
|
|
120
|
+
is acquired normally and the existing settings are preserved.
|
|
121
|
+
|
|
122
|
+
Default directory: `%USERPROFILE%\.config\retrieviewer` on Windows,
|
|
123
|
+
`~/.config/retrieviewer` on macOS/Linux. `RETRIEVIEWER_HOME` overrides it, so use
|
|
124
|
+
the path in the error rather than assuming the default. This is an **offline
|
|
125
|
+
manual recovery**, not a command to remove a live lock or automatic stale reaping.
|
|
126
|
+
|
|
102
127
|
## Evidence, not a misleading green check
|
|
103
128
|
|
|
104
129
|
Registration means the config contains our plugin URL. A runtime receipt means
|
package/MOTION-TABLES.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Precomputed motion tables (0.0.12)
|
|
2
|
+
|
|
3
|
+
`npm run bake:motion` compiles the current approved sources into
|
|
4
|
+
`puppy-motion-tables.generated.mjs`. It does not change a picture, camera,
|
|
5
|
+
trajectory, animation duration or source metadata. `npm run check:motion` checks
|
|
6
|
+
the exact deterministic output without writing. Tests and the publication guard
|
|
7
|
+
reject stale output after source metadata or witnessed art changes.
|
|
8
|
+
|
|
9
|
+
## What is precomputed
|
|
10
|
+
|
|
11
|
+
- Source support episodes, including continuous stance across a cycle seam and
|
|
12
|
+
a complete swing skipped between rendered frames. No stance-history discovery
|
|
13
|
+
occurs while building a default renderer, including after a resize.
|
|
14
|
+
- Clip lists, weights and totals used for action-pose addressing. The runtime no
|
|
15
|
+
longer validates/rebuilds these same lists and totals for each default pose.
|
|
16
|
+
- A dense table of72 facing/seat preparation cases, sharing8 step descriptors.
|
|
17
|
+
Lookup requires a stationary root; it does not insert a turn at running speed.
|
|
18
|
+
- Ten exact-pixel connection witnesses with view, speed and (where applicable)
|
|
19
|
+
gait-phase/velocity-match requirements. These cover walk entry/exit, rear run
|
|
20
|
+
into the authored impact, impact into rear pickup, carry-gather into arrival
|
|
21
|
+
seat, tug into the canonical seat, and four watch endpoints into that seat.
|
|
22
|
+
- SHA256 of every input metadata/art file used by the bake. JSON text is hashed
|
|
23
|
+
with LF line endings; binary artwork is hashed byte-for-byte. Generated text
|
|
24
|
+
checks also accept CRLF checkouts. No source images,
|
|
25
|
+
source hashes or graph search are computed by the running pet.
|
|
26
|
+
|
|
27
|
+
The generated routes preserve the existing approved preparation order. This is
|
|
28
|
+
a bounded compilation of existing paths, not unrestricted motion matching or a
|
|
29
|
+
new animation blend engine. Other actor-specific recovery rules stay in place.
|
|
30
|
+
Unregistered arbitrary-phase joins are not certified: in particular an urgently
|
|
31
|
+
interrupted walk may use its existing recovery rather than a proven phase0 join.
|
|
32
|
+
|
|
33
|
+
## What remains dynamic
|
|
34
|
+
|
|
35
|
+
World displacement, actual velocity, unwrapped gait phase, perspective and the
|
|
36
|
+
small paw-to-world anchor correction still depend on live state. Those cannot
|
|
37
|
+
be baked as fixed screen coordinates while allowing free travel and resizing.
|
|
38
|
+
Support tables address the original source coordinates; they do not stretch the
|
|
39
|
+
head/torso, replace drawings or cause a camera orbit.
|
|
40
|
+
|
|
41
|
+
Paw labels are visible image-space proxies, not anatomical motion capture. Some
|
|
42
|
+
resting endpoints have exact-pose evidence but no individually labeled paws.
|
|
43
|
+
The authored run-to-impact entry is **airborne**, not a planted-paw handoff:
|
|
44
|
+
its gate requires the correct phase, positive speed and matched velocity.
|
|
45
|
+
Neither exact pixels nor a green numerical test proves general animal realism.
|
|
46
|
+
|
|
47
|
+
## Compatibility and resource scope
|
|
48
|
+
|
|
49
|
+
The bundled Q5/default-loader path uses the compiled tables. Optional original
|
|
50
|
+
art and custom loaders retain the general metadata-driven implementation instead
|
|
51
|
+
of accidentally applying the bundled pet's bake to unrelated art. The general
|
|
52
|
+
helpers remain available for authoring and equivalence tests.
|
|
53
|
+
|
|
54
|
+
The generated module is about11KB source, shared between instances; there is no
|
|
55
|
+
extra image cache, dependency, timer, worker or asset-fetch round trip. It removes
|
|
56
|
+
repeat discovery/allocation work, not the roughly20MB retained image payload or
|
|
57
|
+
Node/native process baseline. It is not a large-RAM-reduction claim.
|
|
58
|
+
|
|
59
|
+
Verification compares every baked support sample and wrap, all action-addressing
|
|
60
|
+
boundaries, both actor paths through seeded fetches and rare impacts, and the
|
|
61
|
+
public renderer's text, contacts and mouth anchors. Use
|
|
62
|
+
`node --test puppy-motion-tables.test.mjs`. The owner authorized publication of
|
|
63
|
+
this work as0.0.12 on2026-10-24. Earlier published artifacts remain unchanged.
|
package/RELEASING.md
CHANGED
|
@@ -1,4 +1,48 @@
|
|
|
1
|
-
# Retrieviewer 0.0.
|
|
1
|
+
# Retrieviewer 0.0.13 release process
|
|
2
|
+
|
|
3
|
+
Current target: `@bitefoundry/retrieviewer@0.0.13`, public `latest`.
|
|
4
|
+
The owner authorized npm publication and website deployment on2026-10-24.
|
|
5
|
+
This release contains the reviewed reliability fixes, with unchanged art/motion:
|
|
6
|
+
|
|
7
|
+
- Canonical LF text/hash checks and CRLF regression coverage; binary art stays
|
|
8
|
+
byte-for-byte unchanged. Git attributes and existing JSON text use LF.
|
|
9
|
+
- Exclusive settings locks record the owner PID/host/time/token. Busy errors
|
|
10
|
+
identify the lock and link to the offline manual recovery in INSTALLING.md.
|
|
11
|
+
There is no automatic removal of possibly live locks.
|
|
12
|
+
- Workers require ready plus an acknowledged detach to survive launcher loss.
|
|
13
|
+
Startup disconnect/launcher-death tests cover worker, painter and session cleanup.
|
|
14
|
+
- Oversized Windows grids hide until they fit again; plugin timer delays cannot
|
|
15
|
+
overflow Node's signed32-bit timeout bound into a1ms loop.
|
|
16
|
+
- Windows20 / Linux22 Node CI on push and PR, including installed-consumer checks
|
|
17
|
+
and an owned Windows native diagnostic. Website copy discloses page visit and
|
|
18
|
+
performance analytics separately from the desktop pet.
|
|
19
|
+
|
|
20
|
+
Build and install a fresh exact tarball outside the source tree, compare installed
|
|
21
|
+
bytes and test its native/browser runtimes. Publish that same artifact after the
|
|
22
|
+
new remote CI succeeds; verify registry integrity and matching Pages runtime.
|
|
23
|
+
No new runtime dependency, process, background timer or art cache. No claim of
|
|
24
|
+
new macOS/Linux GUI certification or a material RAM reduction. Preserve all
|
|
25
|
+
earlier npm artifacts, MIT code / CC BY-SA4.0 art and the user's running pet.
|
|
26
|
+
|
|
27
|
+
## Previous 0.0.12 scope (historical)
|
|
28
|
+
|
|
29
|
+
Current target: `@bitefoundry/retrieviewer@0.0.12`, public `latest`.
|
|
30
|
+
On2026-10-24 the owner authorized npm publication and website deployment of the
|
|
31
|
+
reviewed precomputed motion tables. Support episodes, action addressing and
|
|
32
|
+
bounded preparation routes are compiled offline; live travel, perspective and
|
|
33
|
+
paw correction remain dynamic. Default Q5 uses the tables; custom loaders and
|
|
34
|
+
optional original art retain their metadata-driven path. See MOTION-TABLES.md.
|
|
35
|
+
No new artwork, runtime dependency, process or timer. This removes repeated
|
|
36
|
+
CPU/allocation work, not the retained image payload or Node/native baseline.
|
|
37
|
+
Do not claim a large RAM reduction or new Linux/macOS live GUI certification.
|
|
38
|
+
|
|
39
|
+
Build and verify a fresh exact0.0.12 tarball outside the source tree, including
|
|
40
|
+
its owned Windows native lifecycle and bilingual browser runtime. Publish that
|
|
41
|
+
same tarball, verify registry integrity and matching GitHub Pages runtime bytes.
|
|
42
|
+
Do not restart the user's live pet or change host/agent configuration. Earlier
|
|
43
|
+
npm artifacts remain immutable; MIT code / CC BY-SA4.0 artwork stay unchanged.
|
|
44
|
+
|
|
45
|
+
## Previous 0.0.11 scope (historical)
|
|
2
46
|
|
|
3
47
|
Current target: `@bitefoundry/retrieviewer@0.0.11`, public `latest`.
|
|
4
48
|
On2026-10-24 the owner accepted the reviewed candidate and authorized immediate
|
|
@@ -168,8 +168,10 @@ sealed class Companion : ApplicationContext {
|
|
|
168
168
|
if(target!=null&&!Native.IsIconic(target.Window)&&Native.IsWindowVisible(target.Window)){
|
|
169
169
|
next=Native.ClientBounds(target.Window);IntPtr foreground=Native.GetForegroundWindow();show=!picking&&(testMode||foreground==target.Window||foreground==bar.Handle)&&next.Width>=160&&next.Height>=120;
|
|
170
170
|
}
|
|
171
|
-
int nextCell=
|
|
172
|
-
|
|
171
|
+
int nextCell=Program.GridCell(next.Width,next.Height);
|
|
172
|
+
// A huge target may exceed the transport budget even at the largest cell.
|
|
173
|
+
// Hide until its size fits again; never send an invalid visible grid.
|
|
174
|
+
if(nextCell==0){show=false;nextCell=16;}
|
|
173
175
|
int columns=next.Width/nextCell,rows=next.Height/(nextCell*2);
|
|
174
176
|
if(force||show!=visible||next!=canvas||nextCell!=cell){
|
|
175
177
|
visible=show;canvas=next;cell=nextCell;revision++;pet.Hide();
|
|
@@ -237,6 +239,13 @@ static class Program {
|
|
|
237
239
|
using(Companion context=new Companion(single,ipcTest))Application.Run(context);return 0;
|
|
238
240
|
}catch(Exception error){Emit(new {type="error",message=error.Message});return 1;}
|
|
239
241
|
}
|
|
242
|
+
internal static int GridCell(int width,int height){
|
|
243
|
+
foreach(int size in new int[]{8,10,12,16}){
|
|
244
|
+
long columns=(long)width/size,rows=(long)height/(size*2);
|
|
245
|
+
if(columns>0&&rows>0&&columns*rows<=125000)return size;
|
|
246
|
+
}
|
|
247
|
+
return 0;
|
|
248
|
+
}
|
|
240
249
|
static int SelfTest(string proof){
|
|
241
250
|
// Uses only our own off-screen windows. Does NOT click/type in or capture a user application.
|
|
242
251
|
IntPtr foreground=Native.GetForegroundWindow();
|
|
@@ -253,8 +262,9 @@ static class Program {
|
|
|
253
262
|
Native.ShowWindow(target.Handle,7);Application.DoEvents();bool minimized=Native.IsIconic(target.Handle);pet.Hide();bool hidden=!pet.Visible;
|
|
254
263
|
Native.ShowWindow(target.Handle,4);Application.DoEvents();bool restored=!Native.IsIconic(target.Handle);
|
|
255
264
|
bool focus=Native.GetForegroundWindow()==foreground;
|
|
256
|
-
bool
|
|
257
|
-
|
|
265
|
+
bool gridBounds=GridCell(3840,2160)==8&&GridCell(7680,4320)==12&&GridCell(32000,18000)==0&&GridCell(int.MaxValue,int.MaxValue)==0&&GridCell(0,0)==0;
|
|
266
|
+
bool passed=clickThrough&&noActivate&&layered&&follows&&minimized&&hidden&&restored&&focus&&pet.PaintedDots>0&&gridBounds;
|
|
267
|
+
Emit(new {type="self-test",passed=passed,gridBounds=gridBounds,clickThroughStyle=clickThrough,noActivateStyle=noActivate,layered=layered,followGeometry=follows,expectedX=expectedX,expectedY=expectedY,actualX=actual.Left,actualY=actual.Top,minimize=minimized,hide=hidden,restore=restored,foregroundPreserved=focus,dots=pet.PaintedDots,proof=proof});return passed?0:1;
|
|
258
268
|
}
|
|
259
269
|
}
|
|
260
270
|
}
|
|
@@ -102,9 +102,15 @@ export async function startDesktop(options={}){
|
|
|
102
102
|
const helper=await desktopHelper(options);
|
|
103
103
|
return new Promise((resolve,reject)=>{
|
|
104
104
|
const child=spawn(process.execPath,[fileURLToPath(new URL('./worker.mjs',import.meta.url)),'--helper-spec',JSON.stringify(helper)],{detached:true,windowsHide:true,stdio:['ignore','ignore','ignore','ipc'],env:{...process.env,RETRIEVIEWER_HOME:getConfigPaths(options).root,RETRIEVIEWER_INK:ink,RETRIEVIEWER_RETURN_STYLE:returnStyle}});
|
|
105
|
-
let settled=false;const finish=(error,message)=>{if(settled)return;settled=true;clearTimeout(timer);if(child.connected)child.disconnect();child.unref();error?reject(error):resolve(message);};
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
let settled=false,ready=null;const finish=(error,message)=>{if(settled)return;settled=true;clearTimeout(timer);if(child.connected)child.disconnect();child.unref();error?reject(error):resolve(message);};
|
|
106
|
+
// Disconnect on failure aborts startup. Only an acknowledged detach may live on.
|
|
107
|
+
const timer=setTimeout(()=>finish(Error('Desktop startup timed out; no agent settings changed')),20000);
|
|
108
|
+
child.on('error',error=>finish(error));child.on('message',message=>{
|
|
109
|
+
if(settled)return;
|
|
110
|
+
if(message?.error)return finish(Error(message.error));
|
|
111
|
+
if(message?.detached===true&&ready)return finish(null,ready);
|
|
112
|
+
if(message?.running===true&&!ready){ready=message;child.send({command:'detach'},error=>{if(error)finish(error);});}
|
|
113
|
+
});child.on('disconnect',()=>{if(!settled)finish(Error('Desktop disconnected during startup'));});child.on('exit',code=>finish(Error('Desktop exited during startup ('+code+')')));
|
|
108
114
|
});
|
|
109
115
|
}
|
|
110
116
|
export async function cleanDesktop(options={}){
|
|
@@ -9,25 +9,32 @@ import {createFramePump} from './protocol.mjs';
|
|
|
9
9
|
import {controlAddress,parseHelperSpec} from '../desktop/platform.mjs';
|
|
10
10
|
|
|
11
11
|
let helper,pump,timer,server,session,paths,owned=false,stopping=false,frames=0,paintedFrames=0,visible=false,selected=false,pickerVisible=false,pendingViewport=null,lastInteraction=null;
|
|
12
|
-
let nativeError=null;
|
|
12
|
+
let nativeError=null,ready=false,detached=false;
|
|
13
13
|
const returnStyle=process.env.RETRIEVIEWER_RETURN_STYLE??'auto';
|
|
14
14
|
let nativeStderr='';
|
|
15
|
-
const sendParent=message=>{if(process.connected)process.send(message);};
|
|
15
|
+
const sendParent=message=>{if(process.connected)try{process.send(message,error=>{if(error&&!detached)stop();});}catch{if(!detached)stop();}};
|
|
16
|
+
const starting=()=>{if(stopping||(!process.connected&&!detached))throw Error('Desktop launcher closed during startup');};
|
|
16
17
|
async function stop(){
|
|
17
|
-
|
|
18
|
+
const first=!stopping;stopping=true;clearInterval(timer);pump?.dispose();
|
|
18
19
|
if(helper&&!helper.killed){try{helper.stdin.end(JSON.stringify({type:'quit'})+'\n');}catch{}}
|
|
19
|
-
if(server)server.close();
|
|
20
|
+
if(server?.listening)server.close();
|
|
20
21
|
if(owned)try{const current=JSON.parse(await readFile(paths.session,'utf8'));if(current.token===session.token)await unlink(paths.session);}catch{}
|
|
21
22
|
// A wedged painter is our own child only, never the selected terminal.
|
|
22
|
-
const watchdog=setTimeout(()=>{helper?.kill();process.exit(0);},2500);watchdog.unref();
|
|
23
|
+
if(first){const watchdog=setTimeout(()=>{helper?.kill();process.exit(0);},2500);watchdog.unref();}
|
|
23
24
|
if(!helper||helper.exitCode!==null)process.exitCode=0;
|
|
24
25
|
}
|
|
25
|
-
process.on('SIGTERM',stop);process.on('SIGINT',stop);
|
|
26
|
+
process.on('SIGTERM',stop);process.on('SIGINT',stop);
|
|
27
|
+
process.on('disconnect',()=>{if(!detached)stop();});
|
|
28
|
+
process.on('message',m=>{
|
|
29
|
+
if(m?.command==='abort')stop();
|
|
30
|
+
else if(m?.command==='detach'&&ready&&!stopping){detached=true;sendParent({detached:true});}
|
|
31
|
+
});
|
|
26
32
|
try{
|
|
33
|
+
starting();
|
|
27
34
|
const spec=parseHelperSpec(process.argv.slice(2));
|
|
28
|
-
paths=await prepareRoot();await noLink(paths.session);
|
|
35
|
+
paths=await prepareRoot();await noLink(paths.session);starting();
|
|
29
36
|
session={owner:'bitefoundry-retrieviewer-overlay-v1',pid:process.pid,pipe:controlAddress({uuid:randomUUID()}),token:randomBytes(32).toString('hex')};
|
|
30
|
-
const record=await open(paths.session,'wx',0o600);owned=true;try{await record.writeFile(JSON.stringify(session)+'\n');}finally{await record.close();}
|
|
37
|
+
const record=await open(paths.session,'wx',0o600);owned=true;try{await record.writeFile(JSON.stringify(session)+'\n');}finally{await record.close();}starting();
|
|
31
38
|
server=createServer(socket=>{
|
|
32
39
|
socket.setTimeout(1500,()=>socket.destroy());let body='';
|
|
33
40
|
socket.on('error',()=>{});socket.on('data',bytes=>{
|
|
@@ -40,6 +47,7 @@ try{
|
|
|
40
47
|
});
|
|
41
48
|
await new Promise((resolve,reject)=>{server.once('error',reject);server.listen(session.pipe,resolve);});
|
|
42
49
|
if(process.platform!=='win32')await chmod(session.pipe,0o600);
|
|
50
|
+
starting();
|
|
43
51
|
// GUI-subsystem exe: no console to hide. SW_HIDE here also hides its first UI.
|
|
44
52
|
helper=spawn(spec.command,spec.args,{windowsHide:false,stdio:['pipe','pipe','pipe']});
|
|
45
53
|
helper.stdin.on('error',()=>stop());helper.stderr.setEncoding('utf8');helper.stderr.on('data',s=>{nativeStderr=(nativeStderr+s).slice(-4096);});helper.once('error',error=>{sendParent({error:error.message});stop();});
|
|
@@ -49,7 +57,7 @@ try{
|
|
|
49
57
|
reader.on('line',line=>{
|
|
50
58
|
if(line.length>100000)return stop();let m;try{m=JSON.parse(line);}catch{return stop();}
|
|
51
59
|
try{
|
|
52
|
-
if(m.type==='ready'){pickerVisible=m.pickerVisible===true;sendParent({running:true,windowPicker:pickerVisible,mode:spec.mode,returnStyle,pid:process.pid});}
|
|
60
|
+
if(m.type==='ready'&&!stopping){ready=true;pickerVisible=m.pickerVisible===true;sendParent({running:true,windowPicker:pickerVisible,mode:spec.mode,returnStyle,pid:process.pid});}
|
|
53
61
|
else if(m.type==='error'){nativeError=String(m.message??'Desktop painter failed');sendParent({error:nativeError});stop();}
|
|
54
62
|
else if(m.type==='picker')pickerVisible=m.visible===true;
|
|
55
63
|
else if(m.type==='viewport'){pendingViewport=m;visible=m.visible;selected=m.selected===true;pump?.viewport(m);}
|
|
@@ -59,7 +67,7 @@ try{
|
|
|
59
67
|
else if(m.type==='quit')stop();
|
|
60
68
|
}catch(error){write({type:'error',message:error.message});stop();}
|
|
61
69
|
});
|
|
62
|
-
const {createPet}=await import('../../retrieviewer.mjs');const pet=await createPet({returnStyle});
|
|
70
|
+
starting();const {createPet}=await import('../../retrieviewer.mjs');starting();const pet=await createPet({returnStyle});
|
|
63
71
|
if(stopping)pet.dispose();else{
|
|
64
72
|
pump=createFramePump({pet,send:write});if(pendingViewport)pump.viewport(pendingViewport);
|
|
65
73
|
write({type:'loaded',ink:process.env.RETRIEVIEWER_INK??'cream'});timer=setInterval(()=>{try{pump.tick();}catch(error){write({type:'error',message:error.message});stop();}},1000/spec.fps);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitefoundry/retrieviewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "A fluffy Braille desktop pet for Windows and Linux X11, with experimental macOS support and an embeddable TUI engine.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://bitefoundry.github.io/retrieviewer/",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"PUPPY-Q5-COMPARISON.md",
|
|
91
91
|
"COMFORT-ART.md",
|
|
92
92
|
"WATCH-REDRAW.md",
|
|
93
|
+
"MOTION-TABLES.md",
|
|
93
94
|
"BUTTERFLY.md",
|
|
94
95
|
"examples/embed.mjs",
|
|
95
96
|
"examples/live.mjs",
|
|
@@ -102,6 +103,8 @@
|
|
|
102
103
|
"puppy-paper.mjs",
|
|
103
104
|
"puppy-paper-world.mjs",
|
|
104
105
|
"puppy-paper-contact.mjs",
|
|
106
|
+
"puppy-motion-lookup.mjs",
|
|
107
|
+
"puppy-motion-tables.generated.mjs",
|
|
105
108
|
"puppy-paper-seat.mjs",
|
|
106
109
|
"puppy-paper-director.mjs",
|
|
107
110
|
"puppy-paper-behaviors.mjs",
|
|
@@ -144,13 +147,15 @@
|
|
|
144
147
|
"vendor/procedural-animals/LICENSE"
|
|
145
148
|
],
|
|
146
149
|
"scripts": {
|
|
150
|
+
"bake:motion": "node tools/bake-pet-motion.mjs",
|
|
151
|
+
"check:motion": "node tools/bake-pet-motion.mjs --check",
|
|
147
152
|
"start": "node tools/preview-site.mjs",
|
|
148
153
|
"build:site": "node tools/build-site.mjs",
|
|
149
154
|
"pet:companion": "node examples/live.mjs",
|
|
150
155
|
"pet:desktop": "node retrieviewer-cli.mjs desktop",
|
|
151
|
-
"test": "node --test
|
|
156
|
+
"test": "node --test",
|
|
152
157
|
"test:package": "node check-pet-package.mjs",
|
|
153
|
-
"release:check": "node tools/check-release.mjs",
|
|
158
|
+
"release:check": "npm run check:motion && node tools/check-release.mjs",
|
|
154
159
|
"prepublishOnly": "npm run release:check"
|
|
155
160
|
},
|
|
156
161
|
"dependencies": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"width":320,"height":320,"samples":9,"pairs":40,"bytes":36864000,"sha256":"8438ee6cfc52b28f8e327bf37453c8e5ad7d568b2569cd4c5ed1e051d7026905","clips":{"treat-eat":[30,31,32,33,34,35,36,37,38,39],"ball-pickup":[13,14,15,16,17,18,19,20,21,22],"ball-drop":[23,24,25,26,27,28,29]},"edges":[[0,2],[2,3],[3,4],[4,5],[5,4],[5,6],[6,0],[0,7],[7,8],[8,9],[9,10],[10,11],[11,0],[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,10],[10,11],[11,12],[12,13],[13,14],[14,15],[15,16],[16,0]],"ballSourceKeys":{"13":[0,1],"14":[1,2],"15":[2,3],"16":[3,4],"17":[4,5],"18":[5,6],"19":[6,7],"20":[7,8],"21":[8,9],"22":[9,10],"23":[10,11],"24":[11,12],"25":[12,13],"26":[13,14],"27":[14,15],"28":[15,16],"29":[16,0]},"sourceSequences":{"ball-pickup":[0,1,2,3,4,5,6,7,8,9,10],"ball-drop":[10,11,12,13,14,15,16,0]},"scale":0.7870722433460076,"registration":[{"cell":0,"matrix":[[0.7870722433460076,0.0,13.04942965779469],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":1,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":2,"matrix":[[0.7870722433460076,0.0,-475.32889733840295],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":3,"matrix":[[0.7870722433460076,0.0,-718.5342205323193],[0.0,0.7870722433460076,74.89733840304183]]},{"cell":4,"matrix":[[0.7870722433460076,0.0,10.688212927756666],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":5,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":6,"matrix":[[0.7870722433460076,0.0,-476.115969581749],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":7,"matrix":[[0.7870722433460076,0.0,-718.9277566539923],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":8,"matrix":[[0.7870722433460076,0.0,12.655893536121681],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":9,"matrix":[[0.7870722433460076,0.0,-231.7300380228137],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":10,"matrix":[[0.7870722433460076,0.0,-474.93536121673003],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":11,"matrix":[[0.7870722433460076,0.0,-718.5342205323193],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":12,"matrix":[[0.7870722433460076,0.0,12.262357414448672],[0.0,0.7870722433460076,-647.6349809885932]]},{"cell":13,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,-646.8479087452471]]},{"cell":14,"matrix":[[0.7870722433460076,0.0,-474.14828897338396],[0.0,0.7870722433460076,-647.6349809885932]]},{"cell":15,"matrix":[[0.7870722433460076,0.0,-718.9277566539923],[0.0,0.7870722433460076,-647.6349809885932]]}],"neutralSha256":"0b0584bd032ddf41d62f02c5064547d667e84eea9b8a74e3ff2d7043abb5eb78","sourceHashes":{"puppy-companion-interactions-v2.bin.gz":"75d682c0eaab31dd01038f36fd6da425eaee6cb92afc8857e06e3013e3307724","puppy-interactions12-v1-sheet.png":"e3931afbd935355734f9448f12495edb269547cadba30dcd36265ea9e4cf7afd","puppy-paper-seat.bin.gz":"a863225bef502fa3d60fe97c85007a9e85b818d53e5c3b5490fddd80b0c100d9","prepare-companion-interactions-v3.py":"d0d195683d2869f9bf5a94e8c8195d00cb5caf3caa4099c49cc20e384592da73"},"method":"v2 ball sprites byte-exact; treat is full original generated sprite, one source scale, no head/torso mask and no ghost-frame morph","treatSourceKeys":{"30":[0,1],"31":[1,2],"32":[2,3],"33":[3,4],"34":[4,5],"35":[5,4],"36":[4,5],"37":[5,6],"38":[6,1],"39":[1,0]},"treatKeyHashes":["0b0584bd032ddf41d62f02c5064547d667e84eea9b8a74e3ff2d7043abb5eb78","0870c83bbd95da39680c4297fb2a7c08fafb296578f7e872de31ace3736e303d","fe95b5930e429cb1e42ca5c6c06e500c4c30446164ece075fd580d85f8a014e0","2533e5d855f56867c2d0650da1644a175e414145c03a29e43281996094e14e67","a75805e1a40004160a07275db03cc74310950bb8200ca6ca71566706e6a8d776","51b81c3433ba2ee74127a39386bf725d654c72bffbf6cfcbe475107cf1d13cdb","d11f159c000b2e432a77dd3d922d7f51435db5f2a9799f55290d3dedc9c88636"],"treatScale":0.6124260355029586,"treatRegistration":[{"cell":0,"matrix":[[0.6124260355029586,0.0,36.39497041420118],[0.0,0.6124260355029586,57.47928994082841]]},{"cell":1,"matrix":[[0.6124260355029586,0.0,-149.47633136094674],[0.0,0.6124260355029586,56.25443786982248]]},{"cell":2,"matrix":[[0.6124260355029586,0.0,-335.3476331360947],[0.0,0.6124260355029586,56.86686390532543]]},{"cell":3,"matrix":[[0.6124260355029586,0.0,-521.8313609467456],[0.0,0.6124260355029586,56.25443786982248]]},{"cell":4,"matrix":[[0.6124260355029586,0.0,37.00739644970413],[0.0,0.6124260355029586,-181.36686390532543]]},{"cell":5,"matrix":[[0.6124260355029586,0.0,-148.8639053254438],[0.0,0.6124260355029586,-181.36686390532543]]}]}
|
|
1
|
+
{"version":3,"width":320,"height":320,"samples":9,"pairs":40,"bytes":36864000,"sha256":"8438ee6cfc52b28f8e327bf37453c8e5ad7d568b2569cd4c5ed1e051d7026905","clips":{"treat-eat":[30,31,32,33,34,35,36,37,38,39],"ball-pickup":[13,14,15,16,17,18,19,20,21,22],"ball-drop":[23,24,25,26,27,28,29]},"edges":[[0,2],[2,3],[3,4],[4,5],[5,4],[5,6],[6,0],[0,7],[7,8],[8,9],[9,10],[10,11],[11,0],[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,10],[10,11],[11,12],[12,13],[13,14],[14,15],[15,16],[16,0]],"ballSourceKeys":{"13":[0,1],"14":[1,2],"15":[2,3],"16":[3,4],"17":[4,5],"18":[5,6],"19":[6,7],"20":[7,8],"21":[8,9],"22":[9,10],"23":[10,11],"24":[11,12],"25":[12,13],"26":[13,14],"27":[14,15],"28":[15,16],"29":[16,0]},"sourceSequences":{"ball-pickup":[0,1,2,3,4,5,6,7,8,9,10],"ball-drop":[10,11,12,13,14,15,16,0]},"scale":0.7870722433460076,"registration":[{"cell":0,"matrix":[[0.7870722433460076,0.0,13.04942965779469],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":1,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":2,"matrix":[[0.7870722433460076,0.0,-475.32889733840295],[0.0,0.7870722433460076,75.68441064638785]]},{"cell":3,"matrix":[[0.7870722433460076,0.0,-718.5342205323193],[0.0,0.7870722433460076,74.89733840304183]]},{"cell":4,"matrix":[[0.7870722433460076,0.0,10.688212927756666],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":5,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":6,"matrix":[[0.7870722433460076,0.0,-476.115969581749],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":7,"matrix":[[0.7870722433460076,0.0,-718.9277566539923],[0.0,0.7870722433460076,-162.01140684410643]]},{"cell":8,"matrix":[[0.7870722433460076,0.0,12.655893536121681],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":9,"matrix":[[0.7870722433460076,0.0,-231.7300380228137],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":10,"matrix":[[0.7870722433460076,0.0,-474.93536121673003],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":11,"matrix":[[0.7870722433460076,0.0,-718.5342205323193],[0.0,0.7870722433460076,-407.57794676806077]]},{"cell":12,"matrix":[[0.7870722433460076,0.0,12.262357414448672],[0.0,0.7870722433460076,-647.6349809885932]]},{"cell":13,"matrix":[[0.7870722433460076,0.0,-232.12357414448667],[0.0,0.7870722433460076,-646.8479087452471]]},{"cell":14,"matrix":[[0.7870722433460076,0.0,-474.14828897338396],[0.0,0.7870722433460076,-647.6349809885932]]},{"cell":15,"matrix":[[0.7870722433460076,0.0,-718.9277566539923],[0.0,0.7870722433460076,-647.6349809885932]]}],"neutralSha256":"0b0584bd032ddf41d62f02c5064547d667e84eea9b8a74e3ff2d7043abb5eb78","sourceHashes":{"puppy-companion-interactions-v2.bin.gz":"75d682c0eaab31dd01038f36fd6da425eaee6cb92afc8857e06e3013e3307724","puppy-interactions12-v1-sheet.png":"e3931afbd935355734f9448f12495edb269547cadba30dcd36265ea9e4cf7afd","puppy-paper-seat.bin.gz":"a863225bef502fa3d60fe97c85007a9e85b818d53e5c3b5490fddd80b0c100d9","prepare-companion-interactions-v3.py":"d0d195683d2869f9bf5a94e8c8195d00cb5caf3caa4099c49cc20e384592da73"},"method":"v2 ball sprites byte-exact; treat is full original generated sprite, one source scale, no head/torso mask and no ghost-frame morph","treatSourceKeys":{"30":[0,1],"31":[1,2],"32":[2,3],"33":[3,4],"34":[4,5],"35":[5,4],"36":[4,5],"37":[5,6],"38":[6,1],"39":[1,0]},"treatKeyHashes":["0b0584bd032ddf41d62f02c5064547d667e84eea9b8a74e3ff2d7043abb5eb78","0870c83bbd95da39680c4297fb2a7c08fafb296578f7e872de31ace3736e303d","fe95b5930e429cb1e42ca5c6c06e500c4c30446164ece075fd580d85f8a014e0","2533e5d855f56867c2d0650da1644a175e414145c03a29e43281996094e14e67","a75805e1a40004160a07275db03cc74310950bb8200ca6ca71566706e6a8d776","51b81c3433ba2ee74127a39386bf725d654c72bffbf6cfcbe475107cf1d13cdb","d11f159c000b2e432a77dd3d922d7f51435db5f2a9799f55290d3dedc9c88636"],"treatScale":0.6124260355029586,"treatRegistration":[{"cell":0,"matrix":[[0.6124260355029586,0.0,36.39497041420118],[0.0,0.6124260355029586,57.47928994082841]]},{"cell":1,"matrix":[[0.6124260355029586,0.0,-149.47633136094674],[0.0,0.6124260355029586,56.25443786982248]]},{"cell":2,"matrix":[[0.6124260355029586,0.0,-335.3476331360947],[0.0,0.6124260355029586,56.86686390532543]]},{"cell":3,"matrix":[[0.6124260355029586,0.0,-521.8313609467456],[0.0,0.6124260355029586,56.25443786982248]]},{"cell":4,"matrix":[[0.6124260355029586,0.0,37.00739644970413],[0.0,0.6124260355029586,-181.36686390532543]]},{"cell":5,"matrix":[[0.6124260355029586,0.0,-148.8639053254438],[0.0,0.6124260355029586,-181.36686390532543]]}]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Pure lookups over offline data. No source analysis, graph search or I/O here.
|
|
2
|
+
const views=Object.freeze({front:0,rear:1,approach:2});
|
|
3
|
+
export function preparationRoute(tables,kind,{view,flip,seatProgress=0,desired,nextFlip=false,speed=0}){
|
|
4
|
+
if(!Number.isFinite(speed)||Math.abs(speed)>tables.routes.maxPreparationSpeed)throw Error('Motion preparation requires a stopped root');
|
|
5
|
+
const viewIndex=views[view],seat=seatProgress===0?0:seatProgress===1?2:1;
|
|
6
|
+
const target=kind==='action'?(desired==='stand'?0:desired==='seat'?1:undefined):views[desired];
|
|
7
|
+
if(viewIndex===undefined||target===undefined||typeof flip!=='boolean'||typeof nextFlip!=='boolean')throw Error('Unknown baked motion route');
|
|
8
|
+
const index=kind==='action'?((viewIndex*2+ +flip)*3+seat)*2+target:((viewIndex*2+ +flip)*3+target)*2+ +nextFlip;
|
|
9
|
+
const code=tables.routes[kind]?.[index],route=tables.routes.steps[code];if(!route)throw Error('Unknown baked motion route');
|
|
10
|
+
return route;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function canJoinMotion(tables,name,{view,speed,phase=0,nextSpeed=speed}){
|
|
14
|
+
const join=tables.joins[name],epsilon=1e-7;
|
|
15
|
+
if(!join||join.view!==view||![speed,phase,nextSpeed].every(Number.isFinite))return false;
|
|
16
|
+
if(speed<join.speed[0]-epsilon||speed>join.speed[1]+epsilon||nextSpeed<join.speed[0]-epsilon||nextSpeed>join.speed[1]+epsilon||join.positiveSpeed&&(speed<=0||nextSpeed<=0))return false;
|
|
17
|
+
if(join.phase!==undefined){const d=phase-join.phase;if(Math.abs(d-Math.round(d))>epsilon)return false;}
|
|
18
|
+
if(join.matchVelocity&&Math.abs(speed-nextSpeed)>epsilon)return false;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Generated by tools/bake-pet-motion.mjs. Do not edit by hand.
|
|
2
|
+
// Source paw labels are image-space proxies, not anatomical motion capture.
|
|
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"}}});
|