@certe/atmos-editor 0.1.0

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 (234) hide show
  1. package/LICENCE +674 -0
  2. package/README.md +206 -0
  3. package/dist/asset-browser-client.d.ts +24 -0
  4. package/dist/asset-browser-client.d.ts.map +1 -0
  5. package/dist/asset-browser-client.js +60 -0
  6. package/dist/asset-browser-client.js.map +1 -0
  7. package/dist/asset-types.d.ts +33 -0
  8. package/dist/asset-types.d.ts.map +1 -0
  9. package/dist/asset-types.js +2 -0
  10. package/dist/asset-types.js.map +1 -0
  11. package/dist/bootstrap/default-factories.d.ts +38 -0
  12. package/dist/bootstrap/default-factories.d.ts.map +1 -0
  13. package/dist/bootstrap/default-factories.js +268 -0
  14. package/dist/bootstrap/default-factories.js.map +1 -0
  15. package/dist/bootstrap/editor-physics.d.ts +81 -0
  16. package/dist/bootstrap/editor-physics.d.ts.map +1 -0
  17. package/dist/bootstrap/editor-physics.js +512 -0
  18. package/dist/bootstrap/editor-physics.js.map +1 -0
  19. package/dist/bootstrap/geometry-cache.d.ts +5 -0
  20. package/dist/bootstrap/geometry-cache.d.ts.map +1 -0
  21. package/dist/bootstrap/geometry-cache.js +18 -0
  22. package/dist/bootstrap/geometry-cache.js.map +1 -0
  23. package/dist/bootstrap/keyboard-shortcuts.d.ts +4 -0
  24. package/dist/bootstrap/keyboard-shortcuts.d.ts.map +1 -0
  25. package/dist/bootstrap/keyboard-shortcuts.js +43 -0
  26. package/dist/bootstrap/keyboard-shortcuts.js.map +1 -0
  27. package/dist/bootstrap/model-import.d.ts +9 -0
  28. package/dist/bootstrap/model-import.d.ts.map +1 -0
  29. package/dist/bootstrap/model-import.js +55 -0
  30. package/dist/bootstrap/model-import.js.map +1 -0
  31. package/dist/bootstrap/start-editor.d.ts +3 -0
  32. package/dist/bootstrap/start-editor.d.ts.map +1 -0
  33. package/dist/bootstrap/start-editor.js +506 -0
  34. package/dist/bootstrap/start-editor.js.map +1 -0
  35. package/dist/bootstrap/start-player.d.ts +23 -0
  36. package/dist/bootstrap/start-player.d.ts.map +1 -0
  37. package/dist/bootstrap/start-player.js +205 -0
  38. package/dist/bootstrap/start-player.js.map +1 -0
  39. package/dist/bootstrap/types.d.ts +160 -0
  40. package/dist/bootstrap/types.d.ts.map +1 -0
  41. package/dist/bootstrap/types.js +2 -0
  42. package/dist/bootstrap/types.js.map +1 -0
  43. package/dist/camera-frustum-renderer.d.ts +15 -0
  44. package/dist/camera-frustum-renderer.d.ts.map +1 -0
  45. package/dist/camera-frustum-renderer.js +110 -0
  46. package/dist/camera-frustum-renderer.js.map +1 -0
  47. package/dist/camera-presets.d.ts +10 -0
  48. package/dist/camera-presets.d.ts.map +1 -0
  49. package/dist/camera-presets.js +15 -0
  50. package/dist/camera-presets.js.map +1 -0
  51. package/dist/collider-gizmo-renderer.d.ts +13 -0
  52. package/dist/collider-gizmo-renderer.d.ts.map +1 -0
  53. package/dist/collider-gizmo-renderer.js +217 -0
  54. package/dist/collider-gizmo-renderer.js.map +1 -0
  55. package/dist/color-utils.d.ts +5 -0
  56. package/dist/color-utils.d.ts.map +1 -0
  57. package/dist/color-utils.js +13 -0
  58. package/dist/color-utils.js.map +1 -0
  59. package/dist/components/asset-browser-panel.d.ts +14 -0
  60. package/dist/components/asset-browser-panel.d.ts.map +1 -0
  61. package/dist/components/asset-browser-panel.js +247 -0
  62. package/dist/components/asset-browser-panel.js.map +1 -0
  63. package/dist/components/context-menu.d.ts +14 -0
  64. package/dist/components/context-menu.d.ts.map +1 -0
  65. package/dist/components/context-menu.js +48 -0
  66. package/dist/components/context-menu.js.map +1 -0
  67. package/dist/components/editor-shell.d.ts +27 -0
  68. package/dist/components/editor-shell.d.ts.map +1 -0
  69. package/dist/components/editor-shell.js +327 -0
  70. package/dist/components/editor-shell.js.map +1 -0
  71. package/dist/components/fields/boolean-field.d.ts +8 -0
  72. package/dist/components/fields/boolean-field.d.ts.map +1 -0
  73. package/dist/components/fields/boolean-field.js +11 -0
  74. package/dist/components/fields/boolean-field.js.map +1 -0
  75. package/dist/components/fields/color-field.d.ts +8 -0
  76. package/dist/components/fields/color-field.d.ts.map +1 -0
  77. package/dist/components/fields/color-field.js +34 -0
  78. package/dist/components/fields/color-field.js.map +1 -0
  79. package/dist/components/fields/decimal-input.d.ts +13 -0
  80. package/dist/components/fields/decimal-input.d.ts.map +1 -0
  81. package/dist/components/fields/decimal-input.js +49 -0
  82. package/dist/components/fields/decimal-input.js.map +1 -0
  83. package/dist/components/fields/enum-field.d.ts +12 -0
  84. package/dist/components/fields/enum-field.d.ts.map +1 -0
  85. package/dist/components/fields/enum-field.js +20 -0
  86. package/dist/components/fields/enum-field.js.map +1 -0
  87. package/dist/components/fields/game-object-ref-field.d.ts +11 -0
  88. package/dist/components/fields/game-object-ref-field.d.ts.map +1 -0
  89. package/dist/components/fields/game-object-ref-field.js +73 -0
  90. package/dist/components/fields/game-object-ref-field.js.map +1 -0
  91. package/dist/components/fields/material-asset-field.d.ts +10 -0
  92. package/dist/components/fields/material-asset-field.d.ts.map +1 -0
  93. package/dist/components/fields/material-asset-field.js +114 -0
  94. package/dist/components/fields/material-asset-field.js.map +1 -0
  95. package/dist/components/fields/number-field.d.ts +10 -0
  96. package/dist/components/fields/number-field.d.ts.map +1 -0
  97. package/dist/components/fields/number-field.js +21 -0
  98. package/dist/components/fields/number-field.js.map +1 -0
  99. package/dist/components/fields/quat-field.d.ts +8 -0
  100. package/dist/components/fields/quat-field.d.ts.map +1 -0
  101. package/dist/components/fields/quat-field.js +43 -0
  102. package/dist/components/fields/quat-field.js.map +1 -0
  103. package/dist/components/fields/string-field.d.ts +7 -0
  104. package/dist/components/fields/string-field.d.ts.map +1 -0
  105. package/dist/components/fields/string-field.js +20 -0
  106. package/dist/components/fields/string-field.js.map +1 -0
  107. package/dist/components/fields/vec3-field.d.ts +8 -0
  108. package/dist/components/fields/vec3-field.d.ts.map +1 -0
  109. package/dist/components/fields/vec3-field.js +30 -0
  110. package/dist/components/fields/vec3-field.js.map +1 -0
  111. package/dist/components/hierarchy-node.d.ts +18 -0
  112. package/dist/components/hierarchy-node.d.ts.map +1 -0
  113. package/dist/components/hierarchy-node.js +77 -0
  114. package/dist/components/hierarchy-node.js.map +1 -0
  115. package/dist/components/hierarchy-panel.d.ts +14 -0
  116. package/dist/components/hierarchy-panel.d.ts.map +1 -0
  117. package/dist/components/hierarchy-panel.js +228 -0
  118. package/dist/components/hierarchy-panel.js.map +1 -0
  119. package/dist/components/inspector-panel.d.ts +14 -0
  120. package/dist/components/inspector-panel.d.ts.map +1 -0
  121. package/dist/components/inspector-panel.js +288 -0
  122. package/dist/components/inspector-panel.js.map +1 -0
  123. package/dist/components/material-inspector.d.ts +10 -0
  124. package/dist/components/material-inspector.d.ts.map +1 -0
  125. package/dist/components/material-inspector.js +130 -0
  126. package/dist/components/material-inspector.js.map +1 -0
  127. package/dist/components/post-process-panel.d.ts +9 -0
  128. package/dist/components/post-process-panel.d.ts.map +1 -0
  129. package/dist/components/post-process-panel.js +70 -0
  130. package/dist/components/post-process-panel.js.map +1 -0
  131. package/dist/components/project-gate.d.ts +8 -0
  132. package/dist/components/project-gate.d.ts.map +1 -0
  133. package/dist/components/project-gate.js +87 -0
  134. package/dist/components/project-gate.js.map +1 -0
  135. package/dist/components/settings-panel.d.ts +8 -0
  136. package/dist/components/settings-panel.d.ts.map +1 -0
  137. package/dist/components/settings-panel.js +108 -0
  138. package/dist/components/settings-panel.js.map +1 -0
  139. package/dist/components/use-splitter.d.ts +4 -0
  140. package/dist/components/use-splitter.d.ts.map +1 -0
  141. package/dist/components/use-splitter.js +22 -0
  142. package/dist/components/use-splitter.js.map +1 -0
  143. package/dist/editor-mount.d.ts +36 -0
  144. package/dist/editor-mount.d.ts.map +1 -0
  145. package/dist/editor-mount.js +161 -0
  146. package/dist/editor-mount.js.map +1 -0
  147. package/dist/editor-state.d.ts +55 -0
  148. package/dist/editor-state.d.ts.map +1 -0
  149. package/dist/editor-state.js +181 -0
  150. package/dist/editor-state.js.map +1 -0
  151. package/dist/gizmo-meshes.d.ts +9 -0
  152. package/dist/gizmo-meshes.d.ts.map +1 -0
  153. package/dist/gizmo-meshes.js +229 -0
  154. package/dist/gizmo-meshes.js.map +1 -0
  155. package/dist/gizmo-renderer.d.ts +16 -0
  156. package/dist/gizmo-renderer.d.ts.map +1 -0
  157. package/dist/gizmo-renderer.js +77 -0
  158. package/dist/gizmo-renderer.js.map +1 -0
  159. package/dist/gizmo-state.d.ts +25 -0
  160. package/dist/gizmo-state.d.ts.map +1 -0
  161. package/dist/gizmo-state.js +269 -0
  162. package/dist/gizmo-state.js.map +1 -0
  163. package/dist/index.d.ts +33 -0
  164. package/dist/index.d.ts.map +1 -0
  165. package/dist/index.js +22 -0
  166. package/dist/index.js.map +1 -0
  167. package/dist/joint-gizmo-renderer.d.ts +13 -0
  168. package/dist/joint-gizmo-renderer.d.ts.map +1 -0
  169. package/dist/joint-gizmo-renderer.js +133 -0
  170. package/dist/joint-gizmo-renderer.js.map +1 -0
  171. package/dist/material-manager.d.ts +22 -0
  172. package/dist/material-manager.d.ts.map +1 -0
  173. package/dist/material-manager.js +156 -0
  174. package/dist/material-manager.js.map +1 -0
  175. package/dist/object-picker.d.ts +11 -0
  176. package/dist/object-picker.d.ts.map +1 -0
  177. package/dist/object-picker.js +104 -0
  178. package/dist/object-picker.js.map +1 -0
  179. package/dist/orbit-camera.d.ts +38 -0
  180. package/dist/orbit-camera.d.ts.map +1 -0
  181. package/dist/orbit-camera.js +180 -0
  182. package/dist/orbit-camera.js.map +1 -0
  183. package/dist/overlay-renderer.d.ts +23 -0
  184. package/dist/overlay-renderer.d.ts.map +1 -0
  185. package/dist/overlay-renderer.js +95 -0
  186. package/dist/overlay-renderer.js.map +1 -0
  187. package/dist/player-entry.d.ts +6 -0
  188. package/dist/player-entry.d.ts.map +1 -0
  189. package/dist/player-entry.js +4 -0
  190. package/dist/player-entry.js.map +1 -0
  191. package/dist/project-fs.d.ts +28 -0
  192. package/dist/project-fs.d.ts.map +1 -0
  193. package/dist/project-fs.js +258 -0
  194. package/dist/project-fs.js.map +1 -0
  195. package/dist/project-seed.d.ts +3 -0
  196. package/dist/project-seed.d.ts.map +1 -0
  197. package/dist/project-seed.js +35 -0
  198. package/dist/project-seed.js.map +1 -0
  199. package/dist/project-settings.d.ts +29 -0
  200. package/dist/project-settings.d.ts.map +1 -0
  201. package/dist/project-settings.js +69 -0
  202. package/dist/project-settings.js.map +1 -0
  203. package/dist/property-setters.d.ts +4 -0
  204. package/dist/property-setters.d.ts.map +1 -0
  205. package/dist/property-setters.js +58 -0
  206. package/dist/property-setters.js.map +1 -0
  207. package/dist/scene-operations.d.ts +14 -0
  208. package/dist/scene-operations.d.ts.map +1 -0
  209. package/dist/scene-operations.js +195 -0
  210. package/dist/scene-operations.js.map +1 -0
  211. package/dist/scene-snapshot.d.ts +28 -0
  212. package/dist/scene-snapshot.d.ts.map +1 -0
  213. package/dist/scene-snapshot.js +97 -0
  214. package/dist/scene-snapshot.js.map +1 -0
  215. package/dist/script-discovery.d.ts +12 -0
  216. package/dist/script-discovery.d.ts.map +1 -0
  217. package/dist/script-discovery.js +81 -0
  218. package/dist/script-discovery.js.map +1 -0
  219. package/dist/selection-utils.d.ts +4 -0
  220. package/dist/selection-utils.d.ts.map +1 -0
  221. package/dist/selection-utils.js +19 -0
  222. package/dist/selection-utils.js.map +1 -0
  223. package/dist/simple-material-loader.d.ts +17 -0
  224. package/dist/simple-material-loader.d.ts.map +1 -0
  225. package/dist/simple-material-loader.js +85 -0
  226. package/dist/simple-material-loader.js.map +1 -0
  227. package/dist/wireframe-renderer.d.ts +18 -0
  228. package/dist/wireframe-renderer.d.ts.map +1 -0
  229. package/dist/wireframe-renderer.js +106 -0
  230. package/dist/wireframe-renderer.js.map +1 -0
  231. package/package.json +65 -0
  232. package/src/index.ts +48 -0
  233. package/vite-plugin.d.ts +15 -0
  234. package/vite-plugin.mjs +395 -0
