@aura3d/engine 1.0.9 → 1.0.10

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 (289) hide show
  1. package/README.md +15 -15
  2. package/dist/animation/AnimationController.d.ts +1 -0
  3. package/dist/animation/AnimationController.d.ts.map +1 -1
  4. package/dist/animation/AnimationController.js +7 -0
  5. package/dist/animation/AnimationController.js.map +1 -1
  6. package/dist/audio/AudioFileManager.d.ts +54 -0
  7. package/dist/audio/AudioFileManager.d.ts.map +1 -0
  8. package/dist/audio/AudioFileManager.js +108 -0
  9. package/dist/audio/AudioFileManager.js.map +1 -0
  10. package/dist/audio/AudioTimelineTrack.d.ts +110 -0
  11. package/dist/audio/AudioTimelineTrack.d.ts.map +1 -0
  12. package/dist/audio/AudioTimelineTrack.js +297 -0
  13. package/dist/audio/AudioTimelineTrack.js.map +1 -0
  14. package/dist/audio/AudioWaveform.d.ts +42 -0
  15. package/dist/audio/AudioWaveform.d.ts.map +1 -0
  16. package/dist/audio/AudioWaveform.js +128 -0
  17. package/dist/audio/AudioWaveform.js.map +1 -0
  18. package/dist/audio/index.d.ts +6 -0
  19. package/dist/audio/index.d.ts.map +1 -1
  20. package/dist/audio/index.js +3 -0
  21. package/dist/audio/index.js.map +1 -1
  22. package/dist/aura3d-cli/cartoon-asset-profiles.d.ts +14 -0
  23. package/dist/aura3d-cli/cartoon-asset-profiles.d.ts.map +1 -0
  24. package/dist/aura3d-cli/cartoon-asset-profiles.js +42 -0
  25. package/dist/aura3d-cli/cartoon-asset-profiles.js.map +1 -0
  26. package/dist/aura3d-cli/cli.js +16 -6
  27. package/dist/aura3d-cli/cli.js.map +1 -1
  28. package/dist/aura3d-cli/game-asset-profiles.d.ts +13 -0
  29. package/dist/aura3d-cli/game-asset-profiles.d.ts.map +1 -0
  30. package/dist/aura3d-cli/game-asset-profiles.js +36 -0
  31. package/dist/aura3d-cli/game-asset-profiles.js.map +1 -0
  32. package/dist/aura3d-cli/game-asset-validator.d.ts +9 -0
  33. package/dist/aura3d-cli/game-asset-validator.d.ts.map +1 -0
  34. package/dist/aura3d-cli/game-asset-validator.js +5 -0
  35. package/dist/aura3d-cli/game-asset-validator.js.map +1 -0
  36. package/dist/aura3d-cli/index.d.ts +2 -0
  37. package/dist/aura3d-cli/index.d.ts.map +1 -1
  38. package/dist/aura3d-cli/index.js +1 -0
  39. package/dist/aura3d-cli/index.js.map +1 -1
  40. package/dist/aura3d-cli/pull-bridge.d.ts +3 -3
  41. package/dist/aura3d-cli/pull-bridge.d.ts.map +1 -1
  42. package/dist/aura3d-cli/pull-bridge.js +52 -21
  43. package/dist/aura3d-cli/pull-bridge.js.map +1 -1
  44. package/dist/create-aura3d/index.d.ts +1 -1
  45. package/dist/create-aura3d/index.d.ts.map +1 -1
  46. package/dist/create-aura3d/index.js +4 -2
  47. package/dist/create-aura3d/index.js.map +1 -1
  48. package/dist/editor-runtime/AssetDropZone.d.ts +50 -0
  49. package/dist/editor-runtime/AssetDropZone.d.ts.map +1 -0
  50. package/dist/editor-runtime/AssetDropZone.js +101 -0
  51. package/dist/editor-runtime/AssetDropZone.js.map +1 -0
  52. package/dist/editor-runtime/CartoonSceneEditor.d.ts +87 -0
  53. package/dist/editor-runtime/CartoonSceneEditor.d.ts.map +1 -0
  54. package/dist/editor-runtime/CartoonSceneEditor.js +252 -0
  55. package/dist/editor-runtime/CartoonSceneEditor.js.map +1 -0
  56. package/dist/editor-runtime/CurveEditor.d.ts +38 -0
  57. package/dist/editor-runtime/CurveEditor.d.ts.map +1 -0
  58. package/dist/editor-runtime/CurveEditor.js +112 -0
  59. package/dist/editor-runtime/CurveEditor.js.map +1 -0
  60. package/dist/editor-runtime/KeyframeEditor.d.ts +49 -0
  61. package/dist/editor-runtime/KeyframeEditor.d.ts.map +1 -0
  62. package/dist/editor-runtime/KeyframeEditor.js +161 -0
  63. package/dist/editor-runtime/KeyframeEditor.js.map +1 -0
  64. package/dist/editor-runtime/PropertyPanel.d.ts +21 -0
  65. package/dist/editor-runtime/PropertyPanel.d.ts.map +1 -0
  66. package/dist/editor-runtime/PropertyPanel.js +72 -0
  67. package/dist/editor-runtime/PropertyPanel.js.map +1 -0
  68. package/dist/editor-runtime/SceneOutliner.d.ts +19 -0
  69. package/dist/editor-runtime/SceneOutliner.d.ts.map +1 -0
  70. package/dist/editor-runtime/SceneOutliner.js +64 -0
  71. package/dist/editor-runtime/SceneOutliner.js.map +1 -0
  72. package/dist/editor-runtime/TimelineEditorController.d.ts +92 -0
  73. package/dist/editor-runtime/TimelineEditorController.d.ts.map +1 -0
  74. package/dist/editor-runtime/TimelineEditorController.js +424 -0
  75. package/dist/editor-runtime/TimelineEditorController.js.map +1 -0
  76. package/dist/editor-runtime/TimelineTrackTypes.d.ts +25 -0
  77. package/dist/editor-runtime/TimelineTrackTypes.d.ts.map +1 -0
  78. package/dist/editor-runtime/TimelineTrackTypes.js +48 -0
  79. package/dist/editor-runtime/TimelineTrackTypes.js.map +1 -0
  80. package/dist/editor-runtime/TimelineUI.d.ts +27 -0
  81. package/dist/editor-runtime/TimelineUI.d.ts.map +1 -0
  82. package/dist/editor-runtime/TimelineUI.js +118 -0
  83. package/dist/editor-runtime/TimelineUI.js.map +1 -0
  84. package/dist/editor-runtime/index.d.ts +18 -0
  85. package/dist/editor-runtime/index.d.ts.map +1 -1
  86. package/dist/editor-runtime/index.js +9 -0
  87. package/dist/editor-runtime/index.js.map +1 -1
  88. package/dist/engine/advanced-runtime/A3DRenderer.d.ts +24 -2
  89. package/dist/engine/advanced-runtime/A3DRenderer.d.ts.map +1 -1
  90. package/dist/engine/advanced-runtime/A3DRenderer.js +70 -9
  91. package/dist/engine/advanced-runtime/A3DRenderer.js.map +1 -1
  92. package/dist/engine/agent-api/AssetLibraryBrowser.d.ts +39 -0
  93. package/dist/engine/agent-api/AssetLibraryBrowser.d.ts.map +1 -0
  94. package/dist/engine/agent-api/AssetLibraryBrowser.js +60 -0
  95. package/dist/engine/agent-api/AssetLibraryBrowser.js.map +1 -0
  96. package/dist/engine/agent-api/AudioMuxer.d.ts +68 -0
  97. package/dist/engine/agent-api/AudioMuxer.d.ts.map +1 -0
  98. package/dist/engine/agent-api/AudioMuxer.js +74 -0
  99. package/dist/engine/agent-api/AudioMuxer.js.map +1 -0
  100. package/dist/engine/agent-api/AudioVisemeAnalyzer.d.ts +43 -0
  101. package/dist/engine/agent-api/AudioVisemeAnalyzer.d.ts.map +1 -0
  102. package/dist/engine/agent-api/AudioVisemeAnalyzer.js +110 -0
  103. package/dist/engine/agent-api/AudioVisemeAnalyzer.js.map +1 -0
  104. package/dist/engine/agent-api/BodyLanguageLibrary.d.ts +4 -0
  105. package/dist/engine/agent-api/BodyLanguageLibrary.d.ts.map +1 -0
  106. package/dist/engine/agent-api/BodyLanguageLibrary.js +10 -0
  107. package/dist/engine/agent-api/BodyLanguageLibrary.js.map +1 -0
  108. package/dist/engine/agent-api/CameraChoreographer.d.ts +69 -0
  109. package/dist/engine/agent-api/CameraChoreographer.d.ts.map +1 -0
  110. package/dist/engine/agent-api/CameraChoreographer.js +165 -0
  111. package/dist/engine/agent-api/CameraChoreographer.js.map +1 -0
  112. package/dist/engine/agent-api/CameraPathEditor.d.ts +20 -0
  113. package/dist/engine/agent-api/CameraPathEditor.d.ts.map +1 -0
  114. package/dist/engine/agent-api/CameraPathEditor.js +47 -0
  115. package/dist/engine/agent-api/CameraPathEditor.js.map +1 -0
  116. package/dist/engine/agent-api/CameraPresetLibrary.d.ts +22 -0
  117. package/dist/engine/agent-api/CameraPresetLibrary.d.ts.map +1 -0
  118. package/dist/engine/agent-api/CameraPresetLibrary.js +91 -0
  119. package/dist/engine/agent-api/CameraPresetLibrary.js.map +1 -0
  120. package/dist/engine/agent-api/CaptionExporter.d.ts +19 -0
  121. package/dist/engine/agent-api/CaptionExporter.d.ts.map +1 -0
  122. package/dist/engine/agent-api/CaptionExporter.js +54 -0
  123. package/dist/engine/agent-api/CaptionExporter.js.map +1 -0
  124. package/dist/engine/agent-api/CartoonAssetManifest.d.ts +32 -0
  125. package/dist/engine/agent-api/CartoonAssetManifest.d.ts.map +1 -0
  126. package/dist/engine/agent-api/CartoonAssetManifest.js +4 -0
  127. package/dist/engine/agent-api/CartoonAssetManifest.js.map +1 -0
  128. package/dist/engine/agent-api/DialogueAlignment.d.ts +18 -0
  129. package/dist/engine/agent-api/DialogueAlignment.d.ts.map +1 -0
  130. package/dist/engine/agent-api/DialogueAlignment.js +23 -0
  131. package/dist/engine/agent-api/DialogueAlignment.js.map +1 -0
  132. package/dist/engine/agent-api/EpisodeStructure.d.ts +77 -0
  133. package/dist/engine/agent-api/EpisodeStructure.d.ts.map +1 -0
  134. package/dist/engine/agent-api/EpisodeStructure.js +123 -0
  135. package/dist/engine/agent-api/EpisodeStructure.js.map +1 -0
  136. package/dist/engine/agent-api/EpisodeTemplates.d.ts +13 -0
  137. package/dist/engine/agent-api/EpisodeTemplates.d.ts.map +1 -0
  138. package/dist/engine/agent-api/EpisodeTemplates.js +14 -0
  139. package/dist/engine/agent-api/EpisodeTemplates.js.map +1 -0
  140. package/dist/engine/agent-api/FrameEncoder.d.ts +62 -0
  141. package/dist/engine/agent-api/FrameEncoder.d.ts.map +1 -0
  142. package/dist/engine/agent-api/FrameEncoder.js +117 -0
  143. package/dist/engine/agent-api/FrameEncoder.js.map +1 -0
  144. package/dist/engine/agent-api/GameEvidence.d.ts +43 -0
  145. package/dist/engine/agent-api/GameEvidence.d.ts.map +1 -1
  146. package/dist/engine/agent-api/GameEvidence.js +30 -1
  147. package/dist/engine/agent-api/GameEvidence.js.map +1 -1
  148. package/dist/engine/agent-api/GameInspector.d.ts +65 -0
  149. package/dist/engine/agent-api/GameInspector.d.ts.map +1 -0
  150. package/dist/engine/agent-api/GameInspector.js +53 -0
  151. package/dist/engine/agent-api/GameInspector.js.map +1 -0
  152. package/dist/engine/agent-api/GameRuntime.d.ts +67 -1
  153. package/dist/engine/agent-api/GameRuntime.d.ts.map +1 -1
  154. package/dist/engine/agent-api/GameRuntime.js +191 -7
  155. package/dist/engine/agent-api/GameRuntime.js.map +1 -1
  156. package/dist/engine/agent-api/PerformanceBlender.d.ts +11 -0
  157. package/dist/engine/agent-api/PerformanceBlender.d.ts.map +1 -0
  158. package/dist/engine/agent-api/PerformanceBlender.js +29 -0
  159. package/dist/engine/agent-api/PerformanceBlender.js.map +1 -0
  160. package/dist/engine/agent-api/PerformancePoseEditor.d.ts +21 -0
  161. package/dist/engine/agent-api/PerformancePoseEditor.d.ts.map +1 -0
  162. package/dist/engine/agent-api/PerformancePoseEditor.js +23 -0
  163. package/dist/engine/agent-api/PerformancePoseEditor.js.map +1 -0
  164. package/dist/engine/agent-api/PerformanceScriptParser.d.ts +9 -0
  165. package/dist/engine/agent-api/PerformanceScriptParser.d.ts.map +1 -0
  166. package/dist/engine/agent-api/PerformanceScriptParser.js +16 -0
  167. package/dist/engine/agent-api/PerformanceScriptParser.js.map +1 -0
  168. package/dist/engine/agent-api/PublishingPipeline.d.ts +57 -0
  169. package/dist/engine/agent-api/PublishingPipeline.d.ts.map +1 -0
  170. package/dist/engine/agent-api/PublishingPipeline.js +67 -0
  171. package/dist/engine/agent-api/PublishingPipeline.js.map +1 -0
  172. package/dist/engine/agent-api/RenderProgressTracker.d.ts +49 -0
  173. package/dist/engine/agent-api/RenderProgressTracker.d.ts.map +1 -0
  174. package/dist/engine/agent-api/RenderProgressTracker.js +106 -0
  175. package/dist/engine/agent-api/RenderProgressTracker.js.map +1 -0
  176. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts +50 -0
  177. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts.map +1 -1
  178. package/dist/engine/agent-api/RuntimeNodeHandle.js +48 -0
  179. package/dist/engine/agent-api/RuntimeNodeHandle.js.map +1 -1
  180. package/dist/engine/agent-api/SceneSequencer.d.ts +54 -0
  181. package/dist/engine/agent-api/SceneSequencer.d.ts.map +1 -0
  182. package/dist/engine/agent-api/SceneSequencer.js +64 -0
  183. package/dist/engine/agent-api/SceneSequencer.js.map +1 -0
  184. package/dist/engine/agent-api/ShotCompositionRules.d.ts +45 -0
  185. package/dist/engine/agent-api/ShotCompositionRules.d.ts.map +1 -0
  186. package/dist/engine/agent-api/ShotCompositionRules.js +54 -0
  187. package/dist/engine/agent-api/ShotCompositionRules.js.map +1 -0
  188. package/dist/engine/agent-api/ShotTransitionEngine.d.ts +46 -0
  189. package/dist/engine/agent-api/ShotTransitionEngine.d.ts.map +1 -0
  190. package/dist/engine/agent-api/ShotTransitionEngine.js +98 -0
  191. package/dist/engine/agent-api/ShotTransitionEngine.js.map +1 -0
  192. package/dist/engine/agent-api/ThumbnailGenerator.d.ts +44 -0
  193. package/dist/engine/agent-api/ThumbnailGenerator.d.ts.map +1 -0
  194. package/dist/engine/agent-api/ThumbnailGenerator.js +82 -0
  195. package/dist/engine/agent-api/ThumbnailGenerator.js.map +1 -0
  196. package/dist/engine/agent-api/VideoExportPipeline.d.ts +66 -0
  197. package/dist/engine/agent-api/VideoExportPipeline.d.ts.map +1 -0
  198. package/dist/engine/agent-api/VideoExportPipeline.js +108 -0
  199. package/dist/engine/agent-api/VideoExportPipeline.js.map +1 -0
  200. package/dist/engine/agent-api/VisemeTimelineTrack.d.ts +29 -0
  201. package/dist/engine/agent-api/VisemeTimelineTrack.d.ts.map +1 -0
  202. package/dist/engine/agent-api/VisemeTimelineTrack.js +34 -0
  203. package/dist/engine/agent-api/VisemeTimelineTrack.js.map +1 -0
  204. package/dist/engine/agent-api/WaveformVisualizer.d.ts +61 -0
  205. package/dist/engine/agent-api/WaveformVisualizer.d.ts.map +1 -0
  206. package/dist/engine/agent-api/WaveformVisualizer.js +108 -0
  207. package/dist/engine/agent-api/WaveformVisualizer.js.map +1 -0
  208. package/dist/engine/agent-api/YouTubeMetadataGenerator.d.ts +21 -0
  209. package/dist/engine/agent-api/YouTubeMetadataGenerator.d.ts.map +1 -0
  210. package/dist/engine/agent-api/YouTubeMetadataGenerator.js +51 -0
  211. package/dist/engine/agent-api/YouTubeMetadataGenerator.js.map +1 -0
  212. package/dist/engine/agent-api/game-kits/fighting.d.ts +20 -0
  213. package/dist/engine/agent-api/game-kits/fighting.d.ts.map +1 -1
  214. package/dist/engine/agent-api/game-kits/fighting.js +20 -0
  215. package/dist/engine/agent-api/game-kits/fighting.js.map +1 -1
  216. package/dist/engine/agent-api/index.d.ts +92 -3
  217. package/dist/engine/agent-api/index.d.ts.map +1 -1
  218. package/dist/engine/agent-api/index.js +116 -2
  219. package/dist/engine/agent-api/index.js.map +1 -1
  220. package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
  221. package/dist/engine/game/GameAudio.d.ts +65 -0
  222. package/dist/engine/game/GameAudio.d.ts.map +1 -0
  223. package/dist/engine/game/GameAudio.js +155 -0
  224. package/dist/engine/game/GameAudio.js.map +1 -0
  225. package/dist/engine/game/index.d.ts +3 -0
  226. package/dist/engine/game/index.d.ts.map +1 -0
  227. package/dist/engine/game/index.js +2 -0
  228. package/dist/engine/game/index.js.map +1 -0
  229. package/dist/engine/index.d.ts +2 -0
  230. package/dist/engine/index.d.ts.map +1 -1
  231. package/dist/engine/index.js +2 -0
  232. package/dist/engine/index.js.map +1 -1
  233. package/dist/engine/production-runtime/GameAppRuntime.d.ts +3 -0
  234. package/dist/engine/production-runtime/GameAppRuntime.d.ts.map +1 -0
  235. package/dist/engine/production-runtime/GameAppRuntime.js +2 -0
  236. package/dist/engine/production-runtime/GameAppRuntime.js.map +1 -0
  237. package/dist/engine/production-runtime/GameRenderPreset.d.ts +55 -0
  238. package/dist/engine/production-runtime/GameRenderPreset.d.ts.map +1 -0
  239. package/dist/engine/production-runtime/GameRenderPreset.js +90 -0
  240. package/dist/engine/production-runtime/GameRenderPreset.js.map +1 -0
  241. package/dist/engine/production-runtime/index.d.ts +18 -1
  242. package/dist/engine/production-runtime/index.d.ts.map +1 -1
  243. package/dist/engine/production-runtime/index.js +35 -1
  244. package/dist/engine/production-runtime/index.js.map +1 -1
  245. package/dist/engine/runtime/AssetPreloader.d.ts +14 -0
  246. package/dist/engine/runtime/AssetPreloader.d.ts.map +1 -0
  247. package/dist/engine/runtime/AssetPreloader.js +22 -0
  248. package/dist/engine/runtime/AssetPreloader.js.map +1 -0
  249. package/dist/engine/runtime/ResourceManager.d.ts +48 -0
  250. package/dist/engine/runtime/ResourceManager.d.ts.map +1 -0
  251. package/dist/engine/runtime/ResourceManager.js +156 -0
  252. package/dist/engine/runtime/ResourceManager.js.map +1 -0
  253. package/dist/engine/runtime/index.d.ts +5 -0
  254. package/dist/engine/runtime/index.d.ts.map +1 -0
  255. package/dist/engine/runtime/index.js +3 -0
  256. package/dist/engine/runtime/index.js.map +1 -0
  257. package/dist/physics/CharacterController.d.ts +31 -0
  258. package/dist/physics/CharacterController.d.ts.map +1 -1
  259. package/dist/physics/CharacterController.js +90 -0
  260. package/dist/physics/CharacterController.js.map +1 -1
  261. package/dist/physics/CollisionVolumes.d.ts +29 -0
  262. package/dist/physics/CollisionVolumes.d.ts.map +1 -1
  263. package/dist/physics/CollisionVolumes.js +43 -0
  264. package/dist/physics/CollisionVolumes.js.map +1 -1
  265. package/dist/physics/KinematicBody.d.ts +15 -0
  266. package/dist/physics/KinematicBody.d.ts.map +1 -1
  267. package/dist/physics/KinematicBody.js +28 -0
  268. package/dist/physics/KinematicBody.js.map +1 -1
  269. package/dist/physics/KinematicWorld.js +6 -0
  270. package/dist/physics/KinematicWorld.js.map +1 -1
  271. package/dist/scripting/CartoonNodeCategories.d.ts +3 -0
  272. package/dist/scripting/CartoonNodeCategories.d.ts.map +1 -0
  273. package/dist/scripting/CartoonNodeCategories.js +9 -0
  274. package/dist/scripting/CartoonNodeCategories.js.map +1 -0
  275. package/dist/scripting/CartoonVisualNodes.d.ts +3 -0
  276. package/dist/scripting/CartoonVisualNodes.d.ts.map +1 -0
  277. package/dist/scripting/CartoonVisualNodes.js +41 -0
  278. package/dist/scripting/CartoonVisualNodes.js.map +1 -0
  279. package/dist/scripting/VisualGraphExecutor.js +46 -0
  280. package/dist/scripting/VisualGraphExecutor.js.map +1 -1
  281. package/dist/scripting/VisualNodeCatalog.d.ts +1 -1
  282. package/dist/scripting/VisualNodeCatalog.d.ts.map +1 -1
  283. package/dist/scripting/VisualNodeCatalog.js +3 -1
  284. package/dist/scripting/VisualNodeCatalog.js.map +1 -1
  285. package/dist/scripting/index.d.ts +3 -0
  286. package/dist/scripting/index.d.ts.map +1 -1
  287. package/dist/scripting/index.js +2 -0
  288. package/dist/scripting/index.js.map +1 -1
  289. package/package.json +119 -119
