@3driseai/3drise-core 1.0.18 → 1.0.20

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.
Files changed (146) hide show
  1. package/dist/animations/index.d.ts +2 -0
  2. package/dist/animations/index.d.ts.map +1 -0
  3. package/dist/animations/index.js +1 -0
  4. package/dist/animations/trackGenerators.d.ts +140 -0
  5. package/dist/animations/trackGenerators.d.ts.map +1 -0
  6. package/dist/animations/trackGenerators.js +443 -0
  7. package/dist/autoAnimate/bounds.d.ts +7 -0
  8. package/dist/autoAnimate/bounds.d.ts.map +1 -0
  9. package/dist/autoAnimate/bounds.js +23 -0
  10. package/dist/autoAnimate/composer.d.ts +30 -0
  11. package/dist/autoAnimate/composer.d.ts.map +1 -0
  12. package/dist/autoAnimate/composer.js +251 -0
  13. package/dist/autoAnimate/describeScene.d.ts +105 -0
  14. package/dist/autoAnimate/describeScene.d.ts.map +1 -0
  15. package/dist/autoAnimate/describeScene.js +165 -0
  16. package/dist/autoAnimate/draft.d.ts +59 -0
  17. package/dist/autoAnimate/draft.d.ts.map +1 -0
  18. package/dist/autoAnimate/draft.js +2 -0
  19. package/dist/autoAnimate/index.d.ts +14 -0
  20. package/dist/autoAnimate/index.d.ts.map +1 -0
  21. package/dist/autoAnimate/index.js +9 -0
  22. package/dist/autoAnimate/recipes.d.ts +87 -0
  23. package/dist/autoAnimate/recipes.d.ts.map +1 -0
  24. package/dist/autoAnimate/recipes.js +224 -0
  25. package/dist/autoAnimate/rng.d.ts +10 -0
  26. package/dist/autoAnimate/rng.d.ts.map +1 -0
  27. package/dist/autoAnimate/rng.js +16 -0
  28. package/dist/autoAnimate/sceneAnalyzer.d.ts +7 -0
  29. package/dist/autoAnimate/sceneAnalyzer.d.ts.map +1 -0
  30. package/dist/autoAnimate/sceneAnalyzer.js +291 -0
  31. package/dist/autoAnimate/types.d.ts +124 -0
  32. package/dist/autoAnimate/types.d.ts.map +1 -0
  33. package/dist/autoAnimate/types.js +1 -0
  34. package/dist/autoAnimate/validator.d.ts +10 -0
  35. package/dist/autoAnimate/validator.d.ts.map +1 -0
  36. package/dist/autoAnimate/validator.js +59 -0
  37. package/dist/data/effectsDefaults.d.ts +4 -0
  38. package/dist/data/effectsDefaults.d.ts.map +1 -1
  39. package/dist/data/effectsDefaults.js +393 -2
  40. package/dist/data/gridsDefaults.d.ts +5 -0
  41. package/dist/data/gridsDefaults.d.ts.map +1 -0
  42. package/dist/data/gridsDefaults.js +290 -0
  43. package/dist/data/index.d.ts +1 -0
  44. package/dist/data/index.d.ts.map +1 -1
  45. package/dist/data/index.js +1 -0
  46. package/dist/data/particlesDefaults.d.ts +3 -1
  47. package/dist/data/particlesDefaults.d.ts.map +1 -1
  48. package/dist/data/particlesDefaults.js +78 -0
  49. package/dist/environment/cloudConfigs.d.ts +313 -0
  50. package/dist/environment/cloudConfigs.d.ts.map +1 -0
  51. package/dist/environment/cloudConfigs.js +342 -0
  52. package/dist/environment/index.d.ts +5 -0
  53. package/dist/environment/index.d.ts.map +1 -0
  54. package/dist/environment/index.js +6 -0
  55. package/dist/environment/landscapeConfigs.d.ts +220 -0
  56. package/dist/environment/landscapeConfigs.d.ts.map +1 -0
  57. package/dist/environment/landscapeConfigs.js +256 -0
  58. package/dist/environment/oceanConfigs.d.ts +293 -0
  59. package/dist/environment/oceanConfigs.d.ts.map +1 -0
  60. package/dist/environment/oceanConfigs.js +380 -0
  61. package/dist/environment/terrainConfigs.d.ts +254 -0
  62. package/dist/environment/terrainConfigs.d.ts.map +1 -0
  63. package/dist/environment/terrainConfigs.js +292 -0
  64. package/dist/index.d.ts +4 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +4 -0
  67. package/dist/properties/index.d.ts +4 -0
  68. package/dist/properties/index.d.ts.map +1 -0
  69. package/dist/properties/index.js +3 -0
  70. package/dist/properties/registry.d.ts +44 -0
  71. package/dist/properties/registry.d.ts.map +1 -0
  72. package/dist/properties/registry.js +343 -0
  73. package/dist/properties/tables/effectsProperties.d.ts +40 -0
  74. package/dist/properties/tables/effectsProperties.d.ts.map +1 -0
  75. package/dist/properties/tables/effectsProperties.js +512 -0
  76. package/dist/properties/tables/geometryProperties.d.ts +38 -0
  77. package/dist/properties/tables/geometryProperties.d.ts.map +1 -0
  78. package/dist/properties/tables/geometryProperties.js +91 -0
  79. package/dist/properties/tables/getPropertyConfig.d.ts +3 -0
  80. package/dist/properties/tables/getPropertyConfig.d.ts.map +1 -0
  81. package/dist/properties/tables/getPropertyConfig.js +16 -0
  82. package/dist/properties/tables/gridProperties.d.ts +6 -0
  83. package/dist/properties/tables/gridProperties.d.ts.map +1 -0
  84. package/dist/properties/tables/gridProperties.js +121 -0
  85. package/dist/properties/tables/index.d.ts +9 -0
  86. package/dist/properties/tables/index.d.ts.map +1 -0
  87. package/dist/properties/tables/index.js +8 -0
  88. package/dist/properties/tables/lightProperties.d.ts +14 -0
  89. package/dist/properties/tables/lightProperties.d.ts.map +1 -0
  90. package/dist/properties/tables/lightProperties.js +263 -0
  91. package/dist/properties/tables/materialBounds.d.ts +33 -0
  92. package/dist/properties/tables/materialBounds.d.ts.map +1 -0
  93. package/dist/properties/tables/materialBounds.js +180 -0
  94. package/dist/properties/tables/optionalProperties.d.ts +83 -0
  95. package/dist/properties/tables/optionalProperties.d.ts.map +1 -0
  96. package/dist/properties/tables/optionalProperties.js +710 -0
  97. package/dist/properties/tables/particlesProperties.d.ts +17 -0
  98. package/dist/properties/tables/particlesProperties.d.ts.map +1 -0
  99. package/dist/properties/tables/particlesProperties.js +334 -0
  100. package/dist/properties/types.d.ts +43 -0
  101. package/dist/properties/types.d.ts.map +1 -0
  102. package/dist/properties/types.js +12 -0
  103. package/dist/services/AnimationsManager.d.ts +6 -106
  104. package/dist/services/AnimationsManager.d.ts.map +1 -1
  105. package/dist/services/AnimationsManager.js +5 -391
  106. package/dist/services/SceneActions.d.ts +17 -3
  107. package/dist/services/SceneActions.d.ts.map +1 -1
  108. package/dist/services/SceneActions.js +12 -8
  109. package/dist/services/ShadersLibrary.d.ts +1 -1
  110. package/dist/services/ShadersLibrary.d.ts.map +1 -1
  111. package/dist/services/index.d.ts +1 -2
  112. package/dist/services/index.d.ts.map +1 -1
  113. package/dist/shaders/WallpaperGridMaterial.d.ts.map +1 -1
  114. package/dist/shaders/WallpaperGridMaterial.js +6 -1
  115. package/dist/three/GalleryLayoutV.d.ts.map +1 -1
  116. package/dist/three/GalleryLayoutV.js +0 -10
  117. package/dist/three/SceneBuilderV.d.ts.map +1 -1
  118. package/dist/three/SceneBuilderV.js +1 -7
  119. package/dist/types/actions.d.ts +8 -1
  120. package/dist/types/actions.d.ts.map +1 -1
  121. package/dist/types/actions.js +0 -4
  122. package/dist/types/animations.d.ts +0 -51
  123. package/dist/types/animations.d.ts.map +1 -1
  124. package/dist/types/generativeEffects.d.ts +0 -4
  125. package/dist/types/generativeEffects.d.ts.map +1 -1
  126. package/dist/types/generativeParticles.d.ts +175 -2
  127. package/dist/types/generativeParticles.d.ts.map +1 -1
  128. package/dist/types/objectSettings.d.ts +96 -17
  129. package/dist/types/objectSettings.d.ts.map +1 -1
  130. package/dist/types/scene3d.d.ts +3 -3
  131. package/dist/types/scene3d.d.ts.map +1 -1
  132. package/dist/types/types.d.ts +3 -2
  133. package/dist/types/types.d.ts.map +1 -1
  134. package/dist/utils/generativeAnimatable.d.ts +1 -1
  135. package/dist/utils/generativeAnimatable.d.ts.map +1 -1
  136. package/dist/utils/generativeAnimatable.js +7 -1
  137. package/dist/utils/getAnimatableProperties.d.ts +12 -1
  138. package/dist/utils/getAnimatableProperties.d.ts.map +1 -1
  139. package/dist/utils/getAnimatableProperties.js +35 -138
  140. package/dist/utils/index.d.ts +1 -0
  141. package/dist/utils/index.d.ts.map +1 -1
  142. package/dist/utils/index.js +1 -0
  143. package/dist/utils/objectEffects.d.ts +6 -0
  144. package/dist/utils/objectEffects.d.ts.map +1 -0
  145. package/dist/utils/objectEffects.js +5 -0
  146. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ // =============================================================================