@@ -0,0 +1,3 @@
1
+ import type { ProjectFileSystem } from './project-fs.js';
2
+ export declare function seedProject(projectFs: ProjectFileSystem): Promise<void>;
3
+ //# sourceMappingURL=project-seed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-seed.d.ts","sourceRoot":"","sources":["../src/project-seed.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAczD,wBAAsB,WAAW,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7E"}
@@ -0,0 +1,35 @@
1
+ import { serializeMaterialAsset } from '@certe/atmos-renderer';
2
+ import { DEFAULT_PROJECT_SETTINGS } from './project-settings.js';
3
+ const SEED_MATERIALS = {
4
+ default: { shader: 'pbr', albedo: [0.7, 0.7, 0.7, 1], metallic: 0, roughness: 0.5 },
5
+ metal: { shader: 'pbr', albedo: [0.8, 0.8, 0.85, 1], metallic: 1, roughness: 0.3 },
6
+ gold: { shader: 'pbr', albedo: [1.0, 0.76, 0.34, 1], metallic: 1, roughness: 0.35 },
7
+ copper: { shader: 'pbr', albedo: [0.95, 0.64, 0.54, 1], metallic: 1, roughness: 0.4 },
8
+ plastic: { shader: 'pbr', albedo: [0.8, 0.2, 0.2, 1], metallic: 0, roughness: 0.4 },
9
+ rubber: { shader: 'pbr', albedo: [0.15, 0.15, 0.15, 1], metallic: 0, roughness: 0.95 },
10
+ wood: { shader: 'pbr', albedo: [0.55, 0.35, 0.18, 1], metallic: 0, roughness: 0.7 },
11
+ glass: { shader: 'pbr', albedo: [0.9, 0.95, 1.0, 1], metallic: 0, roughness: 0.1 },
12
+ };
13
+ export async function seedProject(projectFs) {
14
+ // Only seed if materials/ doesn't exist yet
15
+ const hasDir = await projectFs.exists('materials');
16
+ if (hasDir)
17
+ return;
18
+ await projectFs.ensureDir('materials');
19
+ await projectFs.ensureDir('scenes');
20
+ const writes = [];
21
+ for (const [key, params] of Object.entries(SEED_MATERIALS)) {
22
+ const name = key.charAt(0).toUpperCase() + key.slice(1);
23
+ const data = { name, ...params };
24
+ const json = serializeMaterialAsset(data);
25
+ writes.push(projectFs.writeFile(`materials/${key}.mat.json`, json));
26
+ }
27
+ // Empty scene
28
+ writes.push(projectFs.writeFile('scenes/main.scene.json', '{}'));
29
+ // Default project settings
30
+ if (!(await projectFs.exists('project-settings.json'))) {
31
+ writes.push(projectFs.writeFile('project-settings.json', JSON.stringify(DEFAULT_PROJECT_SETTINGS, null, 2)));
32
+ }
33
+ await Promise.all(writes);
34
+ }
35
+ //# sourceMappingURL=project-seed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-seed.js","sourceRoot":"","sources":["../src/project-seed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ProjectFileSystem } from './project-fs.js';
2
+ export interface PhysicsSettings {
3
+ gravity: [number, number, number];
4
+ fixedTimestep: number;
5
+ solverIterations: number;
6
+ substeps: number;
7
+ }
8
+ export interface ProjectSettings {
9
+ defaultScene?: string;
10
+ physics: PhysicsSettings;
11
+ }
12
+ export declare const DEFAULT_PHYSICS_SETTINGS: PhysicsSettings;
13
+ export declare const DEFAULT_PROJECT_SETTINGS: ProjectSettings;
14
+ type ChangeListener = () => void;
15
+ export declare class ProjectSettingsManager {
16
+ private _settings;
17
+ private readonly _fs;
18
+ private readonly _listeners;
19
+ constructor(fs: ProjectFileSystem);
20
+ get settings(): Readonly<ProjectSettings>;
21
+ load(): Promise<void>;
22
+ save(): Promise<void>;
23
+ updateDefaultScene(name: string): Promise<void>;
24
+ updatePhysics(partial: Partial<PhysicsSettings>): Promise<void>;
25
+ onChange(fn: ChangeListener): () => void;
26
+ private _notify;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=project-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-settings.d.ts","sourceRoot":"","sources":["../src/project-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,eAAO,MAAM,wBAAwB,EAAE,eAKtC,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,eAEtC,CAAC;AAIF,KAAK,cAAc,GAAG,MAAM,IAAI,CAAC;AAEjC,qBAAa,sBAAsB;IACjC,OAAO,CAAC,SAAS,CAAwD;IACzE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;gBAE5C,EAAE,EAAE,iBAAiB;IAIjC,IAAI,QAAQ,IAAI,QAAQ,CAAC,eAAe,CAAC,CAExC;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAarB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrE,QAAQ,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,IAAI;IAKxC,OAAO,CAAC,OAAO;CAGhB"}
@@ -0,0 +1,69 @@
1
+ export const DEFAULT_PHYSICS_SETTINGS = {
2
+ gravity: [0, -9.81, 0],
3
+ fixedTimestep: 1 / 60,
4
+ solverIterations: 8,
5
+ substeps: 1,
6
+ };
7
+ export const DEFAULT_PROJECT_SETTINGS = {
8
+ physics: { ...DEFAULT_PHYSICS_SETTINGS },
9
+ };
10
+ const SETTINGS_PATH = 'project-settings.json';
11
+ export class ProjectSettingsManager {
12
+ _settings = deepClone(DEFAULT_PROJECT_SETTINGS);
13
+ _fs;
14
+ _listeners = new Set();
15
+ constructor(fs) {
16
+ this._fs = fs;
17
+ }
18
+ get settings() {
19
+ return this._settings;
20
+ }
21
+ async load() {
22
+ try {
23
+ if (await this._fs.exists(SETTINGS_PATH)) {
24
+ const json = await this._fs.readTextFile(SETTINGS_PATH);
25
+ const data = JSON.parse(json);
26
+ this._settings = deepMerge(DEFAULT_PROJECT_SETTINGS, data);
27
+ }
28
+ }
29
+ catch (err) {
30
+ console.warn('[ProjectSettings] Failed to load, using defaults:', err);
31
+ this._settings = deepClone(DEFAULT_PROJECT_SETTINGS);
32
+ }
33
+ }
34
+ async save() {
35
+ const json = JSON.stringify(this._settings, null, 2);
36
+ await this._fs.writeFile(SETTINGS_PATH, json);
37
+ }
38
+ async updateDefaultScene(name) {
39
+ this._settings.defaultScene = name;
40
+ await this.save();
41
+ }
42
+ async updatePhysics(partial) {
43
+ Object.assign(this._settings.physics, partial);
44
+ this._notify();
45
+ await this.save();
46
+ }
47
+ onChange(fn) {
48
+ this._listeners.add(fn);
49
+ return () => { this._listeners.delete(fn); };
50
+ }
51
+ _notify() {
52
+ for (const fn of this._listeners)
53
+ fn();
54
+ }
55
+ }
56
+ function deepClone(obj) {
57
+ return JSON.parse(JSON.stringify(obj));
58
+ }
59
+ function deepMerge(defaults, overrides) {
60
+ const result = deepClone(defaults);
61
+ if (overrides.defaultScene !== undefined) {
62
+ result.defaultScene = overrides.defaultScene;
63
+ }
64
+ if (overrides.physics) {
65
+ Object.assign(result.physics, overrides.physics);
66
+ }
67
+ return result;
68
+ }
69
+ //# sourceMappingURL=project-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-settings.js","sourceRoot":"","sources":["../src/project-settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PropertyDef } from '@certe/atmos-core';
2
+ export declare function getProperty(component: unknown, def: PropertyDef): unknown;
3
+ export declare function setProperty(component: unknown, def: PropertyDef, value: unknown): void;
4
+ //# sourceMappingURL=property-setters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-setters.d.ts","sourceRoot":"","sources":["../src/property-setters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAarD,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAUzE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAoCtF"}
@@ -0,0 +1,58 @@
1
+ import { Transform } from '@certe/atmos-core';
2
+ function navigatePath(obj, parts) {
3
+ let current = obj;
4
+ for (let i = 0; i < parts.length - 1; i++) {
5
+ if (current == null || typeof current !== 'object')
6
+ return null;
7
+ current = current[parts[i]];
8
+ }
9
+ if (current == null || typeof current !== 'object')
10
+ return null;
11
+ return { target: current, key: parts[parts.length - 1] };
12
+ }
13
+ export function getProperty(component, def) {
14
+ const parts = def.key.split('.');
15
+ const nav = navigatePath(component, parts);
16
+ if (!nav)
17
+ return undefined;
18
+ const value = nav.target[nav.key];
19
+ if (value instanceof Float32Array) {
20
+ return Array.from(value);
21
+ }
22
+ return value;
23
+ }
24
+ export function setProperty(component, def, value) {
25
+ const parts = def.key.split('.');
26
+ const nav = navigatePath(component, parts);
27
+ if (!nav)
28
+ return;
29
+ const existing = nav.target[nav.key];
30
+ if (existing instanceof Float32Array && Array.isArray(value)) {
31
+ for (let i = 0; i < value.length && i < existing.length; i++) {
32
+ existing[i] = value[i];
33
+ }
34
+ // Re-assign to trigger setter (e.g. HingeJoint.axis recreates joint)
35
+ nav.target[nav.key] = existing;
36
+ }
37
+ else {
38
+ nav.target[nav.key] = value;
39
+ }
40
+ // Notify transform so the scene re-renders immediately
41
+ const transform = component instanceof Transform
42
+ ? component
43
+ : component['gameObject']
44
+ ? component['gameObject']['transform']
45
+ : null;
46
+ if (transform instanceof Transform) {
47
+ // Re-apply via setters to trigger dirty flag
48
+ transform.setPositionFrom(transform.position);
49
+ transform.setRotationFrom(transform.rotation);
50
+ transform.setScaleFrom(transform.scale);
51
+ }
52
+ // If we navigated through 'material', mark it dirty
53
+ const comp = component;
54
+ if (parts[0] === 'material' && comp['material']) {
55
+ comp['material']['dirty'] = true;
56
+ }
57
+ }
58
+ //# sourceMappingURL=property-setters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-setters.js","sourceRoot":"","sources":["../src/property-setters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Scene, GameObject } from '@certe/atmos-core';
2
+ import type { EditorState } from './editor-state.js';
3
+ export type ReparentValidator = (child: GameObject, newParent: GameObject | null) => boolean;
4
+ export type ReparentCallback = (child: GameObject) => void;
5
+ export type DuplicateCallback = (copy: GameObject, source: GameObject) => void;
6
+ export declare function setReparentValidator(fn: ReparentValidator | null): void;
7
+ export declare function setOnReparent(fn: ReparentCallback | null): void;
8
+ export declare function setOnDuplicate(fn: DuplicateCallback | null): void;
9
+ export declare function findObjectById(scene: Scene, id: number): GameObject | null;
10
+ export declare function duplicateGameObject(scene: Scene, source: GameObject): GameObject;
11
+ export declare function deleteGameObject(scene: Scene, target: GameObject, editorState: EditorState): void;
12
+ export declare function canReparent(child: GameObject, newParent: GameObject | null): boolean;
13
+ export declare function reparentGameObject(scene: Scene, child: GameObject, newParent: GameObject | null): void;
14
+ //# sourceMappingURL=scene-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-operations.d.ts","sourceRoot":"","sources":["../src/scene-operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAItE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOrD,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,IAAI,KAAK,OAAO,CAAC;AAC7F,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAC3D,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;AAM/E,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEvE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE/D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAK1E;AA8ED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAwBhF;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,WAAW,GACvB,IAAI,CAeN;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAMpF;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,UAAU,GAAG,IAAI,GAC3B,IAAI,CA6CN"}
@@ -0,0 +1,195 @@
1
+ import { GameObject as GameObjectClass, getComponentDef } from '@certe/atmos-core';
2
+ import { Mat4, Quat } from '@certe/atmos-math';
3
+ // Scratch data for reparenting (no heap allocs)
4
+ const _invParentWorld = Mat4.create();
5
+ const _newLocal = Mat4.create();
6
+ const _tmpQuat = Quat.create();
7
+ let _reparentValidator = null;
8
+ let _onReparent = null;
9
+ let _onDuplicate = null;
10
+ export function setReparentValidator(fn) {
11
+ _reparentValidator = fn;
12
+ }
13
+ export function setOnReparent(fn) {
14
+ _onReparent = fn;
15
+ }
16
+ export function setOnDuplicate(fn) {
17
+ _onDuplicate = fn;
18
+ }
19
+ export function findObjectById(scene, id) {
20
+ for (const obj of scene.getAllObjects()) {
21
+ if (obj.id === id)
22
+ return obj;
23
+ }
24
+ return null;
25
+ }
26
+ function resolvePropertyPath(obj, path) {
27
+ let current = obj;
28
+ for (const part of path.split('.')) {
29
+ if (current == null || typeof current !== 'object')
30
+ return undefined;
31
+ current = current[part];
32
+ }
33
+ return current;
34
+ }
35
+ function setPropertyPath(target, path, value) {
36
+ const parts = path.split('.');
37
+ let current = target;
38
+ for (let i = 0; i < parts.length - 1; i++) {
39
+ if (current == null || typeof current !== 'object')
40
+ return;
41
+ current = current[parts[i]];
42
+ }
43
+ if (current == null || typeof current !== 'object')
44
+ return;
45
+ const key = parts[parts.length - 1];
46
+ const existing = current[key];
47
+ if (existing instanceof Float32Array && Array.isArray(value)) {
48
+ for (let i = 0; i < value.length && i < existing.length; i++)
49
+ existing[i] = value[i];
50
+ current[key] = existing;
51
+ }
52
+ else {
53
+ current[key] = value;
54
+ }
55
+ }
56
+ function clonePropertyValue(value) {
57
+ if (value instanceof Float32Array)
58
+ return new Float32Array(value);
59
+ if (Array.isArray(value))
60
+ return [...value];
61
+ return value;
62
+ }
63
+ function cloneObjectShallow(source) {
64
+ const copy = new GameObjectClass(source.name + ' (Copy)');
65
+ // Copy transform
66
+ copy.transform.setPositionFrom(source.transform.position);
67
+ copy.transform.setRotationFrom(source.transform.rotation);
68
+ copy.transform.setScaleFrom(source.transform.scale);
69
+ // Copy components with registered properties
70
+ for (const comp of source.getComponents()) {
71
+ const Ctor = comp.constructor;
72
+ const def = getComponentDef(Ctor);
73
+ const newComp = copy.addComponent(Ctor);
74
+ if (def) {
75
+ for (const prop of def.properties) {
76
+ const value = resolvePropertyPath(comp, prop.key);
77
+ if (value !== undefined) {
78
+ setPropertyPath(newComp, prop.key, clonePropertyValue(value));
79
+ }
80
+ }
81
+ }
82
+ // Copy shared GPU resource references (not registered but needed for rendering)
83
+ const src = comp;
84
+ const dst = newComp;
85
+ if (src['mesh'] !== undefined)
86
+ dst['mesh'] = src['mesh'];
87
+ if (src['material'] !== undefined)
88
+ dst['material'] = src['material'];
89
+ }
90
+ return copy;
91
+ }
92
+ function cloneObjectDeep(scene, source) {
93
+ const copy = cloneObjectShallow(source);
94
+ // Recursively duplicate children and parent them under the copy
95
+ for (const child of source.children) {
96
+ const childCopy = cloneObjectDeep(scene, child);
97
+ childCopy.setParent(copy);
98
+ }
99
+ return copy;
100
+ }
101
+ export function duplicateGameObject(scene, source) {
102
+ const copy = cloneObjectDeep(scene, source);
103
+ // Place copy under same parent as source
104
+ if (source.parent) {
105
+ copy.setParent(source.parent);
106
+ }
107
+ scene.add(copy);
108
+ // Post-duplicate hook: initialize physics components etc.
109
+ if (_onDuplicate) {
110
+ const initSubtree = (c, s) => {
111
+ _onDuplicate(c, s);
112
+ const copyChildren = c.children;
113
+ const srcChildren = s.children;
114
+ for (let i = 0; i < copyChildren.length; i++) {
115
+ initSubtree(copyChildren[i], srcChildren[i]);
116
+ }
117
+ };
118
+ initSubtree(copy, source);
119
+ }
120
+ return copy;
121
+ }
122
+ export function deleteGameObject(scene, target, editorState) {
123
+ // Recursively delete children first
124
+ const children = [...target.children];
125
+ for (const child of children) {
126
+ deleteGameObject(scene, child, editorState);
127
+ }
128
+ // Remove from selection if target was selected
129
+ editorState.removeFromSelection(target);
130
+ // Remove from parent
131
+ target.setParent(null);
132
+ // Remove from scene
133
+ scene.remove(target);
134
+ }
135
+ function isDescendant(obj, potentialAncestor) {
136
+ let current = obj.parent;
137
+ while (current) {
138
+ if (current === potentialAncestor)
139
+ return true;
140
+ current = current.parent;
141
+ }
142
+ return false;
143
+ }
144
+ export function canReparent(child, newParent) {
145
+ if (!newParent)
146
+ return true; // root is always valid
147
+ if (child === newParent)
148
+ return false;
149
+ if (isDescendant(newParent, child))
150
+ return false;
151
+ if (_reparentValidator && !_reparentValidator(child, newParent))
152
+ return false;
153
+ return true;
154
+ }
155
+ export function reparentGameObject(scene, child, newParent) {
156
+ if (!canReparent(child, newParent))
157
+ return;
158
+ // Ensure world matrices are up to date before reparenting
159
+ child.transform.updateWorldMatrix();
160
+ // Save current world matrix
161
+ const savedWorld = new Float32Array(child.transform.worldMatrix);
162
+ // Remove from scene roots if currently a root
163
+ child.setParent(newParent);
164
+ // Compute new local transform that preserves the world transform
165
+ // newLocal = inv(newParentWorld) * savedWorld
166
+ if (newParent) {
167
+ newParent.transform.updateWorldMatrix();
168
+ if (Mat4.invert(_invParentWorld, newParent.transform.worldMatrix)) {
169
+ Mat4.multiply(_newLocal, _invParentWorld, savedWorld);
170
+ }
171
+ else {
172
+ _newLocal.set(savedWorld);
173
+ }
174
+ }
175
+ else {
176
+ // No parent: local = world
177
+ _newLocal.set(savedWorld);
178
+ }
179
+ // Decompose newLocal into position, rotation, scale
180
+ // Position = translation column
181
+ child.transform.setPosition(_newLocal[12], _newLocal[13], _newLocal[14]);
182
+ // Scale = column vector lengths
183
+ const sx = Math.sqrt(_newLocal[0] * _newLocal[0] + _newLocal[1] * _newLocal[1] + _newLocal[2] * _newLocal[2]);
184
+ const sy = Math.sqrt(_newLocal[4] * _newLocal[4] + _newLocal[5] * _newLocal[5] + _newLocal[6] * _newLocal[6]);
185
+ const sz = Math.sqrt(_newLocal[8] * _newLocal[8] + _newLocal[9] * _newLocal[9] + _newLocal[10] * _newLocal[10]);
186
+ child.transform.setScale(sx, sy, sz);
187
+ // Rotation = extract quaternion from normalized rotation part
188
+ Quat.fromMat4(_tmpQuat, _newLocal);
189
+ child.transform.setRotationFrom(_tmpQuat);
190
+ // Update root tracking without destroying components
191
+ scene.updateRootStatus(child);
192
+ // Notify listeners (e.g. physics collider re-attachment)
193
+ _onReparent?.(child);
194
+ }
195
+ //# sourceMappingURL=scene-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-operations.js","sourceRoot":"","sources":["../src/scene-operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Scene } from '@certe/atmos-core';
2
+ interface TransformSnapshot {
3
+ position: number[];
4
+ rotation: number[];
5
+ scale: number[];
6
+ }
7
+ interface ComponentSnapshot {
8
+ ctorName: string;
9
+ properties: Map<string, unknown>;
10
+ }
11
+ interface GameObjectSnapshot {
12
+ id: number;
13
+ transform: TransformSnapshot;
14
+ components: ComponentSnapshot[];
15
+ }
16
+ export type SceneSnapshot = GameObjectSnapshot[];
17
+ /**
18
+ * Snapshot all GameObjects' transforms and registered component properties.
19
+ * gameObjectRef values are stored as `{ __goRef: id }` markers.
20
+ */
21
+ export declare function takeSnapshot(scene: Scene): SceneSnapshot;
22
+ /**
23
+ * Restore snapshot values onto existing GameObjects in-place.
24
+ * Objects not found in the scene are skipped. Marks transforms dirty.
25
+ */
26
+ export declare function restoreSnapshot(scene: Scene, snapshot: SceneSnapshot): void;
27
+ export {};
28
+ //# sourceMappingURL=scene-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-snapshot.d.ts","sourceRoot":"","sources":["../src/scene-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAA2B,MAAM,mBAAmB,CAAC;AAIxE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,UAAU,kBAAkB;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,iBAAiB,CAAC;IAC7B,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GAAG,kBAAkB,EAAE,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,aAAa,CAMxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,CA6C3E"}
@@ -0,0 +1,97 @@
1
+ import { getComponentDef } from '@certe/atmos-core';
2
+ import { getProperty, setProperty } from './property-setters.js';
3
+ /**
4
+ * Snapshot all GameObjects' transforms and registered component properties.
5
+ * gameObjectRef values are stored as `{ __goRef: id }` markers.
6
+ */
7
+ export function takeSnapshot(scene) {
8
+ const snapshot = [];
9
+ for (const go of scene.getAllObjects()) {
10
+ snapshot.push(snapshotGameObject(go));
11
+ }
12
+ return snapshot;
13
+ }
14
+ /**
15
+ * Restore snapshot values onto existing GameObjects in-place.
16
+ * Objects not found in the scene are skipped. Marks transforms dirty.
17
+ */
18
+ export function restoreSnapshot(scene, snapshot) {
19
+ // Build id→GameObject lookup
20
+ const byId = new Map();
21
+ for (const go of scene.getAllObjects()) {
22
+ byId.set(go.id, go);
23
+ }
24
+ // Pass 1: Restore ALL transforms first so that auto-computed properties
25
+ // (e.g. HingeJoint.connectedAxis) see correct world matrices for all objects.
26
+ for (const entry of snapshot) {
27
+ const go = byId.get(entry.id);
28
+ if (!go)
29
+ continue;
30
+ const t = go.transform;
31
+ t.setPositionFrom(entry.transform.position);
32
+ t.setRotationFrom(entry.transform.rotation);
33
+ t.setScaleFrom(entry.transform.scale);
34
+ }
35
+ // Pass 2: Restore component properties (setters may trigger joint recreation
36
+ // that depends on other objects' transforms being correct).
37
+ for (const entry of snapshot) {
38
+ const go = byId.get(entry.id);
39
+ if (!go)
40
+ continue;
41
+ const liveComponents = go.getComponents();
42
+ for (let ci = 0; ci < entry.components.length; ci++) {
43
+ const compSnap = entry.components[ci];
44
+ // Match by index — components are snapshotted in getComponents() order,
45
+ // so the same index maps to the same instance (supports multiple of one type).
46
+ const comp = liveComponents[ci];
47
+ if (!comp || comp.constructor.name !== compSnap.ctorName)
48
+ continue;
49
+ const def = getComponentDef(comp.constructor);
50
+ if (!def)
51
+ continue;
52
+ for (const propDef of def.properties) {
53
+ const saved = compSnap.properties.get(propDef.key);
54
+ if (saved === undefined)
55
+ continue;
56
+ const resolved = resolveValue(saved, propDef, byId);
57
+ setProperty(comp, propDef, resolved);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ function snapshotGameObject(go) {
63
+ const t = go.transform;
64
+ const components = [];
65
+ for (const comp of go.getComponents()) {
66
+ const def = getComponentDef(comp.constructor);
67
+ if (!def)
68
+ continue;
69
+ const properties = new Map();
70
+ for (const propDef of def.properties) {
71
+ let value = getProperty(comp, propDef);
72
+ // Store gameObjectRef as id marker
73
+ if (propDef.type === 'gameObjectRef' && value && typeof value === 'object' && 'id' in value) {
74
+ value = { __goRef: value.id };
75
+ }
76
+ properties.set(propDef.key, value);
77
+ }
78
+ components.push({ ctorName: comp.constructor.name, properties });
79
+ }
80
+ return {
81
+ id: go.id,
82
+ transform: {
83
+ position: Array.from(t.position),
84
+ rotation: Array.from(t.rotation),
85
+ scale: Array.from(t.scale),
86
+ },
87
+ components,
88
+ };
89
+ }
90
+ function resolveValue(value, propDef, byId) {
91
+ if (propDef.type === 'gameObjectRef' &&
92
+ value && typeof value === 'object' && '__goRef' in value) {
93
+ return byId.get(value.__goRef) ?? null;
94
+ }
95
+ return value;
96
+ }
97
+ //# sourceMappingURL=scene-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-snapshot.js","sourceRoot":"","sources":["../src/scene-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ScriptAsset } from './asset-types.js';
2
+ import type { AssetEntry } from './asset-types.js';
3
+ /**
4
+ * Process eagerly-loaded script modules and return ScriptAsset[].
5
+ */
6
+ export declare function discoverScripts(modules: Record<string, Record<string, unknown>>): ScriptAsset[];
7
+ /**
8
+ * Auto-discover scripts by scanning the asset tree and dynamically importing
9
+ * .ts files under the given prefix. Works automatically in Vite dev mode.
10
+ */
11
+ export declare function autoDiscoverScripts(entries: AssetEntry[], scriptsPrefix?: string): Promise<ScriptAsset[]>;
12
+ //# sourceMappingURL=script-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-discovery.d.ts","sourceRoot":"","sources":["../src/script-discovery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC/C,WAAW,EAAE,CAqBf;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,UAAU,EAAE,EACrB,aAAa,SAAgB,GAC5B,OAAO,CAAC,WAAW,EAAE,CAAC,CAwBxB"}