← SplineCONTENT HISTORY

Update to Spline

Snapshot Oct 24, 2026 · 13:29 UTC · version 1.2.0

Collection source: downloaded plugin package.

WHAT CHANGED

First saved snapshot

No earlier snapshot is available to establish a change.

Save Spline and check future changes in Following.

Up to 10 plugins free · no card required.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "The built-in States & Transitions animation feature — load ONLY when the user explicitly asks for it (names states, transitions, the timeline, or the States panel), or for physics-coupled kinematic motion (moving platforms — the one motion that must be state-driven): the all-in-one animate() helper plus the low-level addState/addEvent/addAction/updateTween flow, easings, duration, delay, loop and pingpong. Code-driven motion (the default) is the `animation` skill.",
  "included_files": [],
  "name": "spline-3d-state-transitions",
  "skill_md_contents": "---\nname: spline-3d-state-transitions\ndescription: \"The built-in States & Transitions animation feature — load ONLY when the user explicitly asks for it (names states, transitions, the timeline, or the States panel), or for physics-coupled kinematic motion (moving platforms — the one motion that must be state-driven): the all-in-one animate() helper plus the low-level addState/addEvent/addAction/updateTween flow, easings, duration, delay, loop and pingpong. Code-driven motion (the default) is the `animation` skill.\"\n---\n\n# States & Transitions (the built-in animation feature)\n\nOPT-IN ONLY: motion is code-driven by default (the `animation` skill —\nposes computed from time in the HTML layer, written through the `spline`\nbridge). Use the built-in States & Transitions feature ONLY when the user\nexplicitly asks for it — they name states, transitions, the timeline, or\nthe States panel — or for PHYSICS-COUPLED kinematic motion (a positioned\nbody pushes dynamic bodies only when a STATE animates its transform;\nper-frame bridge writes are teleports the simulation cannot see — see the\n`physics` skill). Editing state-based interactivity a scene ALREADY has\nalso belongs here (with the `interactivity` skill for the full\nevent/action machinery).\n\nState-based animation: an object has a Base State (its current look) and one\nor more named States. A *transition* tweens the object from one state to\nanother when an *event* fires.\n\n## The fast path: `animate(stateProps, transitionProps?)`\n`animate` does the whole thing in one call on the selected object: it creates a\nnew state, writes the target properties into it, adds an event, adds a\nTransition action, and configures the tween.\n\n```\n// pulse bigger on start, forever, smoothly\nmesh('Sphere', { width: 200 });\nanimate(\n  { scale: { x: 1.4, y: 1.4, z: 1.4 } },\n  { duration: 800, easing: 'ease-in-out', loop: true, direction: 'alternate' }\n);\n```\n\n`stateProps` (the target look) accepts any of:\n- `position`, `rotation` (DEGREES), `scale` — each `{x?,y?,z?}`\n- `color` — hex/CSS string\n- `width`, `height`, `depth` — numbers\n- `geometry` — a partial geometry change (e.g. `{ radius: 50 }`)\n- `material` — a partial material layer, must include `type`\n  (e.g. `{ type: 'fresnel', alpha: 0.5 }`)\n\n`transitionProps` accepts:\n- `duration` — milliseconds (default 1000)\n- `delay` — milliseconds before starting\n- `easing` — one of the string names below\n- `loop: true` — repeat forever (sets internal `repeat = -1`)\n- `direction: 'alternate'` — ping-pong back and forth (maps to `'pingpong'`)\n- `trigger` — the event that starts it; an `INTERACTION_EVENT` string, default\n  `'Start'` (i.e. plays on scene load). Use `'MouseDown'`, `'MouseHover'`, etc.\n  for interactive transitions.\n- spring tuning: `mass`, `stiffness`, `damping`, `velocity` (used when\n  `easing: 'spring'`).\n\n### Easing string names accepted by `animate`\n`'linear'`, `'ease'`, `'ease-in'`, `'ease-out'`, `'ease-in-out'` (default),\n`'cubic'`, `'spring'`. (`'ease-in-out-bounce'` also maps to spring.)\n\n```\n// click-to-flip an object 180deg with a springy feel\nanimate(\n  { rotation: { y: 180 } },\n  { trigger: 'MouseDown', easing: 'spring', stiffness: 120, damping: 12 }\n);\n```\n\n## The low-level flow (when you need precise control)\nUse this when `animate` is too coarse — e.g. multiple tweens, custom tween\nordering, or wiring an event you already created. All calls operate on the\ncurrently selected object.\n\n1. `addState()` — adds a new state and makes it the active edit target.\n2. Write the target look with normal transform/color/material calls; while a\n   state is active these write *into the state*, not the base:\n   `position({x:300})`, `rotation({z:90})`, `scale({x:2,y:2,z:2})`,\n   `color('#ff3366')`.\n3. `addEvent(type)` — returns the new event id as its result; the alias also\n   exposes the resolved `type`. `type` is an `INTERACTION_EVENT` string,\n   default `'Start'`.\n4. `addAction(eventId, eventType, 'Transition')` — returns\n   `{ actionId, tweenId, initialTweenId }`. The Transition action is created\n   with two tweens: `initialTweenId` (base, frame ~10) and `tweenId` (your new\n   state, frame ~11).\n5. `updateTween(eventId, actionId, tweenId, props)` — set the tween's\n   timing/easing.\n\nBecause `run_code` is straight-line code, you can capture the returned ids in\nvariables within a single code block:\n```\naddState();\nposition({ y: 300 });\nconst e = addEvent('Start');\nconst a = addAction(e, 'Start', 'Transition');\nupdateTween(e, a.actionId, a.tweenId, {\n  duration: 1200,\n  easing: 'ease-in-out',\n  loop: true,            // repeat forever\n  direction: 'alternate' // ping-pong back and forth\n});\n```\n\n## Tween properties (`updateTween` / `addTween`)\n`updateTween` accepts the SAME friendly vocabulary as `animate`:\n- `duration`: number — milliseconds.\n- `delay`: number — milliseconds before the tween starts.\n- `easing`: a string name from the list above (an unknown string is dropped).\n- `loop: true` — infinite repeat.\n- `direction: 'alternate'` — ping-pong back and forth.\n- spring tuning: `mass`, `stiffness`, `damping`, `velocity` (defaults:\n  mass 1, stiffness 80, damping 10, velocity 0) with `easing: 'spring'`.\n\nRaw TweenState values also pass through if you're mirroring what\n`get_objects` reports: `repeat` (extra iterations after the first, `-1` =\ninfinite), `direction: 'normal' | 'pingpong' | 'pingpong-rewind'`, and\nnumeric `easing` enums (`LINEAR = 0`, `EASE = 1`, `EASE_IN = 2`,\n`EASE_OUT = 3`, `EASE_IN_OUT = 4`, `CUBIC = 5`, `SPRING = 6`, `ARC = 7`,\n`NONE = 8`). Prefer the friendly names.\n\n## Common patterns\n```\n// gentle infinite bob\nanimate({ position: { y: 60 } },\n        { duration: 1500, easing: 'ease-in-out', loop: true, direction: 'alternate' });\n\n// spin once on load\nanimate({ rotation: { y: 360 } }, { duration: 4000, easing: 'linear', loop: true });\n\n// fade/scale-in on start\nscale({ x: 0.01, y: 0.01, z: 0.01 });        // start small (base state)\nanimate({ scale: { x: 1, y: 1, z: 1 } },     // grow to full\n        { duration: 600, easing: 'spring' });\n```\n\n### Phase-offset ambient motion (states-world version)\nThe DEFAULT scene-life pattern is the code version — the `animation`\nskill's \"Ambient life (phase offsets)\". When the user has explicitly asked\nfor states, the same idea holds: one looping bob on a whole group reads as\nmechanical, so give each drifting element its OWN loop with a different\nduration/delay. `iterate` visits every selected object; vary the timing\nper index:\n```\nselect(o => o.name.startsWith('Cloud'));\nlet i = 0;\niterate((o) => {\n  animate({ position: { y: 30 + rand() * 30 } },\n          { duration: 2200 + i * 700, delay: i * 400,\n            easing: 'ease-in-out', loop: true, direction: 'alternate' });\n  i = i + 1;\n});\n```\n\nNotes:\n- Rotations are always in DEGREES.\n- Set the *starting* look on the base state (before `animate`), and the\n  *ending* look inside `stateProps`.\n- For click/hover/scroll-driven transitions, set `trigger` (or use the\n  low-level event flow) — see the `interactivity` skill for the full event and\n  action catalog.\n- Verify motion by entering play with `play()` and/or `take_screenshot()`.\n"
}

SHA-256 of public snapshot: 32d9cd37c2be8ebc6e8f1e364087567ac7c0ec2bcef25ce1632dc0f8ccca1388