2
+ // generateAnimation — scene profile + template + style → clips and a sequence.
3
+ // =============================================================================
4
+ //
5
+ // Templates:
6
+ // intro Reveal (hero enters, camera pulls in) → Ensemble (groups cascade in,
7
+ // the rest follow, lights) → Showcase (camera swings around the hero,
8
+ // the hero pulses). Ends on the authored scene. Plays once (hold).
9
+ // ambient One looping step: everything breathes / floats / sways and returns to
10
+ // rest, the camera swings out and back — seamless at the loop seam.
11
+ //
12
+ // Rules enforced here (see claude/auto-animate-plan.md): continuity through a
13
+ // ledger; group coherence (same recipe, ease, duration, ±7% amplitude, cascade in
14
+ // spatial order with a fixed total stagger); scale-relative magnitudes; ground;
15
+ // camera speed limit; return to rest; beat grid (0.25 s); no parent + child on the
16
+ // same object chain; saved objects only; a later entrance is staged at its start
17
+ // pose from the first frame (so nothing pops in before its turn).
18
+ //
19
+ import { toActionKey, uniqueActionKey } from '../utils/actionKeys.js';
20
+ import { analyzeScene } from './sceneAnalyzer.js';
21
+ import { createRng } from './rng.js';
22
+ import { chooseEnter, environmentPaths, Ledger, planAmbient, planCameraDolly, planCameraOrbit, planEnter, planLightEnter, round, STYLES, } from './recipes.js';
23
+ import { validateGenerated } from './validator.js';
24
+ const LENGTH_MUL = { short: 0.8, medium: 1, long: 1.3 };
25
+ const BEAT = 0.25;
26
+ const snap = (t, min = BEAT) => Math.max(min, Math.round(t / BEAT) * BEAT);
27
+ const defaultId = (prefix) => `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
28
+ const getAtPath = (obj, path) => path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj);
29
+ export function generateAnimation(input, options) {
30
+ const profile = options.profile ?? analyzeScene(input, options.analyze);
31
+ const makeId = options.makeId ?? defaultId;
32
+ const seed = options.seed ?? Math.floor(Math.random() * 2 ** 31);
33
+ const rng = createRng(seed);
34
+ const style = STYLES[options.style] ?? STYLES.calm;
35
+ const driver = options.driver ?? 'time';
36
+ const objectsById = new Map((input.objects ?? []).map((o) => [o.id, o]));
37
+ const authored = (state, path) => {
38
+ const src = state === 'camera' ? input.camera
39
+ : state === 'sky' ? input.sky
40
+ : state === 'clouds' ? input.clouds
41
+ : state === 'ocean' ? input.ocean
42
+ : state === 'terrain' ? input.terrain
43
+ : objectsById.get(state);
44
+ const v = getAtPath(src, path);
45
+ return v === undefined ? undefined : (Array.isArray(v) ? [...v] : v);
46
+ };
47
+ const ctx = { profile, rng, style, ledger: new Ledger(authored), makeId, driven: driver !== 'time' };
48
+ const taken = new Set(options.takenKeys ?? []);
49
+ const keyFor = (name) => {
50
+ const k = uniqueActionKey(toActionKey(name), taken);
51
+ taken.add(k);
52
+ return k;
53
+ };
54
+ const clips = [];
55
+ const steps = [];
56
+ const lenMul = LENGTH_MUL[options.length] ?? 1;
57
+ const dur = (base) => snap(base * style.durationMul * lenMul);
58
+ // --- helpers ------------------------------------------------------------------------
59
+ const key = (t, value, ease) => ({ id: makeId('k'), t: round(t), value, ...(ease ? { ease } : {}) });
60
+ const track = (state, path, keys) => ({ id: makeId('tr'), state, path, keys });
61
+ const enterTracks = (moves, t0, d) => moves.map(m => track(m.state, m.path, [key(t0, m.away, m.ease), key(t0 + d, m.rest)]));
62
+ const addClip = (name, tracks, duration, description) => {
63
+ if (!tracks.length)
64
+ return null;
65
+ const clip = {
66
+ id: makeId('clip'), name: `Auto · ${name}`, key: keyFor(`auto ${name}`), description,
67
+ duration: round(duration, 3), fps: 30, loop: false, yoyo: false, endMode: 'hold', tracks,
68
+ };
69
+ clips.push(clip);
70
+ ctx.ledger.commit(tracks);
71
+ return clip;
72
+ };
73
+ const addStep = (list) => {
74
+ const ok = list.filter((c) => !!c);
75
+ if (ok.length)
76
+ steps.push({ id: makeId('step'), clips: ok.map(c => ({ id: makeId('sc'), clipId: c.id, delay: 0, speed: 1 })) });
77
+ return ok.length ? Math.max(...ok.map(c => c.duration)) : 0;
78
+ };
79
+ // --- who moves ----------------------------------------------------------------------------
80
+ const byId = new Map(profile.objects.map(p => [p.id, p]));
81
+ const ancestors = (p) => {
82
+ const out = [];
83
+ let cur = p.parentId ? byId.get(p.parentId) : undefined;
84
+ while (cur && out.length < 64) {
85
+ out.push(cur.id);
86
+ cur = cur.parentId ? byId.get(cur.parentId) : undefined;
87
+ }
88
+ return out;
89
+ };
90
+ const hero = profile.heroId ? byId.get(profile.heroId) ?? null : null;
91
+ const animated = new Set();
92
+ /** A new object may move unless it or one of its ancestors / descendants already does. */
93
+ const canAnimate = (p) => p.saved && p.visible && !animated.has(p.id) && !ancestors(p).some(a => animated.has(a)) &&
94
+ ![...animated].some(id => ancestors(byId.get(id)).includes(p.id));
95
+ if (hero && hero.saved)
96
+ animated.add(hero.id);
97
+ const groups = [];
98
+ for (const g of profile.groups) {
99
+ const members = g.memberIds.map(id => byId.get(id)).filter(m => m.role !== 'hero');
100
+ const free = members.filter(canAnimate);
101
+ if (free.length < 2)
102
+ continue;
103
+ free.forEach(m => animated.add(m.id));
104
+ const order = (rng.next() < 0.5 ? g.order : g.radialOrder).filter(id => free.some(m => m.id === id));
105
+ const first = byId.get(order[0]);
106
+ const label = g.kind === 'parent' ? byId.get(g.parentId)?.name ?? 'Group' : `${first.name.replace(/[\s_\-.#]*\d+\s*$/, '') || first.name}s`;
107
+ groups.push({ group: g, name: label, members: order.map(id => byId.get(id)) });
108
+ }
109
+ const standalone = profile.objects
110
+ .filter(p => (p.role === 'standalone' || p.role === 'member') && canAnimate(p))
111
+ .sort((a, b) => a.bounds.center[0] - b.bounds.center[0]);
112
+ standalone.forEach(p => animated.add(p.id));
113
+ const lights = profile.objects.filter(p => p.role === 'light' && p.saved && p.capabilities.config.includes('intensity'));
114
+ const center = hero ? hero.bounds.center : profile.bounds.center;
115
+ // =========================================================================================
116
+ if (options.template === 'ambient') {
117
+ const T = dur(4);
118
+ const phaseSpan = T * 0.5;
119
+ const stepClips = [];
120
+ const ambientTracks = (p, name, amp, phase) => {
121
+ const plan = planAmbient(name, p, amp, ctx);
122
+ if (!plan)
123
+ return [];
124
+ return [track(p.id, plan.path, plan.points.map(([f, v], i) => key(phase + f * T, v, i < plan.points.length - 1 ? style.ambientEase : undefined)))];
125
+ };
126
+ if (hero && animated.has(hero.id)) {
127
+ stepClips.push(addClip(hero.name, [...ambientTracks(hero, 'float', 1, 0), ...ambientTracks(hero, 'glow', 1, 0)], T, 'Hero: float and glow'));
128
+ }
129
+ for (const g of groups) {
130
+ const name = rng.pick(['float', 'sway', 'breathe']);
131
+ const n = g.members.length;
132
+ const tracks = g.members.flatMap((m, i) => ambientTracks(m, name, rng.jitter(0.07), snap((phaseSpan * i) / Math.max(1, n), 0)));
133
+ stepClips.push(addClip(g.name, tracks, T + phaseSpan, `${name}, a wave across the group`));
134
+ }
135
+ if (standalone.length) {
136
+ const n = standalone.length;
137
+ const tracks = standalone.flatMap((m, i) => ambientTracks(m, 'float', rng.jitter(0.07) * 0.7, snap((phaseSpan * i) / Math.max(1, n), 0)));
138
+ stepClips.push(addClip('Others', tracks, T + phaseSpan, 'Gentle float'));
139
+ }
140
+ if (lights.length) {
141
+ stepClips.push(addClip('Lights', lights.flatMap(l => ambientTracks(l, 'swell', rng.jitter(0.07), 0)), T, 'Light swell'));
142
+ }
143
+ const L = Math.max(T, ...stepClips.filter(Boolean).map(c => c.duration));
144
+ stepClips.push(addClip('Camera', planCameraOrbit(ctx, center, L, rng.next() < 0.5 ? 1 : -1), L, 'Swing out and back'));
145
+ const envTracks = environmentPaths(ctx).map(e => {
146
+ const v = Number(ctx.ledger.get(e.state, e.path));
147
+ const peak = round(Math.min(e.max, Math.max(e.min, v + e.delta / 2)));
148
+ return track(e.state, e.path, [key(0, v, 'easeInOutSine'), key(L / 2, peak, 'easeInOutSine'), key(L, v)]);
149
+ });
150
+ stepClips.push(addClip('Atmosphere', envTracks, L, 'Slow environment drift'));
151
+ addStep(stepClips);
152
+ }
153
+ else {
154
+ // ---------------------------------------------------------------- intro
155
+ const D = dur(1.2);
156
+ const envs = environmentPaths(ctx);
157
+ // Plan every entrance first: their start poses are staged from the first frame.
158
+ const heroMoves = hero && animated.has(hero.id) ? chooseEnter(hero, 1, ctx).moves : [];
159
+ const groupPlans = groups.map(g => {
160
+ // One recipe for the whole group: the first of the style that works for every member.
161
+ const names = [...style.enters, 'pop'];
162
+ const name = names.find(nm => g.members.every(m => planEnter(nm, m, 1, ctx))) ?? 'pop';
163
+ const amps = g.members.map(() => rng.jitter(0.07));
164
+ return { ...g, moves: g.members.map((m, i) => planEnter(name, m, amps[i], ctx) ?? []), recipe: name };
165
+ });
166
+ const standaloneMoves = standalone.map(p => chooseEnter(p, 0.8 * rng.jitter(0.07), ctx).moves);
167
+ const lightMoves = style.name === 'cinematic' ? lights.flatMap(l => planLightEnter(l, ctx)) : [];
168
+ // Step 1 — Reveal
169
+ const later = [...groupPlans.flatMap(g => g.moves.flat()), ...standaloneMoves.flat(), ...lightMoves];
170
+ const step1 = [];
171
+ step1.push(addClip('Staging', later.map(m => track(m.state, m.path, [key(0, m.away)])), BEAT, 'Start poses of what enters later'));
172
+ if (heroMoves.length)
173
+ step1.push(addClip(`${hero.name} enters`, enterTracks(heroMoves, 0, D), D, 'Hero entrance'));
174
+ const dolly = planCameraDolly(ctx, 1);
175
+ const Dc = dur(1.6);
176
+ if (dolly)
177
+ step1.push(addClip('Camera in', [track('camera', dolly.path, [key(0, dolly.away, style.name === 'cinematic' ? 'easeInOutCubic' : 'easeOutCubic'), key(Dc, dolly.rest)])], Dc, 'Pull in to the authored view'));
178
+ const L1 = Math.max(D, Dc);
179
+ // Step 2 — Ensemble
180
+ const step2 = [];
181
+ for (const g of groupPlans) {
182
+ const n = g.members.length;
183
+ const S = snap(Math.min(1.4, Math.max(0.4, 0.18 * n)) * style.durationMul, 0);
184
+ const tracks = g.moves.flatMap((moves, i) => enterTracks(moves, n > 1 ? round((S * i) / (n - 1)) : 0, D));
185
+ step2.push(addClip(`${g.name} enter`, tracks, D + S, `${g.recipe}, cascading`));
186
+ }
187
+ if (standalone.length) {
188
+ const n = standalone.length;
189
+ const S = snap(Math.min(1.2, Math.max(0.3, 0.15 * n)) * style.durationMul, 0);
190
+ step2.push(addClip('Others enter', standaloneMoves.flatMap((moves, i) => enterTracks(moves, n > 1 ? round((S * i) / (n - 1)) : 0, D)), D + S));
191
+ }
192
+ if (lightMoves.length)
193
+ step2.push(addClip('Lights on', enterTracks(lightMoves, 0, D * 1.5), D * 1.5));
194
+ const L2 = step2.filter(Boolean).length ? Math.max(...step2.filter(Boolean).map(c => c.duration)) : 0;
195
+ // Step 3 — Showcase
196
+ const Do = dur(4);
197
+ const step3 = [];
198
+ step3.push(addClip('Camera orbit', planCameraOrbit(ctx, center, Do, rng.next() < 0.5 ? 1 : -1), Do, 'Swing around and back'));
199
+ if (hero && animated.has(hero.id)) {
200
+ const accent = planAmbient(hero.capabilities.emissive ? 'glow' : 'breathe', hero, 1, ctx);
201
+ if (accent) {
202
+ const T = Math.min(Do, dur(1.6));
203
+ step3.push(addClip(`${hero.name} accent`, [track(hero.id, accent.path, accent.points.map(([f, v], i) => key(round((Do - T) / 2 + f * T), v, i < accent.points.length - 1 ? style.ambientEase : undefined)))], Do));
204
+ }
205
+ }
206
+ // Atmosphere: one continuous slow move across the steps (rest − δ → rest).
207
+ const lengths = [L1, L2, Do];
208
+ const total = lengths.reduce((a, b) => a + b, 0);
209
+ const envClip = (stepIndex) => {
210
+ const L = lengths[stepIndex];
211
+ if (!L || !envs.length)
212
+ return null;
213
+ const before = lengths.slice(0, stepIndex).reduce((a, b) => a + b, 0);
214
+ const tracks = envs.map(e => {
215
+ const rest = Number(ctx.ledger.get(e.state, e.path));
216
+ // rest here is where the previous slice left it; the full move ends at the authored value
217
+ const authoredV = Number(authored(e.state, e.path));
218
+ const start = Math.min(e.max, Math.max(e.min, authoredV - e.delta));
219
+ const at = (t) => round(start + (authoredV - start) * (t / total));
220
+ return track(e.state, e.path, [key(0, stepIndex === 0 ? at(0) : rest, 'linear'), key(L, at(before + L))]);
221
+ });
222
+ return addClip(`Atmosphere ${stepIndex + 1}`, tracks, L, 'Slow environment layer');
223
+ };
224
+ step1.push(envClip(0));
225
+ addStep(step1);
226
+ if (L2) {
227
+ step2.push(envClip(1));
228
+ addStep(step2);
229
+ }
230
+ step3.push(envClip(2));
231
+ addStep(step3);
232
+ }
233
+ const name = `Auto · ${options.template === 'ambient' ? 'Ambient loop' : 'Intro'} (${style.name})`;
234
+ const sequence = {
235
+ id: makeId('seq'),
236
+ name,
237
+ key: keyFor(name),
238
+ description: `Generated from the scene (seed ${seed}).`,
239
+ steps,
240
+ cues: [],
241
+ loop: options.template === 'ambient' && driver === 'time',
242
+ yoyo: false,
243
+ reverse: false,
244
+ endMode: 'hold',
245
+ driver,
246
+ driverSettings: { sensitivity: 1, smoothing: 0.25, invert: false },
247
+ autoplay: options.autoplay ?? false,
248
+ };
249
+ const issues = validateGenerated(clips, sequence, { driven: ctx.driven });
250
+ return { clips, sequence, profile, issues };
251
+ }
@@ -0,0 +1,105 @@
1
+ import type { AnalyzeOptions, SceneInput } from './types';
2
+ export type PropKind = 'vec3' | 'number' | 'color' | 'boolean' | 'select' | 'string';
3
+ export interface PropContext {
4
+ path: string;
5
+ kind: PropKind;
6
+ /** Authored value. */
7
+ value?: unknown;
8
+ min?: number;
9
+ max?: number;
10
+ options?: string[];
11
+ }
12
+ export interface ElementContext {
13
+ tracks: PropContext[];
14
+ patch: PropContext[];
15
+ }
16
+ export interface ObjectContext extends ElementContext {
17
+ id: string;
18
+ name: string;
19
+ type: string;
20
+ /** config.type (light / particles / effect / grid kind, shape name). */
21
+ subType?: string;
22
+ role: string;
23
+ /** Has a real (saved) id — only saved objects can be referenced by animations. */
24
+ saved: boolean;
25
+ visible: boolean;
26
+ groupId?: string;
27
+ parentId?: string;
28
+ childIds?: string[];
29
+ /** Authored local transform. */
30
+ position: number[];
31
+ rotation: number[];
32
+ scale: number[];
33
+ /** World bounds. */
34
+ center: number[];
35
+ size: number[];
36
+ fadeable: boolean;
37
+ material?: {
38
+ type?: string;
39
+ variant?: string;
40
+ color?: string;
41
+ };
42
+ }
43
+ export type EnvironmentKey = 'sky' | 'clouds' | 'ocean' | 'terrain';
44
+ export interface EnvironmentContext extends ElementContext {
45
+ /** The element exists in the scene (configured), on or off. */
46
+ present: boolean;
47
+ on: boolean;
48
+ /** deckType / waterType / terrainType. */
49
+ kind?: string;
50
+ preset?: string;
51
+ /** Ocean: 'world' | 'object'… */
52
+ host?: string;
53
+ /** Clouds: the high ice layer. */
54
+ cirrus?: {
55
+ on: boolean;
56
+ preset?: string;
57
+ };
58
+ }
59
+ export interface SceneAnalysis {
60
+ version: 2;
61
+ scene: {
62
+ scale: number;
63
+ ground: number;
64
+ center: number[];
65
+ size: number[];
66
+ heroId: string | null;
67
+ countsByType: Record<string, number>;
68
+ };
69
+ camera: ElementContext & {
70
+ position: number[];
71
+ target: number[];
72
+ fov: number;
73
+ distance: number;
74
+ /** Visible area on the ground plane (y = 0), 0 when no camera is mounted. */
75
+ viewport: {
76
+ visibleWidth: number;
77
+ visibleHeight: number;
78
+ };
79
+ };
80
+ environment: Record<EnvironmentKey, EnvironmentContext>;
81
+ background: {
82
+ hdri: string | null;
83
+ };
84
+ groups: Array<{
85
+ id: string;
86
+ kind: string;
87
+ axis: string;
88
+ order: string[];
89
+ radialOrder: string[];
90
+ }>;
91
+ objects: ObjectContext[];
92
+ }
93
+ export interface DescribeSceneInput extends SceneInput {
94
+ /** HDR background settings (`name` is the preset). */
95
+ hdr?: any;
96
+ }
97
+ export interface DescribeOptions extends AnalyzeOptions {
98
+ /** Visible area on the ground plane (viewer camera), when mounted. */
99
+ viewport?: {
100
+ visibleWidth: number;
101
+ visibleHeight: number;
102
+ } | null;
103
+ }
104
+ export declare function describeScene(input: DescribeSceneInput, options?: DescribeOptions): SceneAnalysis;
105
+ //# sourceMappingURL=describeScene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describeScene.d.ts","sourceRoot":"","sources":["../../src/autoAnimate/describeScene.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ // =============================================================================
2
+ // describeScene — the ONE description of the scene every AI request carries.
3
+ // =============================================================================
4
+ //
5
+ // analyzeScene (layout, roles, groups, hero) + the property registry (every
6
+ // element's keyable tracks and settable properties, with current values and
7
+ // bounds) in one compact, rounded shape. The client sends it as the request's
8
+ // `scene`; the aiAgent mirrors these types (utils/v2/sceneAnalysis.ts — keep them
9
+ // in step).
10
+ //
11
+ // scene scale / ground / bounds / hero / counts — size every magnitude by `scale`
12
+ // camera pose, viewport at ground, keyable paths
13
+ // environment sky / clouds / ocean / terrain: present? on? kind / preset, and — when
14
+ // on — current values as tracks (keyable) + patch (action-only)
15
+ // background HDRI preset name
16
+ // groups cascade orders
17
+ // objects EVERY object (each consumer filters): role, saved, visible, hierarchy,
18
+ // transform, world bounds, material, and
19
+ // tracks what a clip can key (getTrackSpecs) with value / range
20
+ // patch config / environment properties only an instant change can set
21
+ //
22
+ // Pure like analyzeScene: live bounds and the viewport are injected by the caller.
23
+ // Model nodes are left out (node animation has its own path).
24
+ //
25
+ import { analyzeScene } from './sceneAnalyzer.js';
26
+ import { describeProperties, getTrackSpecs } from '../properties/registry.js';
27
+ // --- helpers --------------------------------------------------------------------
28
+ const r = (n) => {
29
+ const v = Number(n);
30
+ return Number.isFinite(v) ? Math.round(v * 1000) / 1000 : 0;
31
+ };
32
+ const rv = (v) => (v ?? []).map(r);
33
+ const roundValue = (v) => (Array.isArray(v) ? v.map(r) : typeof v === 'number' ? r(v) : v);
34
+ /** Registry kinds the AI can write; strings, vec2 and textures are not offered. */
35
+ const PROP_KINDS = new Set(['vec3', 'number', 'color', 'boolean', 'select']);
36
+ /** Families whose set-only properties go out as patch (transform / material / edges / shadow are not offered). */
37
+ const PATCH_DOMAINS = new Set(['light', 'particles', 'effect', 'grid', 'rain', 'clouds', 'config', 'sky', 'cirrus', 'ocean', 'terrain']);
38
+ const toProp = (p) => {
39
+ if (!PROP_KINDS.has(p.kind))
40
+ return null;
41
+ const out = { path: p.key, kind: p.kind, value: roundValue(p.value) };
42
+ if (p.min !== undefined)
43
+ out.min = p.min;
44
+ if (p.max !== undefined)
45
+ out.max = p.max;
46
+ if (p.options?.length)
47
+ out.options = p.options.map(o => o.value);
48
+ return out;
49
+ };
50
+ /** tracks = what a clip keys (with values and bounds); patch = the element's other settable properties. */
51
+ function elementProps(element, settings) {
52
+ const described = new Map(describeProperties(element, settings).map(p => [p.key, p]));
53
+ const trackPaths = getTrackSpecs(element, settings).map(s => s.key);
54
+ const keyed = new Set(trackPaths);
55
+ const tracks = [];
56
+ for (const path of trackPaths) {
57
+ const p = described.get(path);
58
+ const prop = p && toProp(p);
59
+ if (prop)
60
+ tracks.push(prop);
61
+ }
62
+ const patch = [];
63
+ for (const p of described.values()) {
64
+ if (keyed.has(p.key) || !PATCH_DOMAINS.has(p.domain))
65
+ continue;
66
+ const prop = toProp(p);
67
+ if (prop)
68
+ patch.push(prop);
69
+ }
70
+ return { tracks, patch };
71
+ }
72
+ /** One environment element: always its identity; values only when it is on (they are what an animation / change can touch). */
73
+ function environmentOf(key, settings, on) {
74
+ const cfg = key === 'sky' ? settings : settings?.config;
75
+ const present = key === 'sky' ? !!settings
76
+ : key === 'ocean' ? !!(cfg && typeof cfg === 'object' && cfg.waveModel)
77
+ : !!(cfg && typeof cfg === 'object');
78
+ const kind = key === 'clouds' ? cfg?.deckType : key === 'ocean' ? cfg?.waterType : key === 'terrain' ? cfg?.terrainType : undefined;
79
+ const values = on ? elementProps(key, settings) : { tracks: [], patch: [] };
80
+ return {
81
+ present,
82
+ on,
83
+ ...(kind ? { kind } : {}),
84
+ ...(cfg?.preset ? { preset: cfg.preset } : {}),
85
+ ...(key === 'ocean' && cfg?.host ? { host: cfg.host } : {}),
86
+ ...(key === 'clouds' && settings?.cirrus ? { cirrus: { on: settings.cirrus.enabled !== false, ...(settings.cirrus.preset ? { preset: settings.cirrus.preset } : {}) } } : {}),
87
+ ...values,
88
+ };
89
+ }
90
+ function materialOf(obj) {
91
+ const ms = obj?.materialSettings;
92
+ if (!ms?.materialType && !ms?.color)
93
+ return undefined;
94
+ return {
95
+ ...(ms.materialType ? { type: ms.materialType } : {}),
96
+ ...(ms.materialVariant ? { variant: ms.materialVariant } : {}),
97
+ ...(typeof ms.color === 'string' ? { color: ms.color } : {}),
98
+ };
99
+ }
100
+ // --- main ---------------------------------------------------------------------------
101
+ export function describeScene(input, options = {}) {
102
+ // Live bounds, no model nodes.
103
+ const profile = analyzeScene(input, { measure: options.measure });
104
+ const byId = new Map((input.objects ?? []).filter((o) => o && typeof o.id === 'string').map((o) => [o.id, o]));
105
+ const objects = [];
106
+ for (const p of profile.objects) {
107
+ const obj = byId.get(p.id);
108
+ if (!obj)
109
+ continue;
110
+ const material = materialOf(obj);
111
+ objects.push({
112
+ id: p.id,
113
+ name: p.name,
114
+ type: p.type,
115
+ ...(obj.config?.type ? { subType: obj.config.type } : {}),
116
+ role: p.role,
117
+ saved: p.saved,
118
+ visible: p.visible,
119
+ ...(p.groupId ? { groupId: p.groupId } : {}),
120
+ ...(p.parentId ? { parentId: p.parentId } : {}),
121
+ ...(p.childIds.length ? { childIds: p.childIds } : {}),
122
+ position: rv(p.position),
123
+ rotation: rv(p.rotation),
124
+ scale: rv(p.scale),
125
+ center: rv(p.bounds.center),
126
+ size: rv(p.bounds.size),
127
+ fadeable: p.capabilities.fadeable,
128
+ ...(material ? { material } : {}),
129
+ ...elementProps('object', obj),
130
+ });
131
+ }
132
+ const countsByType = {};
133
+ Object.entries(profile.countsByType).forEach(([k, v]) => { if (v)
134
+ countsByType[k] = v; });
135
+ const vp = options.viewport;
136
+ return {
137
+ version: 2,
138
+ scene: {
139
+ scale: r(profile.scale),
140
+ ground: r(profile.ground),
141
+ center: rv(profile.bounds.center),
142
+ size: rv(profile.bounds.size),
143
+ heroId: profile.heroId,
144
+ countsByType,
145
+ },
146
+ camera: {
147
+ position: rv(profile.camera.position),
148
+ target: rv(profile.camera.target),
149
+ fov: r(profile.camera.fov),
150
+ distance: r(profile.camera.distance),
151
+ viewport: vp ? { visibleWidth: r(vp.visibleWidth), visibleHeight: r(vp.visibleHeight) } : { visibleWidth: 0, visibleHeight: 0 },
152
+ tracks: elementProps('camera', input.camera ?? {}).tracks,
153
+ patch: [],
154
+ },
155
+ environment: {
156
+ sky: environmentOf('sky', input.sky, profile.environment.sky),
157
+ clouds: environmentOf('clouds', input.clouds, profile.environment.clouds),
158
+ ocean: environmentOf('ocean', input.ocean, profile.environment.ocean),
159
+ terrain: environmentOf('terrain', input.terrain, profile.environment.terrain),
160
+ },
161
+ background: { hdri: input.hdr?.name ?? null },
162
+ groups: profile.groups.map(g => ({ id: g.id, kind: g.kind, axis: g.axis, order: g.order, radialOrder: g.radialOrder })),
163
+ objects,
164
+ };
165
+ }
@@ -0,0 +1,59 @@
1
+ import type { V3 } from './types';
2
+ export type DraftEase = 'linear' | 'step' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeOutElastic' | 'easeOutBounce';
3
+ export type DraftValue = number | V3 | number[] | string | boolean;
4
+ export interface DraftKey {
5
+ id: string;
6
+ t: number;
7
+ value: DraftValue;
8
+ ease?: DraftEase;
9
+ }
10
+ export interface DraftTrack {
11
+ id: string;
12
+ state: string;
13
+ node?: string;
14
+ path: string;
15
+ keys: DraftKey[];
16
+ }
17
+ export interface DraftClip {
18
+ id: string;
19
+ name: string;
20
+ key: string;
21
+ description?: string;
22
+ duration: number;
23
+ fps: number;
24
+ loop: boolean;
25
+ yoyo: boolean;
26
+ endMode: 'hold' | 'restore';
27
+ tracks: DraftTrack[];
28
+ }
29
+ export interface DraftStepClip {
30
+ id: string;
31
+ clipId: string;
32
+ delay: number;
33
+ speed: number;
34
+ }
35
+ export interface DraftSequence {
36
+ id: string;
37
+ name: string;
38
+ key: string;
39
+ description?: string;
40
+ steps: Array<{
41
+ id: string;
42
+ clips: DraftStepClip[];
43
+ }>;
44
+ cues: [];
45
+ loop: boolean;
46
+ yoyo: boolean;
47
+ reverse: boolean;
48
+ endMode: 'hold' | 'restore';
49
+ driver: 'time' | 'mouseWheel' | 'mouseX' | 'mouseY';
50
+ driverSettings: {
51
+ sensitivity: number;
52
+ smoothing: number;
53
+ invert: boolean;
54
+ };
55
+ autoplay: boolean;
56
+ }
57
+ /** Eases that feel wrong when an input scrubs them backwards (wheel / mouse drivers). */
58
+ export declare const OVERSHOOT_EASES: Set<DraftEase>;
59
+ //# sourceMappingURL=draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/autoAnimate/draft.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,MAAM,SAAS,GACf,QAAQ,GAAG,MAAM,GACjB,YAAY,GAAG,aAAa,GAAG,eAAe,GAC9C,aAAa,GAAG,cAAc,GAAG,gBAAgB,GACjD,aAAa,GAAG,cAAc,GAAG,gBAAgB,GACjD,YAAY,GAAG,aAAa,GAAG,eAAe,GAC9C,YAAY,GAAG,aAAa,GAAG,eAAe,GAC9C,YAAY,GAAG,aAAa,GAAG,eAAe,GAC9C,gBAAgB,GAAG,eAAe,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE;AACxF,MAAM,WAAW,UAAU;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,EAAE,CAAA;CAAE;AACxG,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACzF,MAAM,EAAE,UAAU,EAAE,CAAC;CACxB;AACD,MAAM,WAAW,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC3F,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC5D,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC,CAAC;IACrD,IAAI,EAAE,EAAE,CAAC;IACT,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5E,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,cAAc,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5E,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,yFAAyF;AACzF,eAAO,MAAM,eAAe,gBAAwG,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** Eases that feel wrong when an input scrubs them backwards (wheel / mouse drivers). */
2
+ export const OVERSHOOT_EASES = new Set(['easeInBack', 'easeOutBack', 'easeInOutBack', 'easeOutElastic', 'easeOutBounce']);
@@ -0,0 +1,14 @@
1
+ export * from './types';
2
+ export { analyzeScene, baseName } from './sceneAnalyzer';
3
+ export { makeBounds, boundsAround, unionBounds } from './bounds';
4
+ export { generateAnimation } from './composer';
5
+ export type { GenerateOptions, GenerateResult, AutoTemplate, LengthName } from './composer';
6
+ export { validateGenerated } from './validator';
7
+ export type { GenerationIssue } from './validator';
8
+ export { STYLES } from './recipes';
9
+ export type { StyleName, EnterName, AmbientName } from './recipes';
10
+ export type { DraftClip, DraftSequence, DraftTrack, DraftKey, DraftEase, DraftValue } from './draft';
11
+ export { createRng } from './rng';
12
+ export { describeScene } from './describeScene';
13
+ export type { SceneAnalysis, DescribeSceneInput, DescribeOptions, PropKind, PropContext, ElementContext, ObjectContext, EnvironmentKey, EnvironmentContext, } from './describeScene';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/autoAnimate/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACnE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACR,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EACzF,aAAa,EAAE,cAAc,EAAE,kBAAkB,GACpD,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ // Auto-animate: scene analysis (→ recipes → composer → validator). See claude/auto-animate-plan.md.
2
+ export * from './types.js';
3
+ export { analyzeScene, baseName } from './sceneAnalyzer.js';
4
+ export { makeBounds, boundsAround, unionBounds } from './bounds.js';
5
+ export { generateAnimation } from './composer.js';
6
+ export { validateGenerated } from './validator.js';
7
+ export { STYLES } from './recipes.js';
8
+ export { createRng } from './rng.js';
9
+ export { describeScene } from './describeScene.js';