@zephyr3d/editor 0.3.4 → 0.3.7

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 (75) hide show
  1. package/dist/assets/{index-DzQzWsCG.js → index-ySiLtSxz.js} +3 -3
  2. package/dist/assistant/zephyr-types-index.json +14217 -7895
  3. package/dist/index.html +1 -1
  4. package/dist/modules/zephyr3d_backend-webgl.js.map +1 -1
  5. package/dist/modules/zephyr3d_backend-webgpu.js +13 -12
  6. package/dist/modules/zephyr3d_backend-webgpu.js.map +1 -1
  7. package/dist/modules/zephyr3d_device.js +15 -15
  8. package/dist/modules/zephyr3d_device.js.map +1 -1
  9. package/dist/modules/zephyr3d_imgui.js.map +1 -1
  10. package/dist/modules/zephyr3d_scene.js +3276 -1089
  11. package/dist/modules/zephyr3d_scene.js.map +1 -1
  12. package/dist/vendor/zephyr3d/backend-webgl/dist/index.js.map +1 -1
  13. package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js +7 -6
  14. package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js.map +1 -1
  15. package/dist/vendor/zephyr3d/backend-webgpu/dist/index.js.map +1 -1
  16. package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js +6 -6
  17. package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js.map +1 -1
  18. package/dist/vendor/zephyr3d/device/dist/device.js +15 -15
  19. package/dist/vendor/zephyr3d/device/dist/device.js.map +1 -1
  20. package/dist/vendor/zephyr3d/imgui/dist/index.d.ts +7 -0
  21. package/dist/vendor/zephyr3d/imgui/dist/index.js.map +1 -1
  22. package/dist/vendor/zephyr3d/scene/dist/animation/animation.js +87 -0
  23. package/dist/vendor/zephyr3d/scene/dist/animation/animation.js.map +1 -1
  24. package/dist/vendor/zephyr3d/scene/dist/animation/animationcontroller.js +503 -0
  25. package/dist/vendor/zephyr3d/scene/dist/animation/animationcontroller.js.map +1 -0
  26. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js +686 -63
  27. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js.map +1 -1
  28. package/dist/vendor/zephyr3d/scene/dist/animation/animationtimeline.js +974 -0
  29. package/dist/vendor/zephyr3d/scene/dist/animation/animationtimeline.js.map +1 -0
  30. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics_modifier.js +19 -19
  31. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics_modifier.js.map +1 -1
  32. package/dist/vendor/zephyr3d/scene/dist/app/engine.js +131 -131
  33. package/dist/vendor/zephyr3d/scene/dist/app/engine.js.map +1 -1
  34. package/dist/vendor/zephyr3d/scene/dist/app/scriptregistry.js +17 -12
  35. package/dist/vendor/zephyr3d/scene/dist/app/scriptregistry.js.map +1 -1
  36. package/dist/vendor/zephyr3d/scene/dist/asset/model.js +2 -1
  37. package/dist/vendor/zephyr3d/scene/dist/asset/model.js.map +1 -1
  38. package/dist/vendor/zephyr3d/scene/dist/avatar/wardrobe.js +13 -13
  39. package/dist/vendor/zephyr3d/scene/dist/avatar/wardrobe.js.map +1 -1
  40. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js +201 -201
  41. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js.map +1 -1
  42. package/dist/vendor/zephyr3d/scene/dist/index.d.ts +1271 -10
  43. package/dist/vendor/zephyr3d/scene/dist/index.js +3 -1
  44. package/dist/vendor/zephyr3d/scene/dist/index.js.map +1 -1
  45. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  46. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  47. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lit.js +7 -3
  48. package/dist/vendor/zephyr3d/scene/dist/material/mixins/lit.js.map +1 -1
  49. package/dist/vendor/zephyr3d/scene/dist/material/mtoon.js +4 -4
  50. package/dist/vendor/zephyr3d/scene/dist/material/mtoon.js.map +1 -1
  51. package/dist/vendor/zephyr3d/scene/dist/material/pbrblueprint.js +11 -11
  52. package/dist/vendor/zephyr3d/scene/dist/material/pbrblueprint.js.map +1 -1
  53. package/dist/vendor/zephyr3d/scene/dist/material/shader/helper.js +284 -284
  54. package/dist/vendor/zephyr3d/scene/dist/material/shader/helper.js.map +1 -1
  55. package/dist/vendor/zephyr3d/scene/dist/posteffect/ssr.js +9 -9
  56. package/dist/vendor/zephyr3d/scene/dist/posteffect/ssr.js.map +1 -1
  57. package/dist/vendor/zephyr3d/scene/dist/render/lightpass.js +5 -5
  58. package/dist/vendor/zephyr3d/scene/dist/render/lightpass.js.map +1 -1
  59. package/dist/vendor/zephyr3d/scene/dist/render/renderer.js +7 -7
  60. package/dist/vendor/zephyr3d/scene/dist/render/renderer.js.map +1 -1
  61. package/dist/vendor/zephyr3d/scene/dist/shadow/esm.js +1 -1
  62. package/dist/vendor/zephyr3d/scene/dist/shadow/esm.js.map +1 -1
  63. package/dist/vendor/zephyr3d/scene/dist/shadow/shadow_region.js +45 -45
  64. package/dist/vendor/zephyr3d/scene/dist/shadow/shadow_region.js.map +1 -1
  65. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js +276 -275
  66. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js.map +1 -1
  67. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js +4 -3
  68. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js.map +1 -1
  69. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js +1 -1
  70. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js.map +1 -1
  71. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/mesh.js.map +1 -1
  72. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/node.js +3 -2
  73. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/node.js.map +1 -1
  74. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/sprite.js.map +1 -1
  75. package/package.json +8 -8
@@ -30,22 +30,22 @@ import '../utility/blueprint/material/texture.js';
30
30
  import { ScreenAdapter } from './screen.js';
31
31
  import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js';
32
32
 
33
- /**
34
- * Core engine class managing scripting, serialization, and rendering.
35
- *
36
- * Responsibilities:
37
- * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.
38
- * - Manages a {@link ResourceManager} for loading scenes and assets.
39
- * - Maintains a list of active renderable objects to be rendered each frame.
40
- * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.
41
- * - Supports enabling/disabling of runtime operations.
42
- *
43
- * @remarks
44
- * The engine can be configured with a virtual file system (VFS) and script root path.
45
- * It exposes methods to manage scripts on host objects, update scripts each frame,
46
- * load scenes from files, and render active objects.
47
- *
48
- * @public
33
+ /**
34
+ * Core engine class managing scripting, serialization, and rendering.
35
+ *
36
+ * Responsibilities:
37
+ * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.
38
+ * - Manages a {@link ResourceManager} for loading scenes and assets.
39
+ * - Maintains a list of active renderable objects to be rendered each frame.
40
+ * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.
41
+ * - Supports enabling/disabling of runtime operations.
42
+ *
43
+ * @remarks
44
+ * The engine can be configured with a virtual file system (VFS) and script root path.
45
+ * It exposes methods to manage scripts on host objects, update scripts each frame,
46
+ * load scenes from files, and render active objects.
47
+ *
48
+ * @public
49
49
  */ class Engine {
50
50
  _builtinsVFS;
51
51
  _scriptingSystem;
@@ -55,12 +55,12 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
55
55
  _screen;
56
56
  _activeRenderables;
57
57
  _loadingScenes;
58
- /**
59
- * Creates a new runtime manager.
60
- *
61
- * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.
62
- * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.
63
- * @param enabled - Whether runtime operations are active. Defaults to `true`.
58
+ /**
59
+ * Creates a new runtime manager.
60
+ *
61
+ * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.
62
+ * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.
63
+ * @param enabled - Whether runtime operations are active. Defaults to `true`.
64
64
  */ constructor(VFS, scriptsRoot, enabled){
65
65
  VFS = VFS ?? new HttpFS('./');
66
66
  this._builtinsVFS = null;
@@ -75,13 +75,13 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
75
75
  this._loadingScenes = {};
76
76
  this._screen = new ScreenAdapter();
77
77
  }
78
- /**
79
- * Exposes the instance of {@link ScriptingSystem}.
78
+ /**
79
+ * Exposes the instance of {@link ScriptingSystem}.
80
80
  */ get scriptingSystem() {
81
81
  return this._scriptingSystem;
82
82
  }
83
- /**
84
- * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.
83
+ /**
84
+ * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.
85
85
  */ get VFS() {
86
86
  return this._scriptingSystem.registry.VFS;
87
87
  }
@@ -93,24 +93,24 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
93
93
  this.ensureBuiltinVFS();
94
94
  }