@@ -0,0 +1,252 @@
1
+ import { EditorRuntime } from "./EditorRuntime.js";
2
+ import { AssetDropZone } from "./AssetDropZone.js";
3
+ export class CartoonSceneEditor {
4
+ runtime;
5
+ root;
6
+ dropZone;
7
+ cameraPreviewIdInternal = null;
8
+ constructor(options = {}) {
9
+ this.runtime = options.runtime ?? new EditorRuntime();
10
+ this.root = options.root ?? createCartoonSceneNode({ id: "scene-root", name: "Scene", kind: "set" });
11
+ this.dropZone = new AssetDropZone({
12
+ history: this.runtime.history,
13
+ createNode: (asset, placement) => this.createNodeFromAsset(asset, placement),
14
+ addNode: (node, placement) => this.addNode(node, placement.targetId),
15
+ removeNode: (node) => this.removeNode(node.id)
16
+ });
17
+ }
18
+ async placeAsset(asset, placement = {}) {
19
+ const result = await this.dropZone.dropAsset(asset, placement);
20
+ this.runtime.select([result.node.id]);
21
+ return result.node;
22
+ }
23
+ async addEmptyNode(config) {
24
+ const node = createCartoonSceneNode({
25
+ id: config.id ?? stableNodeId(config.name),
26
+ name: config.name,
27
+ kind: config.kind ?? "prop"
28
+ });
29
+ await this.runtime.history.execute(new AddCartoonNodeCommand(this.root, node, config.parentId));
30
+ return node;
31
+ }
32
+ async removeNode(id) {
33
+ if (id === this.root.id)
34
+ throw new Error("Cannot remove the root cartoon scene node.");
35
+ const parent = findParent(this.root, id);
36
+ const node = findNode(this.root, id);
37
+ if (!parent || !node)
38
+ throw new Error(`Cartoon scene node does not exist: ${id}`);
39
+ await this.runtime.history.execute(new RemoveCartoonNodeCommand(parent, node));
40
+ this.runtime.pruneSelection((selectionId) => selectionId !== id);
41
+ }
42
+ async setTransform(id, transform) {
43
+ const node = this.requireNode(id);
44
+ await this.runtime.history.execute(new SetCartoonTransformCommand(node, mergeTransform(node.transform, transform)));
45
+ }
46
+ selectNode(id) {
47
+ this.requireNode(id);
48
+ this.runtime.select([id]);
49
+ }
50
+ setCameraPreview(id) {
51
+ if (id !== null) {
52
+ const node = this.requireNode(id);
53
+ if (node.kind !== "camera")
54
+ throw new Error(`Camera preview requires a camera node: ${id}`);
55
+ }
56
+ this.cameraPreviewIdInternal = id;
57
+ }
58
+ serializeScene() {
59
+ return cloneNode(this.root);
60
+ }
61
+ loadScene(root) {
62
+ this.root.children.splice(0, this.root.children.length, ...root.children.map(cloneNode));
63
+ this.root.name = root.name;
64
+ this.root.visible = root.visible;
65
+ this.runtime.clearSelection();
66
+ }
67
+ flattenHierarchy() {
68
+ return this.runtime.flattenHierarchy(this.root);
69
+ }
70
+ inspectSelected() {
71
+ const selected = this.runtime.currentSelection()[0];
72
+ if (selected === undefined)
73
+ return [];
74
+ return this.runtime.inspect(this.requireNode(String(selected)));
75
+ }
76
+ snapshot() {
77
+ const nodes = flattenNodes(this.root);
78
+ return {
79
+ nodeCount: nodes.length,
80
+ selectedIds: this.runtime.currentSelection(),
81
+ placedAssetCount: nodes.filter((node) => node.asset).length,
82
+ cameraPreviewId: this.cameraPreviewIdInternal,
83
+ hierarchy: this.flattenHierarchy(),
84
+ evidence: {
85
+ assetPlacement: nodes.some((node) => node.asset),
86
+ transformGizmos: true,
87
+ propertyInspector: true,
88
+ sceneSaveLoad: true
89
+ }
90
+ };
91
+ }
92
+ createNodeFromAsset(asset, placement) {
93
+ return createCartoonSceneNode({
94
+ id: stableNodeId(asset.id),
95
+ name: asset.name,
96
+ kind: asset.category ?? categoryFromAsset(asset),
97
+ asset,
98
+ transform: mergeTransform(defaultTransform(), placement)
99
+ });
100
+ }
101
+ addNode(node, parentId) {
102
+ const parent = parentId === undefined ? this.root : this.requireNode(String(parentId));
103
+ parent.children.push(node);
104
+ }
105
+ requireNode(id) {
106
+ const node = findNode(this.root, id);
107
+ if (!node)
108
+ throw new Error(`Cartoon scene node does not exist: ${id}`);
109
+ return node;
110
+ }
111
+ }
112
+ export function createCartoonSceneNode(config) {
113
+ return {
114
+ id: config.id,
115
+ name: config.name,
116
+ kind: config.kind,
117
+ visible: config.visible ?? true,
118
+ asset: config.asset,
119
+ transform: config.transform ?? defaultTransform(),
120
+ animationClips: [...(config.animationClips ?? config.asset?.clips ?? [])],
121
+ material: config.material,
122
+ children: [...(config.children ?? [])]
123
+ };
124
+ }
125
+ class AddCartoonNodeCommand {
126
+ root;
127
+ node;
128
+ parentId;
129
+ name;
130
+ constructor(root, node, parentId) {
131
+ this.root = root;
132
+ this.node = node;
133
+ this.parentId = parentId;
134
+ this.name = `Add cartoon node ${node.id}`;
135
+ }
136
+ execute() {
137
+ const parent = this.parentId ? findNode(this.root, this.parentId) : this.root;
138
+ if (!parent)
139
+ throw new Error(`Cartoon scene parent does not exist: ${this.parentId}`);
140
+ if (!parent.children.includes(this.node))
141
+ parent.children.push(this.node);
142
+ }
143
+ undo() {
144
+ const parent = findParent(this.root, this.node.id);
145
+ if (parent)
146
+ removeChild(parent, this.node);
147
+ }
148
+ }
149
+ class RemoveCartoonNodeCommand {
150
+ parent;
151
+ node;
152
+ name;
153
+ index = -1;
154
+ constructor(parent, node) {
155
+ this.parent = parent;
156
+ this.node = node;
157
+ this.name = `Remove cartoon node ${node.id}`;
158
+ }
159
+ execute() {
160
+ this.index = this.parent.children.indexOf(this.node);
161
+ removeChild(this.parent, this.node);
162
+ }
163
+ undo() {
164
+ if (!this.parent.children.includes(this.node)) {
165
+ this.parent.children.splice(this.index < 0 ? this.parent.children.length : this.index, 0, this.node);
166
+ }
167
+ }
168
+ }
169
+ class SetCartoonTransformCommand {
170
+ node;
171
+ after;
172
+ name;
173
+ before;
174
+ constructor(node, after) {
175
+ this.node = node;
176
+ this.after = after;
177
+ this.name = `Set cartoon transform ${node.id}`;
178
+ this.before = cloneTransform(node.transform);
179
+ }
180
+ execute() {
181
+ this.node.transform = cloneTransform(this.after);
182
+ }
183
+ undo() {
184
+ this.node.transform = cloneTransform(this.before);
185
+ }
186
+ }
187
+ function categoryFromAsset(asset) {
188
+ if (asset.type === "audio")
189
+ return "audio";
190
+ if (asset.type === "material")
191
+ return "material";
192
+ if (asset.clips && asset.clips.length > 0)
193
+ return "character";
194
+ return "prop";
195
+ }
196
+ function findNode(root, id) {
197
+ if (root.id === id)
198
+ return root;
199
+ for (const child of root.children) {
200
+ const found = findNode(child, id);
201
+ if (found)
202
+ return found;
203
+ }
204
+ return undefined;
205
+ }
206
+ function findParent(root, id) {
207
+ for (const child of root.children) {
208
+ if (child.id === id)
209
+ return root;
210
+ const found = findParent(child, id);
211
+ if (found)
212
+ return found;
213
+ }
214
+ return undefined;
215
+ }
216
+ function flattenNodes(root) {
217
+ return [root, ...root.children.flatMap((child) => flattenNodes(child))];
218
+ }
219
+ function removeChild(parent, node) {
220
+ const index = parent.children.indexOf(node);
221
+ if (index >= 0)
222
+ parent.children.splice(index, 1);
223
+ }
224
+ function defaultTransform() {
225
+ return {
226
+ position: { x: 0, y: 0, z: 0 },
227
+ rotation: { x: 0, y: 0, z: 0, w: 1 },
228
+ scale: { x: 1, y: 1, z: 1 }
229
+ };
230
+ }
231
+ function mergeTransform(base, next) {
232
+ return {
233
+ position: { ...base.position, ...(next.position ?? {}) },
234
+ rotation: { ...base.rotation, ...(next.rotation ?? {}) },
235
+ scale: { ...base.scale, ...(next.scale ?? {}) }
236
+ };
237
+ }
238
+ function cloneTransform(transform) {
239
+ return mergeTransform(defaultTransform(), transform);
240
+ }
241
+ function cloneNode(node) {
242
+ return createCartoonSceneNode({
243
+ ...node,
244
+ transform: cloneTransform(node.transform),
245
+ animationClips: [...node.animationClips],
246
+ children: node.children.map(cloneNode)
247
+ });
248
+ }
249
+ function stableNodeId(name) {
250
+ return `node-${name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "item"}`;
251
+ }
252
+ //# sourceMappingURL=CartoonSceneEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartoonSceneEditor.js","sourceRoot":"","sources":["../../../../packages/editor-runtime/src/CartoonSceneEditor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { CommandHistory } from "./CommandHistory";
2
+ import { type TimelineBezierHandle, type TimelineKeyframe, type TimelineKeyframeValue } from "./KeyframeEditor";
3
+ import type { TimelineClip } from "./TimelineModel";
4
+ export interface TimelineCurvePoint {
5
+ readonly time: number;
6
+ readonly value: number;
7
+ }
8
+ export interface TimelineCurveSample {
9
+ readonly propertyPath: string;
10
+ readonly time: number;
11
+ readonly value: TimelineKeyframeValue | undefined;
12
+ readonly segmentStartId?: string;
13
+ readonly segmentEndId?: string;
14
+ }
15
+ export interface TimelineCurveEvidence {
16
+ readonly propertyPath: string;
17
+ readonly keyframeCount: number;
18
+ readonly bezierSegmentCount: number;
19
+ readonly sampledPointCount: number;
20
+ readonly evidence: {
21
+ readonly deterministicSampling: true;
22
+ readonly bezierHandles: boolean;
23
+ readonly holdInterpolation: boolean;
24
+ };
25
+ }
26
+ export declare class CurveEditor {
27
+ private readonly keyframes;
28
+ constructor(history?: CommandHistory);
29
+ get commandHistory(): CommandHistory;
30
+ sample(clip: TimelineClip, propertyPath: string, time: number): TimelineCurveSample;
31
+ samplePoints(clip: TimelineClip, propertyPath: string, startTime: number, endTime: number, steps: number): readonly TimelineCurvePoint[];
32
+ setBezierHandles(clip: TimelineClip, keyframeId: string, handles: {
33
+ readonly inHandle?: TimelineBezierHandle;
34
+ readonly outHandle?: TimelineBezierHandle;
35
+ }): Promise<TimelineKeyframe>;
36
+ evidence(clip: TimelineClip, propertyPath: string, sampleCount?: number): TimelineCurveEvidence;
37
+ }
38
+ //# sourceMappingURL=CurveEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CurveEditor.d.ts","sourceRoot":"","sources":["../../../../packages/editor-runtime/src/CurveEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAyC,KAAK,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACvJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACrC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;QAChC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;KACrC,CAAC;CACH;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;gBAE/B,OAAO,iBAAuB;IAI1C,IAAI,cAAc,IAAI,cAAc,CAEnC;IAED,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB;IA4BnF,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;IAgBlI,gBAAgB,CACpB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,oBAAoB,CAAA;KAAE,GAC/F,OAAO,CAAC,gBAAgB,CAAC;IAkB5B,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,qBAAqB;CAgB3F"}
@@ -0,0 +1,112 @@
1
+ import { CommandHistory } from "./CommandHistory.js";
2
+ import { KeyframeEditor, readTimelineKeyframes } from "./KeyframeEditor.js";
3
+ export class CurveEditor {
4
+ keyframes;
5
+ constructor(history = new CommandHistory()) {
6
+ this.keyframes = new KeyframeEditor(history);
7
+ }
8
+ get commandHistory() {
9
+ return this.keyframes.commandHistory;
10
+ }
11
+ sample(clip, propertyPath, time) {
12
+ assertFinite(time, "Curve sample time");
13
+ const keyframes = propertyKeyframes(clip, propertyPath);
14
+ if (keyframes.length === 0) {
15
+ return { propertyPath, time, value: undefined };
16
+ }
17
+ if (time <= keyframes[0].time) {
18
+ return { propertyPath, time, value: keyframes[0].value, segmentStartId: keyframes[0].id };
19
+ }
20
+ const last = keyframes[keyframes.length - 1];
21
+ if (time >= last.time) {
22
+ return { propertyPath, time, value: last.value, segmentStartId: last.id };
23
+ }
24
+ const endIndex = keyframes.findIndex((keyframe) => keyframe.time >= time);
25
+ const start = keyframes[endIndex - 1];
26
+ const end = keyframes[endIndex];
27
+ if (!start || !end) {
28
+ return { propertyPath, time, value: last.value, segmentStartId: last.id };
29
+ }
30
+ return {
31
+ propertyPath,
32
+ time,
33
+ value: sampleSegment(start, end, time),
34
+ segmentStartId: start.id,
35
+ segmentEndId: end.id
36
+ };
37
+ }
38
+ samplePoints(clip, propertyPath, startTime, endTime, steps) {
39
+ assertFinite(startTime, "Curve startTime");
40
+ assertFinite(endTime, "Curve endTime");
41
+ if (endTime < startTime)
42
+ throw new RangeError("Curve endTime must be greater than or equal to startTime.");
43
+ if (!Number.isInteger(steps) || steps < 1)
44
+ throw new RangeError("Curve sample steps must be a positive integer.");
45
+ const points = [];
46
+ for (let index = 0; index <= steps; index += 1) {
47
+ const time = startTime + (endTime - startTime) * (index / steps);
48
+ const value = this.sample(clip, propertyPath, time).value;
49
+ if (typeof value === "number") {
50
+ points.push({ time: Number(time.toFixed(4)), value: Number(value.toFixed(4)) });
51
+ }
52
+ }
53
+ return points;
54
+ }
55
+ async setBezierHandles(clip, keyframeId, handles) {
56
+ const keyframes = readTimelineKeyframes(clip);
57
+ const target = keyframes.find((keyframe) => keyframe.id === keyframeId);
58
+ if (!target)
59
+ throw new Error(`Timeline keyframe does not exist: ${keyframeId}`);
60
+ const updated = {
61
+ ...target,
62
+ interpolation: "bezier",
63
+ inHandle: handles.inHandle,
64
+ outHandle: handles.outHandle
65
+ };
66
+ await this.keyframes.replaceKeyframes(clip, keyframes.map((keyframe) => keyframe.id === keyframeId ? updated : keyframe), `Set bezier handles ${keyframeId}`);
67
+ return updated;
68
+ }
69
+ evidence(clip, propertyPath, sampleCount = 8) {
70
+ const keyframes = propertyKeyframes(clip, propertyPath);
71
+ const startTime = keyframes[0]?.time ?? 0;
72
+ const endTime = keyframes[keyframes.length - 1]?.time ?? startTime;
73
+ return {
74
+ propertyPath,
75
+ keyframeCount: keyframes.length,
76
+ bezierSegmentCount: keyframes.filter((keyframe) => keyframe.interpolation === "bezier").length,
77
+ sampledPointCount: this.samplePoints(clip, propertyPath, startTime, endTime, Math.max(1, sampleCount)).length,
78
+ evidence: {
79
+ deterministicSampling: true,
80
+ bezierHandles: keyframes.some((keyframe) => keyframe.inHandle || keyframe.outHandle),
81
+ holdInterpolation: keyframes.some((keyframe) => keyframe.interpolation === "hold")
82
+ }
83
+ };
84
+ }
85
+ }
86
+ function propertyKeyframes(clip, propertyPath) {
87
+ return readTimelineKeyframes(clip).filter((keyframe) => keyframe.propertyPath === propertyPath);
88
+ }
89
+ function sampleSegment(start, end, time) {
90
+ if (start.interpolation === "hold" || typeof start.value !== "number" || typeof end.value !== "number") {
91
+ return start.value;
92
+ }
93
+ const duration = end.time - start.time;
94
+ const t = duration <= 0 ? 1 : clamp((time - start.time) / duration, 0, 1);
95
+ if (start.interpolation !== "bezier") {
96
+ return Number((start.value + (end.value - start.value) * t).toFixed(4));
97
+ }
98
+ const p0 = start.value;
99
+ const p1 = start.value + (start.outHandle?.value ?? 0);
100
+ const p2 = end.value + (end.inHandle?.value ?? 0);
101
+ const p3 = end.value;
102
+ const inv = 1 - t;
103
+ return Number((inv * inv * inv * p0 + 3 * inv * inv * t * p1 + 3 * inv * t * t * p2 + t * t * t * p3).toFixed(4));
104
+ }
105
+ function assertFinite(value, label) {
106
+ if (!Number.isFinite(value))
107
+ throw new RangeError(`${label} must be finite.`);
108
+ }
109
+ function clamp(value, min, max) {
110
+ return Math.max(min, Math.min(max, value));
111
+ }
112
+ //# sourceMappingURL=CurveEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CurveEditor.js","sourceRoot":"","sources":["../../../../packages/editor-runtime/src/CurveEditor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { CommandHistory } from "./CommandHistory";
2
+ import type { TimelineClip } from "./TimelineModel";
3
+ export type TimelineKeyframeValue = number | string | boolean;
4
+ export type TimelineKeyframeInterpolation = "hold" | "linear" | "bezier";
5
+ export interface TimelineBezierHandle {
6
+ readonly time: number;
7
+ readonly value: number;
8
+ }
9
+ export interface TimelineKeyframe {
10
+ readonly id: string;
11
+ readonly propertyPath: string;
12
+ readonly time: number;
13
+ readonly value: TimelineKeyframeValue;
14
+ readonly interpolation: TimelineKeyframeInterpolation;
15
+ readonly inHandle?: TimelineBezierHandle;
16
+ readonly outHandle?: TimelineBezierHandle;
17
+ }
18
+ export interface CreateTimelineKeyframeOptions {
19
+ readonly id?: string;
20
+ readonly propertyPath: string;
21
+ readonly time: number;
22
+ readonly value: TimelineKeyframeValue;
23
+ readonly interpolation?: TimelineKeyframeInterpolation;
24
+ readonly inHandle?: TimelineBezierHandle;
25
+ readonly outHandle?: TimelineBezierHandle;
26
+ }
27
+ export interface PasteTimelineKeyframesOptions {
28
+ readonly timeOffset?: number;
29
+ readonly idPrefix?: string;
30
+ readonly propertyPath?: string;
31
+ }
32
+ export declare function readTimelineKeyframes(clip: TimelineClip): readonly TimelineKeyframe[];
33
+ export declare function encodeTimelineKeyframes(keyframes: readonly TimelineKeyframe[]): string;
34
+ export declare function timelineKeyframesByProperty(clip: TimelineClip, propertyPath: string): readonly TimelineKeyframe[];
35
+ export declare class KeyframeEditor {
36
+ private readonly history;
37
+ constructor(history?: CommandHistory);
38
+ get commandHistory(): CommandHistory;
39
+ keyframes(clip: TimelineClip, propertyPath?: string): readonly TimelineKeyframe[];
40
+ addKeyframe(clip: TimelineClip, options: CreateTimelineKeyframeOptions): Promise<TimelineKeyframe>;
41
+ deleteKeyframes(clip: TimelineClip, ids: readonly string[]): Promise<void>;
42
+ moveKeyframes(clip: TimelineClip, ids: readonly string[], deltaTime: number): Promise<readonly TimelineKeyframe[]>;
43
+ scaleKeyframes(clip: TimelineClip, ids: readonly string[], pivotTime: number, scale: number): Promise<readonly TimelineKeyframe[]>;
44
+ copyKeyframes(clip: TimelineClip, ids: readonly string[]): readonly TimelineKeyframe[];
45
+ pasteKeyframes(clip: TimelineClip, keyframes: readonly TimelineKeyframe[], options?: PasteTimelineKeyframesOptions): Promise<readonly TimelineKeyframe[]>;
46
+ replaceKeyframes(clip: TimelineClip, keyframes: readonly TimelineKeyframe[], label?: string): Promise<void>;
47
+ private applyKeyframes;
48
+ }
49
+ //# sourceMappingURL=KeyframeEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyframeEditor.d.ts","sourceRoot":"","sources":["../../../../packages/editor-runtime/src/KeyframeEditor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ import { CommandHistory } from "./CommandHistory.js";
2
+ const KEYFRAME_PROPERTY = "auraKeyframes";
3
+ export function readTimelineKeyframes(clip) {
4
+ const encoded = clip.properties[KEYFRAME_PROPERTY];
5
+ if (typeof encoded !== "string" || encoded.trim().length === 0)
6
+ return [];
7
+ const parsed = JSON.parse(encoded);
8
+ if (!Array.isArray(parsed)) {
9
+ throw new Error(`Timeline clip keyframes must decode to an array: ${clip.id}`);
10
+ }
11
+ return parsed.map(normalizeKeyframe).sort(compareKeyframes);
12
+ }
13
+ export function encodeTimelineKeyframes(keyframes) {
14
+ return JSON.stringify([...keyframes].map(normalizeKeyframe).sort(compareKeyframes));
15
+ }
16
+ export function timelineKeyframesByProperty(clip, propertyPath) {
17
+ return readTimelineKeyframes(clip).filter((keyframe) => keyframe.propertyPath === propertyPath);
18
+ }
19
+ export class KeyframeEditor {
20
+ history;
21
+ constructor(history = new CommandHistory()) {
22
+ this.history = history;
23
+ }
24
+ get commandHistory() {
25
+ return this.history;
26
+ }
27
+ keyframes(clip, propertyPath) {
28
+ const keyframes = readTimelineKeyframes(clip);
29
+ return propertyPath ? keyframes.filter((keyframe) => keyframe.propertyPath === propertyPath) : keyframes;
30
+ }
31
+ async addKeyframe(clip, options) {
32
+ const keyframe = normalizeKeyframe({
33
+ id: options.id ?? stableKeyframeId(options.propertyPath, options.time),
34
+ propertyPath: options.propertyPath,
35
+ time: options.time,
36
+ value: options.value,
37
+ interpolation: options.interpolation ?? "linear",
38
+ inHandle: options.inHandle,
39
+ outHandle: options.outHandle
40
+ });
41
+ const next = [...readTimelineKeyframes(clip).filter((candidate) => candidate.id !== keyframe.id), keyframe];
42
+ await this.applyKeyframes(clip, next, `Add keyframe ${keyframe.id}`);
43
+ return keyframe;
44
+ }
45
+ async deleteKeyframes(clip, ids) {
46
+ const remove = new Set(ids);
47
+ await this.applyKeyframes(clip, readTimelineKeyframes(clip).filter((keyframe) => !remove.has(keyframe.id)), `Delete ${ids.length} keyframes`);
48
+ }
49
+ async moveKeyframes(clip, ids, deltaTime) {
50
+ assertFinite(deltaTime, "Keyframe deltaTime");
51
+ const move = new Set(ids);
52
+ const next = readTimelineKeyframes(clip).map((keyframe) => move.has(keyframe.id)
53
+ ? normalizeKeyframe({ ...keyframe, time: Math.max(0, keyframe.time + deltaTime) })
54
+ : keyframe);
55
+ await this.applyKeyframes(clip, next, `Move ${ids.length} keyframes`);
56
+ return next.filter((keyframe) => move.has(keyframe.id));
57
+ }
58
+ async scaleKeyframes(clip, ids, pivotTime, scale) {
59
+ assertFinite(pivotTime, "Keyframe pivotTime");
60
+ assertFinite(scale, "Keyframe scale");
61
+ if (scale <= 0)
62
+ throw new RangeError("Keyframe scale must be positive.");
63
+ const scaleIds = new Set(ids);
64
+ const next = readTimelineKeyframes(clip).map((keyframe) => scaleIds.has(keyframe.id)
65
+ ? normalizeKeyframe({ ...keyframe, time: Math.max(0, pivotTime + (keyframe.time - pivotTime) * scale) })
66
+ : keyframe);
67
+ await this.applyKeyframes(clip, next, `Scale ${ids.length} keyframes`);
68
+ return next.filter((keyframe) => scaleIds.has(keyframe.id));
69
+ }
70
+ copyKeyframes(clip, ids) {
71
+ const copy = new Set(ids);
72
+ return readTimelineKeyframes(clip).filter((keyframe) => copy.has(keyframe.id)).map((keyframe) => ({ ...keyframe }));
73
+ }
74
+ async pasteKeyframes(clip, keyframes, options = {}) {
75
+ const timeOffset = options.timeOffset ?? 0;
76
+ assertFinite(timeOffset, "Paste keyframe timeOffset");
77
+ const prefix = options.idPrefix ?? "pasted";
78
+ const pasted = keyframes.map((keyframe, index) => normalizeKeyframe({
79
+ ...keyframe,
80
+ id: `${prefix}-${keyframe.id}-${index}`,
81
+ propertyPath: options.propertyPath ?? keyframe.propertyPath,
82
+ time: Math.max(0, keyframe.time + timeOffset)
83
+ }));
84
+ await this.applyKeyframes(clip, [...readTimelineKeyframes(clip), ...pasted], `Paste ${pasted.length} keyframes`);
85
+ return pasted;
86
+ }
87
+ async replaceKeyframes(clip, keyframes, label = "Replace keyframes") {
88
+ await this.applyKeyframes(clip, keyframes, label);
89
+ }
90
+ async applyKeyframes(clip, keyframes, name) {
91
+ await this.history.execute(new SetClipKeyframesCommand(clip, keyframes, name));
92
+ }
93
+ }
94
+ class SetClipKeyframesCommand {
95
+ clip;
96
+ name;
97
+ before;
98
+ after;
99
+ constructor(clip, keyframes, name) {
100
+ this.clip = clip;
101
+ this.name = name;
102
+ this.before = readTimelineKeyframes(clip);
103
+ this.after = [...keyframes].map(normalizeKeyframe).sort(compareKeyframes);
104
+ }
105
+ execute() {
106
+ this.write(this.after);
107
+ }
108
+ undo() {
109
+ this.write(this.before);
110
+ }
111
+ write(keyframes) {
112
+ if (keyframes.length === 0) {
113
+ delete this.clip.properties[KEYFRAME_PROPERTY];
114
+ return;
115
+ }
116
+ this.clip.properties[KEYFRAME_PROPERTY] = encodeTimelineKeyframes(keyframes);
117
+ }
118
+ }
119
+ function normalizeKeyframe(keyframe) {
120
+ if (!keyframe.id.trim())
121
+ throw new Error("Timeline keyframe id is required.");
122
+ if (!keyframe.propertyPath.trim())
123
+ throw new Error("Timeline keyframe propertyPath is required.");
124
+ assertFinite(keyframe.time, "Timeline keyframe time");
125
+ if (keyframe.time < 0)
126
+ throw new RangeError("Timeline keyframe time must be non-negative.");
127
+ validateKeyframeValue(keyframe.value);
128
+ validateHandle(keyframe.inHandle, "inHandle");
129
+ validateHandle(keyframe.outHandle, "outHandle");
130
+ return {
131
+ id: keyframe.id,
132
+ propertyPath: keyframe.propertyPath,
133
+ time: Number(keyframe.time.toFixed(4)),
134
+ value: keyframe.value,
135
+ interpolation: keyframe.interpolation,
136
+ inHandle: keyframe.inHandle,
137
+ outHandle: keyframe.outHandle
138
+ };
139
+ }
140
+ function validateKeyframeValue(value) {
141
+ if (typeof value === "number" && !Number.isFinite(value)) {
142
+ throw new Error("Timeline keyframe numeric values must be finite.");
143
+ }
144
+ }
145
+ function validateHandle(handle, label) {
146
+ if (!handle)
147
+ return;
148
+ assertFinite(handle.time, `Timeline keyframe ${label}.time`);
149
+ assertFinite(handle.value, `Timeline keyframe ${label}.value`);
150
+ }
151
+ function assertFinite(value, label) {
152
+ if (!Number.isFinite(value))
153
+ throw new RangeError(`${label} must be finite.`);
154
+ }
155
+ function compareKeyframes(left, right) {
156
+ return left.time - right.time || left.propertyPath.localeCompare(right.propertyPath) || left.id.localeCompare(right.id);
157
+ }
158
+ function stableKeyframeId(propertyPath, time) {
159
+ return `key-${propertyPath.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "value"}-${Number(time.toFixed(4)).toString().replace(".", "-")}`;
160
+ }
161
+ //# sourceMappingURL=KeyframeEditor.js.map