{"_id":"@blcklab/anyo-animation","_rev":"4-7a6c7202d6295d47c65b8c8172c8bee9","name":"@blcklab/anyo-animation","dist-tags":{"latest":"0.1.4"},"versions":{"0.1.1":{"name":"@blcklab/anyo-animation","version":"0.1.1","keywords":["anyo","animation","3d","gltf","glb","sekai64","state-machine","spatial-web"],"author":{"name":"blcklab"},"license":"MIT","_id":"@blcklab/anyo-animation@0.1.1","maintainers":[{"name":"okarin_lab","email":"avelurs.billy@gmail.com"}],"homepage":"https://github.com/blcklab/anyo-animation#readme","bugs":{"url":"https://github.com/blcklab/anyo-animation/issues"},"dist":{"shasum":"61298451cee2afe468ec7a7359b066360b9bac62","tarball":"https://registry.npmjs.org/@blcklab/anyo-animation/-/anyo-animation-0.1.1.tgz","fileCount":77,"integrity":"sha512-hyhZx/HAYjSaG9AnG6ZIVSmn49YvccahlodqkskZzyl7bRuOj3F+1WY2j2cQL6A1VwXI/RJo6J4cWFMlgdJx3A==","signatures":[{"sig":"MEUCIQCqQ5ZNwcIGQUawymQvYSpDU1VTSSD0KE4BOcPllcbzeQIgZhm7TqjRlCocHVH3zqyK4KVz3QIuhAgEYud9U2aKanE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@blcklab%2fanyo-animation@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":342844},"main":"./dist/cjs/index.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./sekai64":{"types":"./dist/types/sekai64/index.d.ts","import":"./dist/esm/sekai64/index.js"},"./authoring":{"types":"./dist/types/authoring/index.d.ts","import":"./dist/esm/authoring/index.js","require":"./dist/cjs/authoring/index.js"},"./package.json":"./package.json"},"gitHead":"ed03a9b0ee35b9a905bec31c580b6e4ed64bf121","scripts":{"size":"node scripts/size.mjs","test":"npm run build && node --test tests/*.test.mjs","build":"node scripts/build.mjs","check":"npm run typecheck && npm run typecheck:examples && npm run test && npm run verify:boundaries && npm run verify:package && npm run verify:stable && npm run size && npm run test:consumer","clean":"node scripts/clean.mjs","typecheck":"npm run generate:version && tsc -p tsconfig.check.json --noEmit --pretty false","test:consumer":"node scripts/test-packed-consumer.mjs","verify:stable":"node scripts/verify-stable.mjs","prepublishOnly":"npm run check","verify:package":"node scripts/verify-package.mjs","generate:version":"node scripts/generate-version.mjs","verify:boundaries":"node scripts/verify-boundaries.mjs","typecheck:examples":"tsc -p tsconfig.examples.json --pretty false"},"_npmUser":{"name":"okarin_lab","email":"avelurs.billy@gmail.com"},"repository":{"url":"git+https://github.com/blcklab/anyo-animation.git","type":"git"},"_npmVersion":"10.9.8","description":"Optional renderer-neutral animation runtime for Anyo with parameters, state machines, events, root motion, authoring contracts, and an explicit Sekai64 adapter.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@blcklab/anyo":"0.10.0-rc.1","@blcklab/sekai64":"0.8.0-rc.33"},"peerDependencies":{"@blcklab/anyo":">=0.9.1-0 <0.10.0 || >=0.10.0-0 <1.0.0","@blcklab/sekai64":">=0.8.0-0 <0.9.0"},"peerDependenciesMeta":{"@blcklab/sekai64":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/anyo-animation_0.1.1_1789160372010_0.9232292100854818","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@blcklab/anyo-animation","version":"0.1.2","keywords":["anyo","animation","3d","gltf","glb","sekai64","state-machine","spatial-web"],"author":{"name":"blcklab"},"license":"MIT","_id":"@blcklab/anyo-animation@0.1.2","maintainers":[{"name":"okarin_lab","email":"avelurs.billy@gmail.com"}],"homepage":"https://github.com/blcklab/anyo-animation#readme","bugs":{"url":"https://github.com/blcklab/anyo-animation/issues"},"dist":{"shasum":"e7c3ccc239d72af1a8c89b65a15daff7acc031e3","tarball":"https://registry.npmjs.org/@blcklab/anyo-animation/-/anyo-animation-0.1.2.tgz","fileCount":77,"integrity":"sha512-2SQjnoxY/HivkIGeyhX27WRc6npDcnBEeblrj9i702amc3pS1eLnRlT6C6t9WJtBAUENtZBFPfgB8uOaCT9bDg==","signatures":[{"sig":"MEUCIQCVEawn50KPXxHs6F9PSm8uMdK8DNwUtM0AakD16w9I3wIgaQVbK4Y2kJzb/tQ7vQSYwBfvd7Li2HDvj3ZZiOftmI8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@blcklab%2fanyo-animation@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":351984},"main":"./dist/cjs/index.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./sekai64":{"types":"./dist/types/sekai64/index.d.ts","import":"./dist/esm/sekai64/index.js"},"./authoring":{"types":"./dist/types/authoring/index.d.ts","import":"./dist/esm/authoring/index.js","require":"./dist/cjs/authoring/index.js"},"./package.json":"./package.json"},"gitHead":"1587f1df735f3d39dbcb770510e1b49b807efa5a","scripts":{"size":"node scripts/size.mjs","test":"npm run build && node --test tests/*.test.mjs","build":"node scripts/build.mjs","check":"npm run typecheck && npm run typecheck:examples && npm run test && npm run verify:boundaries && npm run verify:package && npm run verify:stable && npm run size && npm run test:consumer","clean":"node scripts/clean.mjs","typecheck":"npm run generate:version && tsc -p tsconfig.check.json --noEmit --pretty false","test:consumer":"node scripts/test-packed-consumer.mjs","verify:stable":"node scripts/verify-stable.mjs","prepublishOnly":"npm run check","verify:package":"node scripts/verify-package.mjs","generate:version":"node scripts/generate-version.mjs","verify:boundaries":"node scripts/verify-boundaries.mjs","typecheck:examples":"tsc -p tsconfig.examples.json --pretty false"},"_npmUser":{"name":"okarin_lab","email":"avelurs.billy@gmail.com"},"repository":{"url":"git+https://github.com/blcklab/anyo-animation.git","type":"git"},"_npmVersion":"10.9.8","description":"Optional renderer-neutral animation runtime for Anyo with parameters, state machines, events, root motion, authoring contracts, and an explicit Sekai64 adapter.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@blcklab/anyo":"0.10.0-rc.1","@blcklab/sekai64":"0.8.0-rc.33"},"peerDependencies":{"@blcklab/anyo":">=0.9.1-0 <0.10.0 || >=0.10.0-0 <1.0.0","@blcklab/sekai64":">=0.8.0-0 <0.9.0"},"peerDependenciesMeta":{"@blcklab/sekai64":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/anyo-animation_0.1.2_1789370056934_0.7842391322998117","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@blcklab/anyo-animation","version":"0.1.3","keywords":["anyo","animation","3d","gltf","glb","sekai64","state-machine","spatial-web"],"author":{"name":"blcklab"},"license":"MIT","_id":"@blcklab/anyo-animation@0.1.3","maintainers":[{"name":"okarin_lab","email":"avelurs.billy@gmail.com"}],"homepage":"https://github.com/blcklab/anyo-animation#readme","bugs":{"url":"https://github.com/blcklab/anyo-animation/issues"},"dist":{"shasum":"76bc1c4fc46211a1d349267021da867cbce14167","tarball":"https://registry.npmjs.org/@blcklab/anyo-animation/-/anyo-animation-0.1.3.tgz","fileCount":85,"integrity":"sha512-V6B8nhVX9CxaJIAwm5OeJ0gA7wBq3GyKfn/hWr7aEEi4+K3b3fMoyS2C9EZqKL20t1FvBhe///wmsMMfJL1I5w==","signatures":[{"sig":"MEUCIBUfy1ku9ZxKkJP5ZkknokK+vmOLCcZIRcZF9gs8BTVKAiEA4kWy6PeABZ2UJTevA3pMl3ytnWYH0cUB+2oz3X0ldkM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCuHzyQVDzh4HDTlTRSvHoWwCW801CoFfUOgQFFPfGULwIgFl2nueNmdYPfIDD4rVTeDOcMgiXwQfpL8AXd4YGMXL8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@blcklab%2fanyo-animation@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":411542},"main":"./dist/cjs/index.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./sekai64":{"types":"./dist/types/sekai64/index.d.ts","import":"./dist/esm/sekai64/index.js"},"./authoring":{"types":"./dist/types/authoring/index.d.ts","import":"./dist/esm/authoring/index.js","require":"./dist/cjs/authoring/index.js"},"./package.json":"./package.json"},"gitHead":"d77781de6e318f147b8e540155ecb079ef47da2a","scripts":{"size":"node scripts/size.mjs","test":"npm run build && node --test tests/*.test.mjs","build":"node scripts/build.mjs","check":"npm run typecheck && npm run typecheck:examples && npm run test && npm run verify:boundaries && npm run verify:package && npm run verify:stable && npm run size && npm run test:consumer","clean":"node scripts/clean.mjs","typecheck":"npm run generate:version && tsc -p tsconfig.check.json --noEmit --pretty false","test:consumer":"node scripts/test-packed-consumer.mjs","verify:stable":"node scripts/verify-stable.mjs","prepublishOnly":"npm run check","verify:package":"node scripts/verify-package.mjs","generate:version":"node scripts/generate-version.mjs","verify:boundaries":"node scripts/verify-boundaries.mjs","typecheck:examples":"tsc -p tsconfig.examples.json --pretty false"},"_npmUser":{"name":"okarin_lab","email":"avelurs.billy@gmail.com"},"repository":{"url":"git+https://github.com/blcklab/anyo-animation.git","type":"git"},"_npmVersion":"10.9.8","description":"Optional renderer-neutral animation runtime for Anyo with parameters, state machines, events, root motion, authoring contracts, and an explicit Sekai64 adapter.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@blcklab/anyo":"0.10.0-rc.3","@blcklab/sekai64":"0.8.0-rc.34"},"peerDependencies":{"@blcklab/anyo":">=0.9.1-0 <0.10.0 || >=0.10.0-0 <1.0.0","@blcklab/sekai64":">=0.8.0-0 <0.9.0"},"peerDependenciesMeta":{"@blcklab/sekai64":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/anyo-animation_0.1.3_1790200661723_0.5380472776921457","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"_id":"@blcklab/anyo-animation@0.1.4","bugs":{"url":"https://github.com/blcklab/anyo-animation/issues"},"dist":{"shasum":"42d055047fedc8a4461783fab5c889e84660616d","tarball":"https://registry.npmjs.org/@blcklab/anyo-animation/-/anyo-animation-0.1.4.tgz","fileCount":85,"integrity":"sha512-mD/pF5QT3A8s2KgDJPanY6Zi+jDITXopv8qOM9fTQtkMdyvE2QBU2V1S1uCXLPkOx8xDWJwTDxQGbL67lTGXFA==","signatures":[{"sig":"MEUCIH3+rBWi2E3VjunIdjy19ZQ+jrqcH2sAs37RzWlBI2uvAiEAwhL/x6VsHcPjE7suT9YeIC7GzI1ncH2uiPSF0E25DDw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC0rGuCFriTVkHkm3XwlXnzy//vzFoEfgMVxYCsULk+HQIgbQpUBa+DI71eyf96y44jcFPoliYzC8IjRKOZmR2PrpQ="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@blcklab%2fanyo-animation@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":411846},"main":"./dist/cjs/index.js","name":"@blcklab/anyo-animation","type":"module","types":"./dist/types/index.d.ts","author":{"name":"blcklab"},"module":"./dist/esm/index.js","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./sekai64":{"types":"./dist/types/sekai64/index.d.ts","import":"./dist/esm/sekai64/index.js"},"./authoring":{"types":"./dist/types/authoring/index.d.ts","import":"./dist/esm/authoring/index.js","require":"./dist/cjs/authoring/index.js"},"./package.json":"./package.json"},"gitHead":"3f2b321601f5d68b681dc2b2d5c41110498e9148","license":"MIT","scripts":{"size":"node scripts/size.mjs","test":"npm run build && node --test tests/*.test.mjs","build":"node scripts/build.mjs","check":"npm run typecheck && npm run typecheck:examples && npm run test && npm run verify:boundaries && npm run verify:package && npm run verify:stable && npm run size && npm run test:consumer","clean":"node scripts/clean.mjs","typecheck":"npm run generate:version && tsc -p tsconfig.check.json --noEmit --pretty false","test:consumer":"node scripts/test-packed-consumer.mjs","verify:stable":"node scripts/verify-stable.mjs","prepublishOnly":"npm run check","verify:package":"node scripts/verify-package.mjs","generate:version":"node scripts/generate-version.mjs","verify:boundaries":"node scripts/verify-boundaries.mjs","typecheck:examples":"tsc -p tsconfig.examples.json --pretty false"},"version":"0.1.4","_npmUser":{"name":"okarin_lab","email":"avelurs.billy@gmail.com"},"homepage":"https://github.com/blcklab/anyo-animation#readme","keywords":["anyo","animation","3d","gltf","glb","sekai64","state-machine","spatial-web"],"repository":{"url":"git+https://github.com/blcklab/anyo-animation.git","type":"git"},"_npmVersion":"10.9.8","description":"Optional renderer-neutral animation runtime for Anyo with parameters, state machines, events, root motion, authoring contracts, and an explicit Sekai64 adapter.","directories":{},"maintainers":[{"name":"okarin_lab","email":"avelurs.billy@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@blcklab/anyo":"0.11.0-rc.15","@blcklab/sekai64":"0.8.0-rc.43"},"peerDependencies":{"@blcklab/anyo":">=0.9.1-0 <0.10.0 || >=0.10.0-0 <0.11.0 || >=0.11.0-0 <1.0.0","@blcklab/sekai64":">=0.8.0-0 <0.9.0"},"peerDependenciesMeta":{"@blcklab/sekai64":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/anyo-animation_0.1.4_1790694911004_0.831074924058889"}}},"time":{"created":"2026-09-11T20:59:31.861Z","modified":"2026-09-29T15:15:11.425Z","0.1.1":"2026-09-11T20:59:32.173Z","0.1.2":"2026-09-14T07:14:17.067Z","0.1.3":"2026-09-23T21:57:41.811Z","0.1.4":"2026-09-29T15:15:11.093Z"},"bugs":{"url":"https://github.com/blcklab/anyo-animation/issues"},"author":{"name":"blcklab"},"license":"MIT","homepage":"https://github.com/blcklab/anyo-animation#readme","keywords":["anyo","animation","3d","gltf","glb","sekai64","state-machine","spatial-web"],"repository":{"url":"git+https://github.com/blcklab/anyo-animation.git","type":"git"},"description":"Optional renderer-neutral animation runtime for Anyo with parameters, state machines, events, root motion, authoring contracts, and an explicit Sekai64 adapter.","maintainers":[{"name":"okarin_lab","email":"avelurs.billy@gmail.com"}],"readme":"# @blcklab/anyo-animation\n\nOptional, renderer-neutral animation behavior for Anyo worlds.\n\nThe package owns authored playback rules: typed parameters, state machines, deterministic transitions, crossfades, marker actions, snapshots, lifecycle handling, and root-motion ownership. Low-level clip sampling, skeletons, morph targets, and mixers remain in the renderer adapter.\n\n```txt\nAnyo JSON\n   ↓\n@blcklab/anyo-animation\n   ↓\nrenderer-neutral animation adapter\n   ↓\n@blcklab/anyo-animation/sekai64\n   ↓\n@blcklab/sekai64/animation\n```\n\nThe root entry has zero runtime dependencies and never imports Sekai64.\n\n## Install\n\n```bash\nnpm install @blcklab/anyo-animation @blcklab/anyo\n```\n\nFor the official Sekai64 integration:\n\n```bash\nnpm install @blcklab/sekai64\n```\n\n## Quick start\n\n```ts\nimport { createWorld } from '@blcklab/anyo'\nimport { entitiesPlugin } from '@blcklab/anyo/entities'\nimport { createSekai64AnimationRuntime } from '@blcklab/anyo-animation/sekai64'\n\nconst animation = createSekai64AnimationRuntime({\n  canvas: document.querySelector('#world') as HTMLCanvasElement,\n  backend: 'auto',\n})\n\nconst world = createWorld({\n  renderer: animation.renderer,\n  plugins: [entitiesPlugin(), animation.plugin],\n})\n\nawait world.load('/world.json')\nworld.start()\n```\n\nThe Sekai64 integration installs its optional animation renderer module lazily and registers the explicit `animated-model` asset loader. Static Anyo projects remain unchanged.\n\n### Player / shared VRM integration\n\nHosts that install renderer modules directly can use `createSekai64AnimationIntegration()` and pass the same `module` to the Avatar VRM loader. The animation adapter can then bind a compatible animated `GltfModelNode` even when that model was loaded by the VRM loader rather than by Animation's own `animated-model` loader.\n\n```ts\nimport { createSekai64AnimationIntegration } from '@blcklab/anyo-animation/sekai64'\nimport { createSekai64VrmAssetLoader } from '@blcklab/anyo-avatar/vrm/sekai64'\n\nconst animation = createSekai64AnimationIntegration()\n\nconst renderer = {\n  modules: [animation.module],\n  assetLoaders: [\n    animation.assetLoader,\n    createSekai64VrmAssetLoader({ animationModule: animation.module }),\n  ],\n}\n\nconst plugins = [animation.plugin]\n```\n\nThis is additive: `createSekai64AnimationRuntime()` and the existing `animated-model` workflow remain supported.\n\n## Authored component\n\n```json\n{\n  \"type\": \"anyo.animation\",\n  \"clips\": {\n    \"idle\": \"Idle\",\n    \"walk\": \"Walk\",\n    \"run\": \"Run\",\n    \"jump\": \"Jump\"\n  },\n  \"autoplay\": true,\n  \"parameters\": {\n    \"moving\": { \"type\": \"boolean\", \"default\": false },\n    \"speed\": { \"type\": \"number\", \"default\": 0, \"min\": 0, \"max\": 5 },\n    \"jump\": { \"type\": \"trigger\" }\n  },\n  \"stateMachine\": {\n    \"initial\": \"idle\",\n    \"states\": {\n      \"idle\": { \"clip\": \"idle\" },\n      \"walk\": { \"clip\": \"walk\" },\n      \"run\": { \"clip\": \"run\" },\n      \"jump\": { \"clip\": \"jump\", \"loop\": \"once\" }\n    },\n    \"transitions\": [\n      {\n        \"from\": \"idle\",\n        \"to\": \"walk\",\n        \"when\": { \"speed\": { \"greaterThan\": 0.1 } },\n        \"duration\": 0.2\n      },\n      {\n        \"from\": \"*\",\n        \"to\": \"jump\",\n        \"when\": { \"jump\": { \"triggered\": true } },\n        \"priority\": 100,\n        \"duration\": 0.1\n      },\n      {\n        \"from\": \"jump\",\n        \"to\": \"idle\",\n        \"exitTime\": 1,\n        \"duration\": 0.15\n      }\n    ]\n  },\n  \"markers\": {\n    \"footstep-left\": {\n      \"action\": \"audio.play\",\n      \"params\": { \"clip\": \"footstep-left\" }\n    }\n  },\n  \"rootMotion\": {\n    \"mode\": \"horizontal-only\",\n    \"node\": \"Hips\"\n  }\n}\n```\n\n## Runtime control\n\n```ts\nanimation.plugin.play('hero', 'walk')\nanimation.plugin.transitionTo('hero', 'run', 0.25)\nanimation.plugin.pause('hero')\nanimation.plugin.resume('hero')\nanimation.plugin.seek('hero', 0.5)\nanimation.plugin.setSpeed('hero', 1.25)\nanimation.plugin.stop('hero')\n```\n\nCommands issued before an animated asset finishes loading are retained and applied after the binding becomes available.\n\n## Parameters\n\n```ts\nanimation.plugin.setBoolean('hero', 'moving', true)\nanimation.plugin.setNumber('hero', 'speed', 2.5)\nanimation.plugin.setTrigger('hero', 'jump')\nanimation.plugin.resetTrigger('hero', 'jump')\n\nconst speed = animation.plugin.getParameter('hero', 'speed')\n```\n\nNumber parameters are clamped to their authored minimum and maximum. Triggers are one-shot values and are consumed automatically by matching transitions.\n\n### Subscriptions and host bindings\n\n```ts\nconst unsubscribe = animation.plugin.subscribeParameter(\n  'hero',\n  'speed',\n  (speed) => console.log(speed),\n)\n\nconst unbind = animation.plugin.bindParameter(\n  'hero',\n  'speed',\n  () => movementController.speed,\n)\n```\n\nBindings are renderer-neutral and do not import controls, physics, Player, or Editor packages.\n\n## State machines\n\nTransitions support:\n\n```txt\nequals\nnotEquals\ngreaterThan\ngreaterThanOrEqual\nlessThan\nlessThanOrEqual\ntriggered\nnotTriggered\n```\n\nAdditional policies:\n\n```txt\nall / any condition mode\nany-state transitions with \"*\"\nnormalized exit time\npriority\ninterruptible transitions\ntrigger consumption\ncrossfade duration\nstate entry and exit actions\n```\n\nSekai64 executes the blend. Anyo Animation determines when and why a state changes.\n\n## Marker actions\n\nSekai64 clip markers are forwarded as `animation:marker` events. Authored marker bindings run existing Anyo actions using JSON-compatible parameters. Executable JavaScript is never stored in world JSON.\n\n## Root motion\n\nSupported modes:\n\n```txt\ndisabled\nextract-only\napply-to-entity\napply-to-controller\nhorizontal-only\n```\n\nFor Sekai64, the selected root translation track is removed from the rendered clip and sampled separately. This prevents double motion when the extracted delta is written into Anyo's transient transform store.\n\n`apply-to-controller` and `extract-only` emit `animation:root-motion`; applications can also use `onRootMotion`.\n\n## Snapshots\n\n```ts\nconst entityParameters = animation.plugin.createParameterSnapshot('hero')\nanimation.plugin.restoreParameterSnapshot('hero', entityParameters)\n\nconst session = animation.plugin.createSnapshot()\nlocalStorage.setItem('animation', JSON.stringify(session))\nanimation.plugin.restoreSnapshot(JSON.parse(localStorage.getItem('animation')!))\n```\n\nSnapshots contain plain JSON-compatible values and never revive entities that are no longer present.\n\n## Player and recovery lifecycle\n\nThe plugin reacts to Player/world pause and resume events and reconciles after renderer recovery or world replacement. It cleans up bindings, subscriptions, parameter bindings, root-motion transform layers, cloned root-motion clips, and mixer listeners.\n\nFor explicit teardown:\n\n```ts\nawait animation.plugin.disposeAsync()\n```\n\n## World actions\n\nThe plugin registers:\n\n```txt\nanimation.play\nanimation.state\nanimation.parameter\nanimation.trigger\n```\n\nThese make animation control available to other data-driven Anyo systems without direct package coupling.\n\n## Authoring integration\n\nEditor and generator tools should import the optional authoring subpath:\n\n```ts\nimport {\n  createAnimationComponentDefinition,\n  listAnimationClipReferences,\n  validateAnimationComponentData,\n} from '@blcklab/anyo-animation/authoring'\n```\n\nThis entry is renderer-neutral and safe for Editor forms, prefab validation, inspectors, and schema-driven tooling.\n\n## Custom renderer adapters\n\n```ts\nimport { createAnimationPlugin } from '@blcklab/anyo-animation'\n\nconst animation = createAnimationPlugin({\n  adapter: myAnimationAdapter,\n  strict: true,\n  onDiagnostic(diagnostic) {\n    console.warn(diagnostic.code, diagnostic.message)\n  },\n})\n```\n\nImplement `AnimationRuntimeAdapter` and `AnimationEntityBinding`. Crossfades, events, normalized time, and root-motion extraction are optional capabilities; basic playback remains supported.\n\n## Package boundaries\n\n```txt\n@blcklab/anyo-animation\n  parameters, state machines, actions, snapshots, lifecycle\n\n@blcklab/anyo-animation/authoring\n  editor-safe component creation and validation\n\n@blcklab/anyo-animation/sekai64\n  animated glTF/GLB loader, mixers, crossfades, markers, root motion\n```\n\n## Stable guarantees\n\nSee [Compatibility](docs/COMPATIBILITY.md) for the `0.1.x` compatibility contract.\n\n### Externally prepared clips\n\nRenderer-specific importers/retargeters can prepare Sekai64 `AnimationClip` objects for an already-loaded model and hand playback ownership to Anyo Animation:\n\n```ts\nconst unregister = integration.adapter.registerExternalClips(model, clips, {\n  restorePose,\n})\n```\n\nThis hook does not parse or retarget animation data. The producer owns the clips and must dispose them after unregistering. Anyo Animation owns mixer/play/stop/crossfade behavior while the registration is active. This is intended for integrations such as VRMA humanoid retargeting without duplicating the renderer animation runtime.\n","readmeFilename":"README.md"}