95
95
  }
96
- /**
97
- * Exposes the instance of {@link ResourceManager}.
96
+ /**
97
+ * Exposes the instance of {@link ResourceManager}.
98
98
  */ get resourceManager() {
99
99
  return this._resourceManager;
100
100
  }
101
- /**
102
- * Exposes the shared runtime MSDF text atlas manager.
101
+ /**
102
+ * Exposes the shared runtime MSDF text atlas manager.
103
103
  */ get msdfTextAtlasManager() {
104
104
  return this._msdfTextAtlasManager;
105
105
  }
106
- /**
107
- * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.
108
- *
109
- * Existing scene nodes that still reference this font asset are not updated automatically.
110
- * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.
111
- *
112
- * @param font - The loaded font asset path to release.
113
- * @returns `true` if either the atlas cache or the font cache had an entry to remove.
106
+ /**
107
+ * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.
108
+ *
109
+ * Existing scene nodes that still reference this font asset are not updated automatically.
110
+ * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.
111
+ *
112
+ * @param font - The loaded font asset path to release.
113
+ * @returns `true` if either the atlas cache or the font cache had an entry to remove.
114
114
  */ releaseFontAsset(font) {
115
115
  const fontAsset = this._resourceManager.getFontAsset(font);
116
116
  if (!fontAsset) {
@@ -120,21 +120,21 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
120
120
  const fontReleased = this._resourceManager.releaseFontAsset(fontAsset);
121
121
  return atlasReleased || fontReleased;
122
122
  }
123
- /**
124
- * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.
125
- *
126
- * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.
127
- * Existing scene nodes that reference this font asset will use the updated atlas automatically.
128
- *
129
- * @param font - The font asset path to configure the MSDF atlas for.
130
- * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).
131
- * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).
132
- * @param distanceRange - The distance range for MSDF generation. Defaults to 4.
133
- * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.
134
- * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.
135
- *
136
- * @remarks
137
- * The font asset must be loaded and available in the resource manager for the atlas to be configured.
123
+ /**
124
+ * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.
125
+ *
126
+ * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.
127
+ * Existing scene nodes that reference this font asset will use the updated atlas automatically.
128
+ *
129
+ * @param font - The font asset path to configure the MSDF atlas for.
130
+ * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).
131
+ * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).
132
+ * @param distanceRange - The distance range for MSDF generation. Defaults to 4.
133
+ * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.
134
+ * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.
135
+ *
136
+ * @remarks
137
+ * The font asset must be loaded and available in the resource manager for the atlas to be configured.
138
138
  */ configureMSDFAtlas(font, pageSize, glyphSize, distanceRange, padding) {
139
139
  const fontAsset = this._resourceManager.getFontAsset(font);
140
140
  if (!fontAsset) {
@@ -144,85 +144,85 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
144
144
  this._msdfTextAtlasManager.configureAtlas(fontAsset, pageSize, glyphSize, distanceRange, padding);
145
145
  return true;
146
146
  }
147
- /**
148
- * Exposes the active {@link ScreenAdapter}.
147
+ /**
148
+ * Exposes the active {@link ScreenAdapter}.
149
149
  */ get screen() {
150
150
  return this._screen;
151
151
  }
152
152
  /** @internal */ async init() {
153
153
  await this.ensureBuiltinVFS();
154
154
  }
155
- /**
156
- * Detaches all scripts from all hosts, if enabled.
157
- *
158
- * No-op when `enabled === false`.
155
+ /**
156
+ * Detaches all scripts from all hosts, if enabled.
157
+ *
158
+ * No-op when `enabled === false`.
159
159
  */ detachAllScripts() {
160
160
  if (this._enabled) {
161
161
  this._scriptingSystem.detachAllScripts();
162
162
  }
163
163
  }
164
- /**
165
- * Loads a runtime script class from file
166
- * @param module - file path
167
- * @returns The runtime script class or null
164
+ /**
165
+ * Loads a runtime script class from file
166
+ * @param module - file path
167
+ * @returns The runtime script class or null
168
168
  */ async loadRuntimeScriptClass(module) {
169
169
  return await this._scriptingSystem.loadRuntimeScriptClass(module);
170
170
  }
171
- /**
172
- * Attaches a script module to the given host, if enabled.
173
- *
174
- * When disabled, this method resolves to `null` without side effects.
175
- *
176
- * @typeParam T - Host type.
177
- * @param host - Host object to attach the script to.
178
- * @param module - Module identifier to resolve and load.
179
- * @param config - Optional configuration passed to the script instance.
180
- * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.
171
+ /**
172
+ * Attaches a script module to the given host, if enabled.
173
+ *
174
+ * When disabled, this method resolves to `null` without side effects.
175
+ *
176
+ * @typeParam T - Host type.
177
+ * @param host - Host object to attach the script to.
178
+ * @param module - Module identifier to resolve and load.
179
+ * @param config - Optional configuration passed to the script instance.
180
+ * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.
181
181
  */ async attachScript(host, module, config) {
182
182
  return this._enabled ? await this._scriptingSystem.attachScript(host, module, config) : null;
183
183
  }
184
- /**
185
- * Detaches a script from a host, by module ID or instance, if enabled.
186
- *
187
- * No-op when disabled.
188
- *
189
- * @typeParam T - Host type.
190
- * @param host - Host to detach from.
191
- * @param idOrInstance - Target script by module ID or instance reference.
184
+ /**
185
+ * Detaches a script from a host, by module ID or instance, if enabled.
186
+ *
187
+ * No-op when disabled.
188
+ *
189
+ * @typeParam T - Host type.
190
+ * @param host - Host to detach from.
191
+ * @param idOrInstance - Target script by module ID or instance reference.
192
192
  */ detachScript(host, idOrInstance) {
193
193
  if (this._enabled) {
194
194
  this._scriptingSystem.detachScript(host, idOrInstance);
195
195
  }
196
196
  }
197
- /**
198
- * Gets all scripts attached to a host.
199
- *
200
- * Delegates to {@link ScriptingSystem.getScriptObjects}.
201
- *
202
- * @typeParam T - Expected script type.
203
- * @param host - Host object to query.
204
- * @returns Script instances attached to the host, or an empty array.
197
+ /**
198
+ * Gets all scripts attached to a host.
199
+ *
200
+ * Delegates to {@link ScriptingSystem.getScriptObjects}.
201
+ *
202
+ * @typeParam T - Expected script type.
203
+ * @param host - Host object to query.
204
+ * @returns Script instances attached to the host, or an empty array.
205
205
  */ getScriptObjects(host) {
206
206
  return this._scriptingSystem.getScriptObjects(host);
207
207
  }
208
- /**
209
- * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.
210
- *
211
- * @param deltaTime - Time since last update in Seconds.
212
- * @param elapsedTime - Total elapsed time in Seconds.
208
+ /**
209
+ * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.
210
+ *
211
+ * @param deltaTime - Time since last update in Seconds.
212
+ * @param elapsedTime - Total elapsed time in Seconds.
213
213
  */ update(deltaTime, elapsedTime) {
214
214
  if (this._enabled) {
215
215
  this._scriptingSystem.update(deltaTime, elapsedTime);
216
216
  }
217
217
  }
218
- /**
219
- * Loads a scene from a file path.
220
- *
221
- * Concurrent requests for the same normalized path share the same loading promise.
222
- * Scripts declared on the scene and its nodes are attached after the scene is loaded.
223
- *
224
- * @param path - Scene file path in the current VFS.
225
- * @returns The loaded scene, or `null` when loading fails.
218
+ /**
219
+ * Loads a scene from a file path.
220
+ *
221
+ * Concurrent requests for the same normalized path share the same loading promise.
222
+ * Scripts declared on the scene and its nodes are attached after the scene is loaded.
223
+ *
224
+ * @param path - Scene file path in the current VFS.
225
+ * @returns The loaded scene, or `null` when loading fails.
226
226
  */ async loadSceneFromFile(path) {
227
227
  path = this.VFS.normalizePath(path);
228
228
  if (!this._loadingScenes[path]) {
@@ -230,15 +230,15 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
230
230
  }
231
231
  return this._loadingScenes[path];
232
232
  }
233
- /**
234
- * Sets or clears the renderable for a render layer.
235
- *
236
- * Passing `null` clears the layer. Object renderables are held through a strong reference wrapper,
237
- * while render functions are stored directly.
238
- *
239
- * @param renderable - Renderable object or render function to assign, or `null` to clear.
240
- * @param layer - Render layer index. Defaults to `0`.
241
- * @param hook - Optional render hook invoked before and after this layer renders.
233
+ /**
234
+ * Sets or clears the renderable for a render layer.
235
+ *
236
+ * Passing `null` clears the layer. Object renderables are held through a strong reference wrapper,
237
+ * while render functions are stored directly.
238
+ *
239
+ * @param renderable - Renderable object or render function to assign, or `null` to clear.
240
+ * @param layer - Render layer index. Defaults to `0`.
241
+ * @param hook - Optional render hook invoked before and after this layer renders.
242
242
  */ setRenderable(renderable, layer = 0, hook) {
243
243
  const entry = this._activeRenderables[layer];
244
244
  if (!entry) {
@@ -261,13 +261,13 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
261
261
  entry.hook = hook ?? null;
262
262
  }
263
263
  }
264
- /**
265
- * Reads a file from the current VFS.
266
- *
267
- * @typeParam T - Requested read encoding.
268
- * @param path - File path to read.
269
- * @param encoding - Optional read encoding. Defaults to `binary`.
270
- * @returns The file content, or `null` when the read fails.
264
+ /**
265
+ * Reads a file from the current VFS.
266
+ *
267
+ * @typeParam T - Requested read encoding.
268
+ * @param path - File path to read.
269
+ * @param encoding - Optional read encoding. Defaults to `binary`.
270
+ * @returns The file content, or `null` when the read fails.
271
271
  */ async readFile(path, encoding) {
272
272
  try {
273
273
  const content = await this.VFS.readFile(path, {
@@ -279,14 +279,14 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
279
279
  return null;
280
280
  }
281
281
  }
282
- /**
283
- * Starts the runtime by optionally showing a splash screen, running a startup script,
284
- * and loading the startup scene.
285
- *
286
- * @param startupScene - Optional scene path rendered on layer `0` after startup completes.
287
- * @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.
288
- * @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`
289
- * extension is removed before loading.
282
+ /**
283
+ * Starts the runtime by optionally showing a splash screen, running a startup script,
284
+ * and loading the startup scene.
285
+ *
286
+ * @param startupScene - Optional scene path rendered on layer `0` after startup completes.
287
+ * @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.
288
+ * @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`
289
+ * extension is removed before loading.
290
290
  */ async startup(startupScene, splashScreen, startupScript) {
291
291
  const splashScreenLayer = 9999;
292
292
  if (splashScreen) {
@@ -305,11 +305,11 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
305
305
  }
306
306
  this.setRenderable(null, splashScreenLayer);
307
307
  }
308
- /**
309
- * Renders all active render layers.
310
- *
311
- * Each layer's `beforeRender` hook can return `false` to skip rendering that layer.
312
- * The `afterRender` hook is invoked after the render attempt.
308
+ /**
309
+ * Renders all active render layers.
310
+ *
311
+ * Each layer's `beforeRender` hook can return `false` to skip rendering that layer.
312
+ * The `afterRender` hook is invoked after the render attempt.
313
313
  */ render() {
314
314
  this._activeRenderables.forEach((info)=>{
315
315
  if (!info.renderable) {
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sources":["../../src/app/engine.ts"],"sourcesContent":["import type { GenericConstructor, IDisposable, Nullable, ReadOptions } from '@zephyr3d/base';\nimport { MemoryFS, objectEntries } from '@zephyr3d/base';\nimport { DRef } from '@zephyr3d/base';\nimport { HttpFS, type VFS } from '@zephyr3d/base';\nimport { ScriptingSystem } from './scriptingsystem';\nimport type { Host } from './scriptingsystem';\nimport type { RuntimeScript, RuntimeScriptConfig } from './runtimescript';\nimport { ResourceManager } from '../utility/serialization/manager';\nimport type { Scene } from '../scene';\nimport {\n BoxShape,\n CapsuleShape,\n CylinderShape,\n PlaneShape,\n SphereShape,\n TetrahedronShape,\n TorusShape\n} from '../shapes';\nimport {\n BlinnMaterial,\n LambertMaterial,\n PBRMetallicRoughnessMaterial,\n PBRSpecularGlossinessMaterial,\n UnlitMaterial\n} from '../material';\nimport { StandardSpriteMaterial } from '../material/sprite_std';\nimport { ScreenAdapter } from './screen';\nimport { MSDFTextAtlasManager } from '../text/runtime';\n\n/**\n * Interface for objects that can be rendered.\n *\n * @public\n */\nexport interface IRenderable extends IDisposable {\n render(): void;\n}\n\n/**\n * Type for render functions that can be registered as renderables.\n *\n * @public\n */\nexport type RenderFunc = () => void;\n\n/**\n * Interface for render hooks to customize rendering behavior.\n *\n * @public\n */\nexport interface IRenderHook {\n // If presents, called before rendering the renderable. Return `false` to skip rendering.\n beforeRender?: (renderable: any) => boolean | void;\n // If presents, called after rendering the renderable.\n afterRender?: (renderable: any) => void;\n}\n\n/**\n * Core engine class managing scripting, serialization, and rendering.\n *\n * Responsibilities:\n * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.\n * - Manages a {@link ResourceManager} for loading scenes and assets.\n * - Maintains a list of active renderable objects to be rendered each frame.\n * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.\n * - Supports enabling/disabling of runtime operations.\n *\n * @remarks\n * The engine can be configured with a virtual file system (VFS) and script root path.\n * It exposes methods to manage scripts on host objects, update scripts each frame,\n * load scenes from files, and render active objects.\n *\n * @public\n */\nexport class Engine {\n private _builtinsVFS: Nullable<MemoryFS>;\n private _scriptingSystem: ScriptingSystem;\n private _resourceManager: ResourceManager;\n private _msdfTextAtlasManager: MSDFTextAtlasManager;\n private _enabled: boolean;\n private _screen: ScreenAdapter;\n protected _activeRenderables: {\n renderable: Nullable<RenderFunc> | DRef<IRenderable>;\n hook: Nullable<IRenderHook>;\n }[];\n private _loadingScenes: Partial<Record<string, Promise<Nullable<Scene>>>>;\n /**\n * Creates a new runtime manager.\n *\n * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.\n * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.\n * @param enabled - Whether runtime operations are active. Defaults to `true`.\n */\n constructor(VFS?: VFS, scriptsRoot?: string, enabled?: boolean) {\n VFS = VFS ?? new HttpFS('./');\n this._builtinsVFS = null;\n this._scriptingSystem = new ScriptingSystem({ VFS, scriptsRoot });\n this._resourceManager = new ResourceManager(VFS);\n this._msdfTextAtlasManager = new MSDFTextAtlasManager();\n this._enabled = enabled ?? true;\n this._activeRenderables = [];\n this._loadingScenes = {};\n this._screen = new ScreenAdapter();\n }\n /**\n * Exposes the instance of {@link ScriptingSystem}.\n */\n get scriptingSystem() {\n return this._scriptingSystem;\n }\n /**\n * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.\n */\n get VFS() {\n return this._scriptingSystem.registry.VFS;\n }\n set VFS(vfs: VFS) {\n if (vfs !== this._resourceManager.VFS) {\n this._resourceManager.VFS?.close();\n this._resourceManager.VFS = vfs;\n this._scriptingSystem.registry.VFS = vfs;\n this.ensureBuiltinVFS();\n }\n }\n /**\n * Exposes the instance of {@link ResourceManager}.\n */\n get resourceManager() {\n return this._resourceManager;\n }\n /**\n * Exposes the shared runtime MSDF text atlas manager.\n */\n get msdfTextAtlasManager() {\n return this._msdfTextAtlasManager;\n }\n /**\n * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.\n *\n * Existing scene nodes that still reference this font asset are not updated automatically.\n * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.\n *\n * @param font - The loaded font asset path to release.\n * @returns `true` if either the atlas cache or the font cache had an entry to remove.\n */\n releaseFontAsset(font: string) {\n const fontAsset = this._resourceManager.getFontAsset(font);\n if (!fontAsset) {\n return false;\n }\n const atlasReleased = this._msdfTextAtlasManager.releaseAtlas(fontAsset);\n const fontReleased = this._resourceManager.releaseFontAsset(fontAsset);\n return atlasReleased || fontReleased;\n }\n /**\n * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.\n *\n * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.\n * Existing scene nodes that reference this font asset will use the updated atlas automatically.\n *\n * @param font - The font asset path to configure the MSDF atlas for.\n * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).\n * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).\n * @param distanceRange - The distance range for MSDF generation. Defaults to 4.\n * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.\n * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.\n *\n * @remarks\n * The font asset must be loaded and available in the resource manager for the atlas to be configured.\n */\n configureMSDFAtlas(\n font: string,\n pageSize: number,\n glyphSize: number,\n distanceRange?: number,\n padding?: number\n ) {\n const fontAsset = this._resourceManager.getFontAsset(font);\n if (!fontAsset) {\n console.warn(`Font asset '${font}' not found for MSDF atlas configuration.`);\n return false;\n }\n this._msdfTextAtlasManager.configureAtlas(fontAsset, pageSize, glyphSize, distanceRange, padding);\n return true;\n }\n /**\n * Exposes the active {@link ScreenAdapter}.\n */\n get screen() {\n return this._screen;\n }\n /** @internal */\n async init() {\n await this.ensureBuiltinVFS();\n }\n /**\n * Detaches all scripts from all hosts, if enabled.\n *\n * No-op when `enabled === false`.\n */\n detachAllScripts() {\n if (this._enabled) {\n this._scriptingSystem.detachAllScripts();\n }\n }\n /**\n * Loads a runtime script class from file\n * @param module - file path\n * @returns The runtime script class or null\n */\n async loadRuntimeScriptClass<T extends Host = Host>(\n module: string\n ): Promise<Nullable<{ url: string; cls: GenericConstructor<RuntimeScript<T>> }>> {\n return await this._scriptingSystem.loadRuntimeScriptClass(module);\n }\n /**\n * Attaches a script module to the given host, if enabled.\n *\n * When disabled, this method resolves to `null` without side effects.\n *\n * @typeParam T - Host type.\n * @param host - Host object to attach the script to.\n * @param module - Module identifier to resolve and load.\n * @param config - Optional configuration passed to the script instance.\n * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.\n */\n async attachScript<T extends Host>(\n host: Nullable<T>,\n module: string,\n config?: Nullable<RuntimeScriptConfig>\n ) {\n return this._enabled ? await this._scriptingSystem.attachScript(host, module, config) : null;\n }\n /**\n * Detaches a script from a host, by module ID or instance, if enabled.\n *\n * No-op when disabled.\n *\n * @typeParam T - Host type.\n * @param host - Host to detach from.\n * @param idOrInstance - Target script by module ID or instance reference.\n */\n detachScript<T extends Host>(host: T, idOrInstance: string | RuntimeScript<T>) {\n if (this._enabled) {\n this._scriptingSystem.detachScript(host, idOrInstance);\n }\n }\n /**\n * Gets all scripts attached to a host.\n *\n * Delegates to {@link ScriptingSystem.getScriptObjects}.\n *\n * @typeParam T - Expected script type.\n * @param host - Host object to query.\n * @returns Script instances attached to the host, or an empty array.\n */\n getScriptObjects<T extends RuntimeScript<any>>(host: unknown) {\n return this._scriptingSystem.getScriptObjects(host) as T[];\n }\n /**\n * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.\n *\n * @param deltaTime - Time since last update in Seconds.\n * @param elapsedTime - Total elapsed time in Seconds.\n */\n update(deltaTime: number, elapsedTime: number) {\n if (this._enabled) {\n this._scriptingSystem.update(deltaTime, elapsedTime);\n }\n }\n /**\n * Loads a scene from a file path.\n *\n * Concurrent requests for the same normalized path share the same loading promise.\n * Scripts declared on the scene and its nodes are attached after the scene is loaded.\n *\n * @param path - Scene file path in the current VFS.\n * @returns The loaded scene, or `null` when loading fails.\n */\n async loadSceneFromFile(path: string) {\n path = this.VFS.normalizePath(path);\n if (!this._loadingScenes[path]) {\n this._loadingScenes[path] = this._loadScene(path);\n }\n return this._loadingScenes[path]!;\n }\n /**\n * Sets or clears the renderable for a render layer.\n *\n * Passing `null` clears the layer. Object renderables are held through a strong reference wrapper,\n * while render functions are stored directly.\n *\n * @param renderable - Renderable object or render function to assign, or `null` to clear.\n * @param layer - Render layer index. Defaults to `0`.\n * @param hook - Optional render hook invoked before and after this layer renders.\n */\n setRenderable(renderable: Nullable<IRenderable | RenderFunc>, layer = 0, hook?: IRenderHook) {\n const entry = this._activeRenderables[layer];\n if (!entry) {\n this._activeRenderables[layer] = {\n renderable: renderable\n ? typeof renderable === 'function'\n ? renderable\n : new DRef<IRenderable>(renderable)\n : null,\n hook: hook ?? null\n };\n } else {\n if (entry.renderable) {\n if (entry.renderable instanceof DRef) {\n entry.renderable.dispose();\n }\n entry.renderable = null;\n }\n if (typeof renderable === 'function') {\n entry.renderable = renderable;\n } else if (renderable) {\n entry.renderable = new DRef<IRenderable>(renderable);\n }\n entry.hook = hook ?? null;\n }\n }\n /**\n * Reads a file from the current VFS.\n *\n * @typeParam T - Requested read encoding.\n * @param path - File path to read.\n * @param encoding - Optional read encoding. Defaults to `binary`.\n * @returns The file content, or `null` when the read fails.\n */\n async readFile<T extends ReadOptions['encoding'] = 'binary'>(path: string, encoding?: T) {\n try {\n const content = await this.VFS.readFile(path, { encoding: encoding ?? 'binary' });\n return content as T extends 'binary' ? ArrayBuffer : string;\n } catch (err) {\n console.error(`Read file '${path}' failed: ${err}`);\n return null;\n }\n }\n /**\n * Starts the runtime by optionally showing a splash screen, running a startup script,\n * and loading the startup scene.\n *\n * @param startupScene - Optional scene path rendered on layer `0` after startup completes.\n * @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.\n * @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`\n * extension is removed before loading.\n */\n async startup(\n startupScene?: Nullable<string>,\n splashScreen?: Nullable<string>,\n startupScript?: Nullable<string>\n ) {\n const splashScreenLayer = 9999;\n if (splashScreen) {\n const splashScreenScene = await this.loadSceneFromFile(splashScreen);\n if (splashScreenScene) {\n this.setRenderable(splashScreenScene, splashScreenLayer);\n }\n }\n if (startupScript) {\n const path =\n startupScript.toLowerCase().endsWith('.ts') || startupScript.toLowerCase().endsWith('.js')\n ? startupScript.slice(0, -3)\n : startupScript;\n await this.attachScript(null, path);\n }\n if (startupScene) {\n const scene = await this.loadSceneFromFile(startupScene);\n this.setRenderable(scene, 0);\n }\n this.setRenderable(null, splashScreenLayer);\n }\n /**\n * Renders all active render layers.\n *\n * Each layer's `beforeRender` hook can return `false` to skip rendering that layer.\n * The `afterRender` hook is invoked after the render attempt.\n */\n render() {\n this._activeRenderables.forEach((info) => {\n if (!info.renderable) {\n return;\n }\n const render = info.hook?.beforeRender\n ? (info.hook.beforeRender(\n typeof info.renderable === 'function' ? info.renderable : info.renderable.get()\n ) ?? true)\n : true;\n if (render) {\n if (typeof info.renderable === 'function') {\n info.renderable();\n } else {\n info.renderable.get()?.render();\n }\n }\n if (info.hook?.afterRender) {\n info.hook.afterRender(\n typeof info.renderable === 'function' ? info.renderable : info.renderable.get()\n );\n }\n });\n }\n private async ensureBuiltinVFS() {\n if (!this._builtinsVFS) {\n this._builtinsVFS = await this.createBuiltinVFS();\n }\n this.VFS.unmount('/assets/@builtins');\n this.VFS.mount('/assets/@builtins', this._builtinsVFS);\n }\n private async createBuiltinVFS() {\n const fs = new MemoryFS();\n const shapeClsMap = {\n '/primitives/box.zmsh': BoxShape,\n '/primitives/sphere.zmsh': SphereShape,\n '/primitives/cylinder.zmsh': CylinderShape,\n '/primitives/plane.zmsh': PlaneShape,\n '/primitives/torus.zmsh': TorusShape,\n '/primitives/tetrahedron.zmsh': TetrahedronShape,\n '/primitives/capsule.zmsh': CapsuleShape,\n '/materials/unlit.zmtl': UnlitMaterial,\n '/materials/lambert.zmtl': LambertMaterial,\n '/materials/blinnphong.zmtl': BlinnMaterial,\n '/materials/pbr_metallic_roughness.zmtl': PBRMetallicRoughnessMaterial,\n '/materials/pbr_specular_glossiness.zmtl': PBRSpecularGlossinessMaterial,\n '/materials/sprite_std.zmtl': StandardSpriteMaterial\n } as const;\n for (const [key] of objectEntries(shapeClsMap)) {\n const obj = new shapeClsMap[key]();\n await this.writeSerializableObject(fs, 'Default', obj, key);\n obj.dispose();\n }\n fs.readOnly = true;\n return fs;\n }\n private async writeSerializableObject(VFS: VFS, type: string, obj: any, path: string) {\n try {\n const data = await this.resourceManager.serializeObject(obj);\n const content = JSON.stringify({ type, data }, null, 2);\n await VFS.writeFile(path, content, { encoding: 'utf8', create: true });\n } catch (err) {\n console.error(`Write file '${path}' failed: ${err}`);\n }\n }\n private async _loadScene(path: string) {\n try {\n const scene = await this._resourceManager.loadScene(path);\n if (scene) {\n const sceneScripts =\n scene.scripts.length > 0\n ? scene.scripts\n : scene.script\n ? [{ script: scene.script, config: scene.scriptConfig }]\n : [];\n for (const attachment of sceneScripts) {\n if (!attachment.script) {\n continue;\n }\n try {\n await this.attachScript(\n scene,\n attachment.script,\n (attachment.config ?? null) as RuntimeScriptConfig | null\n );\n } catch (err) {\n console.error(`Attach script failed: ${err}`);\n }\n }\n const nodes: (typeof scene.rootNode)[] = [];\n scene.rootNode.iterate((node) => {\n nodes.push(node);\n });\n const attachTasks = nodes.map(async (node) => {\n const attachments =\n node.scripts.length > 0\n ? node.scripts\n : node.script\n ? [{ script: node.script, config: node.scriptConfig }]\n : [];\n for (const attachment of attachments) {\n if (!attachment.script) {\n continue;\n }\n try {\n await this.attachScript(\n node,\n attachment.script,\n (attachment.config ?? null) as RuntimeScriptConfig | null\n );\n } catch (err) {\n console.error(`Attach script failed: ${err}`);\n }\n }\n });\n if (attachTasks.length > 0) {\n await Promise.allSettled(attachTasks);\n }\n }\n return scene;\n } catch (err) {\n console.error(`Load scene from '${path}' failed: ${err}`);\n return null;\n }\n }\n}\n\nexport { MSDFTextAtlasManager };\n"],"names":["Engine","_builtinsVFS","_scriptingSystem","_resourceManager","_msdfTextAtlasManager","_enabled","_screen","_activeRenderables","_loadingScenes","VFS","scriptsRoot","enabled","HttpFS","ScriptingSystem","ResourceManager","MSDFTextAtlasManager","ScreenAdapter","scriptingSystem","registry","vfs","close","ensureBuiltinVFS","resourceManager","msdfTextAtlasManager","releaseFontAsset","font","fontAsset","getFontAsset","atlasReleased","releaseAtlas","fontReleased","configureMSDFAtlas","pageSize","glyphSize","distanceRange","padding","console","warn","configureAtlas","screen","init","detachAllScripts","loadRuntimeScriptClass","module","attachScript","host","config","detachScript","idOrInstance","getScriptObjects","update","deltaTime","elapsedTime","loadSceneFromFile","path","normalizePath","_loadScene","setRenderable","renderable","layer","hook","entry","DRef","dispose","readFile","encoding","content","err","error","startup","startupScene","splashScreen","startupScript","splashScreenLayer","splashScreenScene","toLowerCase","endsWith","slice","scene","render","forEach","info","beforeRender","get","afterRender","createBuiltinVFS","unmount","mount","fs","MemoryFS","shapeClsMap","BoxShape","SphereShape","CylinderShape","PlaneShape","TorusShape","TetrahedronShape","CapsuleShape","UnlitMaterial","LambertMaterial","BlinnMaterial","PBRMetallicRoughnessMaterial","PBRSpecularGlossinessMaterial","StandardSpriteMaterial","key","objectEntries","obj","writeSerializableObject","readOnly","type","data","serializeObject","JSON","stringify","writeFile","create","loadScene","sceneScripts","scripts","length","script","scriptConfig","attachment","nodes","rootNode","iterate","node","push","attachTasks","map","attachments","Promise","allSettled"],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","sources":["../../src/app/engine.ts"],"sourcesContent":["import type { GenericConstructor, IDisposable, Nullable, ReadOptions } from '@zephyr3d/base';\r\nimport { MemoryFS, objectEntries } from '@zephyr3d/base';\r\nimport { DRef } from '@zephyr3d/base';\r\nimport { HttpFS, type VFS } from '@zephyr3d/base';\r\nimport { ScriptingSystem } from './scriptingsystem';\r\nimport type { Host } from './scriptingsystem';\r\nimport type { RuntimeScript, RuntimeScriptConfig } from './runtimescript';\r\nimport { ResourceManager } from '../utility/serialization/manager';\r\nimport type { Scene } from '../scene';\r\nimport {\r\n BoxShape,\r\n CapsuleShape,\r\n CylinderShape,\r\n PlaneShape,\r\n SphereShape,\r\n TetrahedronShape,\r\n TorusShape\r\n} from '../shapes';\r\nimport {\r\n BlinnMaterial,\r\n LambertMaterial,\r\n PBRMetallicRoughnessMaterial,\r\n PBRSpecularGlossinessMaterial,\r\n UnlitMaterial\r\n} from '../material';\r\nimport { StandardSpriteMaterial } from '../material/sprite_std';\r\nimport { ScreenAdapter } from './screen';\r\nimport { MSDFTextAtlasManager } from '../text/runtime';\r\n\r\n/**\r\n * Interface for objects that can be rendered.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderable extends IDisposable {\r\n render(): void;\r\n}\r\n\r\n/**\r\n * Type for render functions that can be registered as renderables.\r\n *\r\n * @public\r\n */\r\nexport type RenderFunc = () => void;\r\n\r\n/**\r\n * Interface for render hooks to customize rendering behavior.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderHook {\r\n // If presents, called before rendering the renderable. Return `false` to skip rendering.\r\n beforeRender?: (renderable: any) => boolean | void;\r\n // If presents, called after rendering the renderable.\r\n afterRender?: (renderable: any) => void;\r\n}\r\n\r\n/**\r\n * Core engine class managing scripting, serialization, and rendering.\r\n *\r\n * Responsibilities:\r\n * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.\r\n * - Manages a {@link ResourceManager} for loading scenes and assets.\r\n * - Maintains a list of active renderable objects to be rendered each frame.\r\n * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.\r\n * - Supports enabling/disabling of runtime operations.\r\n *\r\n * @remarks\r\n * The engine can be configured with a virtual file system (VFS) and script root path.\r\n * It exposes methods to manage scripts on host objects, update scripts each frame,\r\n * load scenes from files, and render active objects.\r\n *\r\n * @public\r\n */\r\nexport class Engine {\r\n private _builtinsVFS: Nullable<MemoryFS>;\r\n private _scriptingSystem: ScriptingSystem;\r\n private _resourceManager: ResourceManager;\r\n private _msdfTextAtlasManager: MSDFTextAtlasManager;\r\n private _enabled: boolean;\r\n private _screen: ScreenAdapter;\r\n protected _activeRenderables: {\r\n renderable: Nullable<RenderFunc> | DRef<IRenderable>;\r\n hook: Nullable<IRenderHook>;\r\n }[];\r\n private _loadingScenes: Partial<Record<string, Promise<Nullable<Scene>>>>;\r\n /**\r\n * Creates a new runtime manager.\r\n *\r\n * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.\r\n * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.\r\n * @param enabled - Whether runtime operations are active. Defaults to `true`.\r\n */\r\n constructor(VFS?: VFS, scriptsRoot?: string, enabled?: boolean) {\r\n VFS = VFS ?? new HttpFS('./');\r\n this._builtinsVFS = null;\r\n this._scriptingSystem = new ScriptingSystem({ VFS, scriptsRoot });\r\n this._resourceManager = new ResourceManager(VFS);\r\n this._msdfTextAtlasManager = new MSDFTextAtlasManager();\r\n this._enabled = enabled ?? true;\r\n this._activeRenderables = [];\r\n this._loadingScenes = {};\r\n this._screen = new ScreenAdapter();\r\n }\r\n /**\r\n * Exposes the instance of {@link ScriptingSystem}.\r\n */\r\n get scriptingSystem() {\r\n return this._scriptingSystem;\r\n }\r\n /**\r\n * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.\r\n */\r\n get VFS() {\r\n return this._scriptingSystem.registry.VFS;\r\n }\r\n set VFS(vfs: VFS) {\r\n if (vfs !== this._resourceManager.VFS) {\r\n this._resourceManager.VFS?.close();\r\n this._resourceManager.VFS = vfs;\r\n this._scriptingSystem.registry.VFS = vfs;\r\n this.ensureBuiltinVFS();\r\n }\r\n }\r\n /**\r\n * Exposes the instance of {@link ResourceManager}.\r\n */\r\n get resourceManager() {\r\n return this._resourceManager;\r\n }\r\n /**\r\n * Exposes the shared runtime MSDF text atlas manager.\r\n */\r\n get msdfTextAtlasManager() {\r\n return this._msdfTextAtlasManager;\r\n }\r\n /**\r\n * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.\r\n *\r\n * Existing scene nodes that still reference this font asset are not updated automatically.\r\n * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.\r\n *\r\n * @param font - The loaded font asset path to release.\r\n * @returns `true` if either the atlas cache or the font cache had an entry to remove.\r\n */\r\n releaseFontAsset(font: string) {\r\n const fontAsset = this._resourceManager.getFontAsset(font);\r\n if (!fontAsset) {\r\n return false;\r\n }\r\n const atlasReleased = this._msdfTextAtlasManager.releaseAtlas(fontAsset);\r\n const fontReleased = this._resourceManager.releaseFontAsset(fontAsset);\r\n return atlasReleased || fontReleased;\r\n }\r\n /**\r\n * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.\r\n *\r\n * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.\r\n * Existing scene nodes that reference this font asset will use the updated atlas automatically.\r\n *\r\n * @param font - The font asset path to configure the MSDF atlas for.\r\n * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).\r\n * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).\r\n * @param distanceRange - The distance range for MSDF generation. Defaults to 4.\r\n * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.\r\n * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.\r\n *\r\n * @remarks\r\n * The font asset must be loaded and available in the resource manager for the atlas to be configured.\r\n */\r\n configureMSDFAtlas(\r\n font: string,\r\n pageSize: number,\r\n glyphSize: number,\r\n distanceRange?: number,\r\n padding?: number\r\n ) {\r\n const fontAsset = this._resourceManager.getFontAsset(font);\r\n if (!fontAsset) {\r\n console.warn(`Font asset '${font}' not found for MSDF atlas configuration.`);\r\n return false;\r\n }\r\n this._msdfTextAtlasManager.configureAtlas(fontAsset, pageSize, glyphSize, distanceRange, padding);\r\n return true;\r\n }\r\n /**\r\n * Exposes the active {@link ScreenAdapter}.\r\n */\r\n get screen() {\r\n return this._screen;\r\n }\r\n /** @internal */\r\n async init() {\r\n await this.ensureBuiltinVFS();\r\n }\r\n /**\r\n * Detaches all scripts from all hosts, if enabled.\r\n *\r\n * No-op when `enabled === false`.\r\n */\r\n detachAllScripts() {\r\n if (this._enabled) {\r\n this._scriptingSystem.detachAllScripts();\r\n }\r\n }\r\n /**\r\n * Loads a runtime script class from file\r\n * @param module - file path\r\n * @returns The runtime script class or null\r\n */\r\n async loadRuntimeScriptClass<T extends Host = Host>(\r\n module: string\r\n ): Promise<Nullable<{ url: string; cls: GenericConstructor<RuntimeScript<T>> }>> {\r\n return await this._scriptingSystem.loadRuntimeScriptClass(module);\r\n }\r\n /**\r\n * Attaches a script module to the given host, if enabled.\r\n *\r\n * When disabled, this method resolves to `null` without side effects.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - Host object to attach the script to.\r\n * @param module - Module identifier to resolve and load.\r\n * @param config - Optional configuration passed to the script instance.\r\n * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.\r\n */\r\n async attachScript<T extends Host>(\r\n host: Nullable<T>,\r\n module: string,\r\n config?: Nullable<RuntimeScriptConfig>\r\n ) {\r\n return this._enabled ? await this._scriptingSystem.attachScript(host, module, config) : null;\r\n }\r\n /**\r\n * Detaches a script from a host, by module ID or instance, if enabled.\r\n *\r\n * No-op when disabled.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - Host to detach from.\r\n * @param idOrInstance - Target script by module ID or instance reference.\r\n */\r\n detachScript<T extends Host>(host: T, idOrInstance: string | RuntimeScript<T>) {\r\n if (this._enabled) {\r\n this._scriptingSystem.detachScript(host, idOrInstance);\r\n }\r\n }\r\n /**\r\n * Gets all scripts attached to a host.\r\n *\r\n * Delegates to {@link ScriptingSystem.getScriptObjects}.\r\n *\r\n * @typeParam T - Expected script type.\r\n * @param host - Host object to query.\r\n * @returns Script instances attached to the host, or an empty array.\r\n */\r\n getScriptObjects<T extends RuntimeScript<any>>(host: unknown) {\r\n return this._scriptingSystem.getScriptObjects(host) as T[];\r\n }\r\n /**\r\n * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.\r\n *\r\n * @param deltaTime - Time since last update in Seconds.\r\n * @param elapsedTime - Total elapsed time in Seconds.\r\n */\r\n update(deltaTime: number, elapsedTime: number) {\r\n if (this._enabled) {\r\n this._scriptingSystem.update(deltaTime, elapsedTime);\r\n }\r\n }\r\n /**\r\n * Loads a scene from a file path.\r\n *\r\n * Concurrent requests for the same normalized path share the same loading promise.\r\n * Scripts declared on the scene and its nodes are attached after the scene is loaded.\r\n *\r\n * @param path - Scene file path in the current VFS.\r\n * @returns The loaded scene, or `null` when loading fails.\r\n */\r\n async loadSceneFromFile(path: string) {\r\n path = this.VFS.normalizePath(path);\r\n if (!this._loadingScenes[path]) {\r\n this._loadingScenes[path] = this._loadScene(path);\r\n }\r\n return this._loadingScenes[path]!;\r\n }\r\n /**\r\n * Sets or clears the renderable for a render layer.\r\n *\r\n * Passing `null` clears the layer. Object renderables are held through a strong reference wrapper,\r\n * while render functions are stored directly.\r\n *\r\n * @param renderable - Renderable object or render function to assign, or `null` to clear.\r\n * @param layer - Render layer index. Defaults to `0`.\r\n * @param hook - Optional render hook invoked before and after this layer renders.\r\n */\r\n setRenderable(renderable: Nullable<IRenderable | RenderFunc>, layer = 0, hook?: IRenderHook) {\r\n const entry = this._activeRenderables[layer];\r\n if (!entry) {\r\n this._activeRenderables[layer] = {\r\n renderable: renderable\r\n ? typeof renderable === 'function'\r\n ? renderable\r\n : new DRef<IRenderable>(renderable)\r\n : null,\r\n hook: hook ?? null\r\n };\r\n } else {\r\n if (entry.renderable) {\r\n if (entry.renderable instanceof DRef) {\r\n entry.renderable.dispose();\r\n }\r\n entry.renderable = null;\r\n }\r\n if (typeof renderable === 'function') {\r\n entry.renderable = renderable;\r\n } else if (renderable) {\r\n entry.renderable = new DRef<IRenderable>(renderable);\r\n }\r\n entry.hook = hook ?? null;\r\n }\r\n }\r\n /**\r\n * Reads a file from the current VFS.\r\n *\r\n * @typeParam T - Requested read encoding.\r\n * @param path - File path to read.\r\n * @param encoding - Optional read encoding. Defaults to `binary`.\r\n * @returns The file content, or `null` when the read fails.\r\n */\r\n async readFile<T extends ReadOptions['encoding'] = 'binary'>(path: string, encoding?: T) {\r\n try {\r\n const content = await this.VFS.readFile(path, { encoding: encoding ?? 'binary' });\r\n return content as T extends 'binary' ? ArrayBuffer : string;\r\n } catch (err) {\r\n console.error(`Read file '${path}' failed: ${err}`);\r\n return null;\r\n }\r\n }\r\n /**\r\n * Starts the runtime by optionally showing a splash screen, running a startup script,\r\n * and loading the startup scene.\r\n *\r\n * @param startupScene - Optional scene path rendered on layer `0` after startup completes.\r\n * @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.\r\n * @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`\r\n * extension is removed before loading.\r\n */\r\n async startup(\r\n startupScene?: Nullable<string>,\r\n splashScreen?: Nullable<string>,\r\n startupScript?: Nullable<string>\r\n ) {\r\n const splashScreenLayer = 9999;\r\n if (splashScreen) {\r\n const splashScreenScene = await this.loadSceneFromFile(splashScreen);\r\n if (splashScreenScene) {\r\n this.setRenderable(splashScreenScene, splashScreenLayer);\r\n }\r\n }\r\n if (startupScript) {\r\n const path =\r\n startupScript.toLowerCase().endsWith('.ts') || startupScript.toLowerCase().endsWith('.js')\r\n ? startupScript.slice(0, -3)\r\n : startupScript;\r\n await this.attachScript(null, path);\r\n }\r\n if (startupScene) {\r\n const scene = await this.loadSceneFromFile(startupScene);\r\n this.setRenderable(scene, 0);\r\n }\r\n this.setRenderable(null, splashScreenLayer);\r\n }\r\n /**\r\n * Renders all active render layers.\r\n *\r\n * Each layer's `beforeRender` hook can return `false` to skip rendering that layer.\r\n * The `afterRender` hook is invoked after the render attempt.\r\n */\r\n render() {\r\n this._activeRenderables.forEach((info) => {\r\n if (!info.renderable) {\r\n return;\r\n }\r\n const render = info.hook?.beforeRender\r\n ? (info.hook.beforeRender(\r\n typeof info.renderable === 'function' ? info.renderable : info.renderable.get()\r\n ) ?? true)\r\n : true;\r\n if (render) {\r\n if (typeof info.renderable === 'function') {\r\n info.renderable();\r\n } else {\r\n info.renderable.get()?.render();\r\n }\r\n }\r\n if (info.hook?.afterRender) {\r\n info.hook.afterRender(\r\n typeof info.renderable === 'function' ? info.renderable : info.renderable.get()\r\n );\r\n }\r\n });\r\n }\r\n private async ensureBuiltinVFS() {\r\n if (!this._builtinsVFS) {\r\n this._builtinsVFS = await this.createBuiltinVFS();\r\n }\r\n this.VFS.unmount('/assets/@builtins');\r\n this.VFS.mount('/assets/@builtins', this._builtinsVFS);\r\n }\r\n private async createBuiltinVFS() {\r\n const fs = new MemoryFS();\r\n const shapeClsMap = {\r\n '/primitives/box.zmsh': BoxShape,\r\n '/primitives/sphere.zmsh': SphereShape,\r\n '/primitives/cylinder.zmsh': CylinderShape,\r\n '/primitives/plane.zmsh': PlaneShape,\r\n '/primitives/torus.zmsh': TorusShape,\r\n '/primitives/tetrahedron.zmsh': TetrahedronShape,\r\n '/primitives/capsule.zmsh': CapsuleShape,\r\n '/materials/unlit.zmtl': UnlitMaterial,\r\n '/materials/lambert.zmtl': LambertMaterial,\r\n '/materials/blinnphong.zmtl': BlinnMaterial,\r\n '/materials/pbr_metallic_roughness.zmtl': PBRMetallicRoughnessMaterial,\r\n '/materials/pbr_specular_glossiness.zmtl': PBRSpecularGlossinessMaterial,\r\n '/materials/sprite_std.zmtl': StandardSpriteMaterial\r\n } as const;\r\n for (const [key] of objectEntries(shapeClsMap)) {\r\n const obj = new shapeClsMap[key]();\r\n await this.writeSerializableObject(fs, 'Default', obj, key);\r\n obj.dispose();\r\n }\r\n fs.readOnly = true;\r\n return fs;\r\n }\r\n private async writeSerializableObject(VFS: VFS, type: string, obj: any, path: string) {\r\n try {\r\n const data = await this.resourceManager.serializeObject(obj);\r\n const content = JSON.stringify({ type, data }, null, 2);\r\n await VFS.writeFile(path, content, { encoding: 'utf8', create: true });\r\n } catch (err) {\r\n console.error(`Write file '${path}' failed: ${err}`);\r\n }\r\n }\r\n private async _loadScene(path: string) {\r\n try {\r\n const scene = await this._resourceManager.loadScene(path);\r\n if (scene) {\r\n const sceneScripts =\r\n scene.scripts.length > 0\r\n ? scene.scripts\r\n : scene.script\r\n ? [{ script: scene.script, config: scene.scriptConfig }]\r\n : [];\r\n for (const attachment of sceneScripts) {\r\n if (!attachment.script) {\r\n continue;\r\n }\r\n try {\r\n await this.attachScript(\r\n scene,\r\n attachment.script,\r\n (attachment.config ?? null) as RuntimeScriptConfig | null\r\n );\r\n } catch (err) {\r\n console.error(`Attach script failed: ${err}`);\r\n }\r\n }\r\n const nodes: (typeof scene.rootNode)[] = [];\r\n scene.rootNode.iterate((node) => {\r\n nodes.push(node);\r\n });\r\n const attachTasks = nodes.map(async (node) => {\r\n const attachments =\r\n node.scripts.length > 0\r\n ? node.scripts\r\n : node.script\r\n ? [{ script: node.script, config: node.scriptConfig }]\r\n : [];\r\n for (const attachment of attachments) {\r\n if (!attachment.script) {\r\n continue;\r\n }\r\n try {\r\n await this.attachScript(\r\n node,\r\n attachment.script,\r\n (attachment.config ?? null) as RuntimeScriptConfig | null\r\n );\r\n } catch (err) {\r\n console.error(`Attach script failed: ${err}`);\r\n }\r\n }\r\n });\r\n if (attachTasks.length > 0) {\r\n await Promise.allSettled(attachTasks);\r\n }\r\n }\r\n return scene;\r\n } catch (err) {\r\n console.error(`Load scene from '${path}' failed: ${err}`);\r\n return null;\r\n }\r\n }\r\n}\r\n\r\nexport { MSDFTextAtlasManager };\r\n"],"names":["Engine","_builtinsVFS","_scriptingSystem","_resourceManager","_msdfTextAtlasManager","_enabled","_screen","_activeRenderables","_loadingScenes","VFS","scriptsRoot","enabled","HttpFS","ScriptingSystem","ResourceManager","MSDFTextAtlasManager","ScreenAdapter","scriptingSystem","registry","vfs","close","ensureBuiltinVFS","resourceManager","msdfTextAtlasManager","releaseFontAsset","font","fontAsset","getFontAsset","atlasReleased","releaseAtlas","fontReleased","configureMSDFAtlas","pageSize","glyphSize","distanceRange","padding","console","warn","configureAtlas","screen","init","detachAllScripts","loadRuntimeScriptClass","module","attachScript","host","config","detachScript","idOrInstance","getScriptObjects","update","deltaTime","elapsedTime","loadSceneFromFile","path","normalizePath","_loadScene","setRenderable","renderable","layer","hook","entry","DRef","dispose","readFile","encoding","content","err","error","startup","startupScene","splashScreen","startupScript","splashScreenLayer","splashScreenScene","toLowerCase","endsWith","slice","scene","render","forEach","info","beforeRender","get","afterRender","createBuiltinVFS","unmount","mount","fs","MemoryFS","shapeClsMap","BoxShape","SphereShape","CylinderShape","PlaneShape","TorusShape","TetrahedronShape","CapsuleShape","UnlitMaterial","LambertMaterial","BlinnMaterial","PBRMetallicRoughnessMaterial","PBRSpecularGlossinessMaterial","StandardSpriteMaterial","key","objectEntries","obj","writeSerializableObject","readOnly","type","data","serializeObject","JSON","stringify","writeFile","create","loadScene","sceneScripts","scripts","length","script","scriptConfig","attachment","nodes","rootNode","iterate","node","push","attachTasks","map","attachments","Promise","allSettled"],"mappings":"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"}
@@ -69,7 +69,7 @@ function hasRawQuery(spec) {
69
69
  *
70
70
  * Modes:
71
71
  * - Editor mode (`editorMode === true`): local script graphs are bundled to data URLs.
72
- * - Runtime mode (`editorMode === false`): returns .js URLs directly (with .ts -\> .js mapping).
72
+ * - Runtime mode (`editorMode === false`): returns .js/.mjs URLs directly (with .ts -\> .js mapping).
73
73
  *
74
74
  * Caching:
75
75
  * - Built bundles are memoized in `_built` map keyed by canonical source path.
@@ -163,8 +163,8 @@ function hasRawQuery(spec) {
163
163
  * Fetches raw source for a logical module id by probing known extensions.
164
164
  *
165
165
  * Search order:
166
- * - If `id` already ends with `.ts` or `.js` and is a file -\> return it.
167
- * - Else try `.id.ts`, then `.id.js`.
166
+ * - If `id` already ends with `.ts`, `.js`, or `.mjs` and is a file -\> return it.
167
+ * - Else try `.id.ts`, then `.id.js`, then `.id.mjs`.
168
168
  *
169
169
  * @param id - Logical module identifier (absolute or logical path-like).
170
170
  * @returns Source code, resolved path, and type (`'js' | 'ts'`), or `undefined` if not found.
@@ -174,7 +174,7 @@ function hasRawQuery(spec) {
174
174
  if (id.endsWith('.ts')) {
175
175
  pathWithExt = id;
176
176
  type = 'ts';
177
- } else if (id.endsWith('.js')) {
177
+ } else if (id.endsWith('.js') || id.endsWith('.mjs')) {
178
178
  pathWithExt = id;
179
179
  type = 'js';
180
180
  }
@@ -193,13 +193,16 @@ function hasRawQuery(spec) {
193
193
  'js'
194
194
  ];
195
195
  if (!type) {
196
- for (const t of types){
196
+ for (const t of [
197
+ ...types,
198
+ 'mjs'
199
+ ]){
197
200
  pathWithExt = `${id}.${t}`;
198
201
  const exists = await this._vfs.exists(pathWithExt);
199
202
  if (exists) {
200
203
  const stats = await this._vfs.stat(pathWithExt);
201
204
  if (stats.isFile) {
202
- type = t;
205
+ type = t === 'ts' ? 'ts' : 'js';
203
206
  break;
204
207
  }
205
208
  }
@@ -221,8 +224,9 @@ function hasRawQuery(spec) {
221
224
  *
222
225
  * Behavior:
223
226
  * - In editor mode, builds the module to a data URL.
224
- * - Otherwise, returns `.js` URL directly:
227
+ * - Otherwise, returns `.js` or `.mjs` URL directly:
225
228
  * - If `id` ends with `.js`: return as-is.
229
+ * - If `id` ends with `.mjs`: return as-is.
226
230
  * - If `id` ends with `.ts`: map to `.js` (assumes pre-built file exists).
227
231
  * - Else: append `.js`.
228
232
  *
@@ -233,7 +237,7 @@ function hasRawQuery(spec) {
233
237
  if (id.startsWith('/assets/@builtins/')) {
234
238
  return await this.build(String(id));
235
239
  }
236
- return getApp().editorMode !== 'none' ? await this.build(String(id)) : id.endsWith('.js') ? id : id.endsWith('.ts') ? `${id.slice(0, -3)}.js` : `${id}.js`;
240
+ return getApp().editorMode !== 'none' ? await this.build(String(id)) : id.endsWith('.js') || id.endsWith('.mjs') ? id : id.endsWith('.ts') ? `${id.slice(0, -3)}.js` : `${id}.js`;
237
241
  }
238
242
  /**
239
243
  * Recursively gathers direct static and dynamic import dependencies for a module.
@@ -376,7 +380,7 @@ function hasRawQuery(spec) {
376
380
  const ts = this.getTypeScriptRuntime();
377
381
  const res = ts.transpileModule(code, {
378
382
  compilerOptions: {
379
- target: ts.ScriptTarget.ES2015,
383
+ target: ts.ScriptTarget.ES2020,
380
384
  module: ts.ModuleKind.ESNext,
381
385
  experimentalDecorators: true,
382
386
  useDefineForClassFields: false
@@ -391,11 +395,12 @@ function hasRawQuery(spec) {
391
395
  const res = ts.transpileModule(code, {
392
396
  compilerOptions: {
393
397
  allowJs: true,
394
- target: ts.ScriptTarget.ES2015,
398
+ // Keep modern syntax such as async generators, class fields, and private fields intact.
399
+ target: ts.ScriptTarget.ES2022,
395
400
  module: ts.ModuleKind.System,
396
401
  esModuleInterop: true,
397
402
  experimentalDecorators: true,
398
- useDefineForClassFields: false
403
+ useDefineForClassFields: true
399
404
  },
400
405
  fileName: logicalId
401
406
  });
@@ -579,7 +584,7 @@ async function __z3dLoad(spec, parentId = '') {
579
584
  } else if (baseSpec.startsWith('/')) {
580
585
  return `${baseSpec.replace(/^\/+/, '/')}${suffix}`;
581
586
  } else if (getApp().editorMode !== 'none') {
582
- const libRoot = this._vfs.normalizePath(this._scriptsRoot || '/');
587
+ const libRoot = '/'; //this._vfs.normalizePath(this._scriptsRoot || '/');
583
588
  // naked module, checking if it is a installed module in editor mode
584
589
  let depsLockPath = this._vfs.normalizePath(this._vfs.join(libRoot, 'libs/deps.lock.json'));
585
590
  let depsExists = await this._vfs.exists(depsLockPath);