@zephyr3d/scene 0.9.4 → 0.9.5

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 (102) hide show
  1. package/dist/animation/animationmask.js +224 -0
  2. package/dist/animation/animationmask.js.map +1 -0
  3. package/dist/animation/animationset.js +268 -67
  4. package/dist/animation/animationset.js.map +1 -1
  5. package/dist/animation/animationtrack.js.map +1 -1
  6. package/dist/animation/eulerrotationtrack.js +3 -0
  7. package/dist/animation/eulerrotationtrack.js.map +1 -1
  8. package/dist/animation/fixed_geometry_cache_track.js +7 -0
  9. package/dist/animation/fixed_geometry_cache_track.js.map +1 -1
  10. package/dist/animation/ik_modifier.js.map +1 -1
  11. package/dist/animation/joint_dynamics/collision.js +6 -4
  12. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  13. package/dist/animation/joint_dynamics/controller.js +390 -43
  14. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  15. package/dist/animation/joint_dynamics/joint_dynamics_system.js +62 -3
  16. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  17. package/dist/animation/joint_dynamics/solver.js +4 -3
  18. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  19. package/dist/animation/joint_dynamics/types.js.map +1 -1
  20. package/dist/animation/joint_dynamics_modifier.js +2 -0
  21. package/dist/animation/joint_dynamics_modifier.js.map +1 -1
  22. package/dist/animation/morphtarget.js +3 -72
  23. package/dist/animation/morphtarget.js.map +1 -1
  24. package/dist/animation/morphtrack.js +3 -0
  25. package/dist/animation/morphtrack.js.map +1 -1
  26. package/dist/animation/pca_geometry_cache_track.js +3 -0
  27. package/dist/animation/pca_geometry_cache_track.js.map +1 -1
  28. package/dist/animation/proptrack.js +3 -0
  29. package/dist/animation/proptrack.js.map +1 -1
  30. package/dist/animation/rotationtrack.js +3 -0
  31. package/dist/animation/rotationtrack.js.map +1 -1
  32. package/dist/animation/scaletrack.js +3 -0
  33. package/dist/animation/scaletrack.js.map +1 -1
  34. package/dist/animation/skeleton.js +254 -79
  35. package/dist/animation/skeleton.js.map +1 -1
  36. package/dist/animation/skeleton_modifier.js.map +1 -1
  37. package/dist/animation/spring_modifier.js.map +1 -1
  38. package/dist/animation/translationtrack.js +3 -0
  39. package/dist/animation/translationtrack.js.map +1 -1
  40. package/dist/app/engine.js +171 -107
  41. package/dist/app/engine.js.map +1 -1
  42. package/dist/app/scriptregistry.js +251 -80
  43. package/dist/app/scriptregistry.js.map +1 -1
  44. package/dist/asset/assetmanager.js +344 -365
  45. package/dist/asset/assetmanager.js.map +1 -1
  46. package/dist/asset/loaders/gltf/gltf_loader.js +17 -14
  47. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
  48. package/dist/asset/loaders/loader.js +1 -6
  49. package/dist/asset/loaders/loader.js.map +1 -1
  50. package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -1
  51. package/dist/asset/model.js +1000 -131
  52. package/dist/asset/model.js.map +1 -1
  53. package/dist/avatar/wardrobe.js +474 -0
  54. package/dist/avatar/wardrobe.js.map +1 -0
  55. package/dist/index.d.ts +1125 -199
  56. package/dist/index.js +3 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +6 -3
  59. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  60. package/dist/material/mixins/pbr/common.js +72 -15
  61. package/dist/material/mixins/pbr/common.js.map +1 -1
  62. package/dist/material/msdf_text_sprite.js +4 -4
  63. package/dist/material/msdf_text_sprite.js.map +1 -1
  64. package/dist/material/pbrblueprint.js +102 -102
  65. package/dist/material/pbrblueprint.js.map +1 -1
  66. package/dist/render/envlight.js +54 -1
  67. package/dist/render/envlight.js.map +1 -1
  68. package/dist/render/sky.js +9 -0
  69. package/dist/render/sky.js.map +1 -1
  70. package/dist/scene/batchgroup.js +11 -13
  71. package/dist/scene/batchgroup.js.map +1 -1
  72. package/dist/scene/environment.js +15 -2
  73. package/dist/scene/environment.js.map +1 -1
  74. package/dist/scene/mesh.js +79 -16
  75. package/dist/scene/mesh.js.map +1 -1
  76. package/dist/scene/scene.js +1 -0
  77. package/dist/scene/scene.js.map +1 -1
  78. package/dist/scene/scene_node.js +203 -2
  79. package/dist/scene/scene_node.js.map +1 -1
  80. package/dist/text/font/font_asset.js.map +1 -1
  81. package/dist/text/msdf/generator.js.map +1 -1
  82. package/dist/text/msdf/shape.js +4 -1
  83. package/dist/text/msdf/shape.js.map +1 -1
  84. package/dist/text/runtime/msdf_text_atlas_manager.js +4 -1
  85. package/dist/text/runtime/msdf_text_atlas_manager.js.map +1 -1
  86. package/dist/utility/blueprint/material/inputs.js +1157 -1154
  87. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  88. package/dist/utility/bounding_volume.js.map +1 -1
  89. package/dist/utility/pmrem.js +34 -8
  90. package/dist/utility/pmrem.js.map +1 -1
  91. package/dist/utility/serialization/manager.js +22 -9
  92. package/dist/utility/serialization/manager.js.map +1 -1
  93. package/dist/utility/serialization/scene/animation.js +700 -7
  94. package/dist/utility/serialization/scene/animation.js.map +1 -1
  95. package/dist/utility/serialization/scene/mesh.js +64 -4
  96. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  97. package/dist/utility/serialization/scene/node.js +187 -8
  98. package/dist/utility/serialization/scene/node.js.map +1 -1
  99. package/dist/utility/serialization/types.js.map +1 -1
  100. package/dist/utility/textures/sheenlut.js +138 -0
  101. package/dist/utility/textures/sheenlut.js.map +1 -0
  102. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton_modifier.js","sources":["../../src/animation/skeleton_modifier.ts"],"sourcesContent":["import type { Skeleton } from './skeleton';\r\n\r\n/**\r\n * Abstract base class for skeleton post-processors.\r\n *\r\n * Post-processors are applied after the base animation/bind pose layer,\r\n * allowing procedural modifications like IK, spring physics, or manual overrides.\r\n *\r\n * @public\r\n */\r\nexport abstract class SkeletonModifier {\r\n /** Whether this processor is enabled */\r\n protected _enabled: boolean;\r\n\r\n constructor() {\r\n this._enabled = true;\r\n }\r\n\r\n /**\r\n * Get the blend weight [0-1]\r\n */\r\n get weight(): number {\r\n return this._getWeight();\r\n }\r\n\r\n set weight(value: number) {\r\n this._setWeight(value);\r\n }\r\n\r\n /**\r\n * Get whether this processor is enabled\r\n */\r\n get enabled(): boolean {\r\n return this._enabled;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this._enabled = value;\r\n }\r\n\r\n /**\r\n * Apply post-processing to skeleton joints.\r\n *\r\n * This method is called after the base animation/bind pose has been applied.\r\n * Implementations should modify joint transforms and blend with the current state\r\n * using the processor's weight.\r\n *\r\n * @param skeleton - The skeleton to process\r\n * @param deltaTime - Time elapsed since last frame (in seconds)\r\n */\r\n abstract apply(skeleton: Skeleton, deltaTime: number): void;\r\n\r\n /**\r\n * Reset the processor to its initial state.\r\n *\r\n * Called when the skeleton or animation state changes significantly.\r\n */\r\n abstract reset(): void;\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n */\r\n protected abstract _getWeight(): number;\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param _value - New blend weight (0-1)\r\n */\r\n protected abstract _setWeight(_value: number): void;\r\n}\r\n"],"names":["SkeletonModifier","_enabled","weight","_getWeight","value","_setWeight","enabled"],"mappings":"AAEA;;;;;;;AAOC,IACM,MAAeA,gBAAAA,CAAAA;6CAEpB,QAA4B;IAE5B,WAAc,EAAA;QACZ,IAAI,CAACC,QAAQ,GAAG,IAAA;AAClB;AAEA;;AAEC,MACD,IAAIC,MAAiB,GAAA;QACnB,OAAO,IAAI,CAACC,UAAU,EAAA;AACxB;IAEA,IAAID,MAAAA,CAAOE,KAAa,EAAE;QACxB,IAAI,CAACC,UAAU,CAACD,KAAAA,CAAAA;AAClB;AAEA;;AAEC,MACD,IAAIE,OAAmB,GAAA;QACrB,OAAO,IAAI,CAACL,QAAQ;AACtB;IAEA,IAAIK,OAAAA,CAAQF,KAAc,EAAE;QAC1B,IAAI,CAACH,QAAQ,GAAGG,KAAAA;AAClB;AA+BF;;;;"}
1
+ {"version":3,"file":"skeleton_modifier.js","sources":["../../src/animation/skeleton_modifier.ts"],"sourcesContent":["import type { SkeletonRig } from './skeleton';\r\n\r\n/**\r\n * Abstract base class for skeleton post-processors.\r\n *\r\n * Post-processors are applied after the base animation/bind pose layer,\r\n * allowing procedural modifications like IK, spring physics, or manual overrides.\r\n *\r\n * @public\r\n */\r\nexport abstract class SkeletonModifier {\r\n /** Whether this processor is enabled */\r\n protected _enabled: boolean;\r\n\r\n constructor() {\r\n this._enabled = true;\r\n }\r\n\r\n /**\r\n * Get the blend weight [0-1]\r\n */\r\n get weight(): number {\r\n return this._getWeight();\r\n }\r\n\r\n set weight(value: number) {\r\n this._setWeight(value);\r\n }\r\n\r\n /**\r\n * Get whether this processor is enabled\r\n */\r\n get enabled(): boolean {\r\n return this._enabled;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this._enabled = value;\r\n }\r\n\r\n /**\r\n * Apply post-processing to skeleton joints.\r\n *\r\n * This method is called after the base animation/bind pose has been applied.\r\n * Implementations should modify joint transforms and blend with the current state\r\n * using the processor's weight.\r\n *\r\n * @param skeleton - The shared rig to process\r\n * @param deltaTime - Time elapsed since last frame (in seconds)\r\n */\r\n abstract apply(skeleton: SkeletonRig, deltaTime: number): void;\r\n\r\n /**\r\n * Reset the processor to its initial state.\r\n *\r\n * Called when the skeleton or animation state changes significantly.\r\n */\r\n abstract reset(): void;\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n */\r\n protected abstract _getWeight(): number;\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param _value - New blend weight (0-1)\r\n */\r\n protected abstract _setWeight(_value: number): void;\r\n}\r\n"],"names":["SkeletonModifier","_enabled","weight","_getWeight","value","_setWeight","enabled"],"mappings":"AAEA;;;;;;;AAOC,IACM,MAAeA,gBAAAA,CAAAA;6CAEpB,QAA4B;IAE5B,WAAc,EAAA;QACZ,IAAI,CAACC,QAAQ,GAAG,IAAA;AAClB;AAEA;;AAEC,MACD,IAAIC,MAAiB,GAAA;QACnB,OAAO,IAAI,CAACC,UAAU,EAAA;AACxB;IAEA,IAAID,MAAAA,CAAOE,KAAa,EAAE;QACxB,IAAI,CAACC,UAAU,CAACD,KAAAA,CAAAA;AAClB;AAEA;;AAEC,MACD,IAAIE,OAAmB,GAAA;QACrB,OAAO,IAAI,CAACL,QAAQ;AACtB;IAEA,IAAIK,OAAAA,CAAQF,KAAc,EAAE;QAC1B,IAAI,CAACH,QAAQ,GAAGG,KAAAA;AAClB;AA+BF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"spring_modifier.js","sources":["../../src/animation/spring_modifier.ts"],"sourcesContent":["import { SkeletonModifier } from './skeleton_modifier';\r\nimport type { Skeleton } from './skeleton';\r\nimport type { SpringSystem } from './spring/spring_system';\r\n\r\n/**\r\n * Post-processor wrapper for spring physics systems.\r\n *\r\n * Integrates spring-based physics simulation into the skeleton post-processing pipeline.\r\n * The spring system is updated each frame and results are blended with the base animation.\r\n *\r\n * @deprecated Use the new {@link JointDynamicsModifier} class instead.\r\n *\r\n * @public\r\n */\r\nexport class SpringModifier extends SkeletonModifier {\r\n private _springSystem: SpringSystem;\r\n private _weight: number;\r\n\r\n /**\r\n * Create a spring post-processor.\r\n *\r\n * @param springSystem - The spring system to integrate\r\n * @param weight - Blend weight [0-1] (default: 1.0)\r\n */\r\n constructor(springSystem: SpringSystem, weight: number = 1.0) {\r\n super();\r\n this._weight = weight;\r\n this._springSystem = springSystem;\r\n }\r\n\r\n /**\r\n * Get the spring system.\r\n */\r\n get springSystem(): SpringSystem {\r\n return this._springSystem;\r\n }\r\n\r\n /**\r\n * Apply spring physics to skeleton joints.\r\n */\r\n apply(_skeleton: Skeleton, deltaTime: number): void {\r\n if (!this._enabled || this._weight <= 0) {\r\n return;\r\n }\r\n\r\n // Update spring physics simulation\r\n this._springSystem.update(deltaTime);\r\n\r\n // Apply results to scene nodes with blending\r\n this._springSystem.applyToNodes(this._weight);\r\n }\r\n\r\n /**\r\n * Reset the spring system to initial state.\r\n */\r\n reset(): void {\r\n this._springSystem.reset();\r\n }\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n * @returns The current blend weight (0-1)\r\n */\r\n protected _getWeight(): number {\r\n return this._weight;\r\n }\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param value - New blend weight (0-1)\r\n */\r\n protected _setWeight(value: number): void {\r\n this._weight = Math.max(0, Math.min(1, value));\r\n }\r\n}\r\n"],"names":["SpringModifier","SkeletonModifier","_springSystem","_weight","springSystem","weight","apply","_skeleton","deltaTime","_enabled","update","applyToNodes","reset","_setWeight","value","Math","max","min"],"mappings":";;AAIA;;;;;;;;;IAUO,MAAMA,cAAuBC,SAAAA,gBAAAA,CAAAA;IAC1BC,aAA4B;IAC5BC,OAAgB;AAExB;;;;;AAKC,MACD,WAAYC,CAAAA,YAA0B,EAAEC,MAAAA,GAAiB,GAAG,CAAE;QAC5D,KAAK,EAAA;QACL,IAAI,CAACF,OAAO,GAAGE,MAAAA;QACf,IAAI,CAACH,aAAa,GAAGE,YAAAA;AACvB;AAEA;;AAEC,MACD,IAAIA,YAA6B,GAAA;QAC/B,OAAO,IAAI,CAACF,aAAa;AAC3B;AAEA;;AAEC,MACDI,KAAMC,CAAAA,SAAmB,EAAEC,SAAiB,EAAQ;QAClD,IAAI,CAAC,IAAI,CAACC,QAAQ,IAAI,IAAI,CAACN,OAAO,IAAI,CAAG,EAAA;AACvC,YAAA;AACF;;AAGA,QAAA,IAAI,CAACD,aAAa,CAACQ,MAAM,CAACF,SAAAA,CAAAA;;AAG1B,QAAA,IAAI,CAACN,aAAa,CAACS,YAAY,CAAC,IAAI,CAACR,OAAO,CAAA;AAC9C;AAEA;;AAEC,MACDS,KAAc,GAAA;QACZ,IAAI,CAACV,aAAa,CAACU,KAAK,EAAA;AAC1B;AAEA;;;AAGC,MACD,UAA+B,GAAA;QAC7B,OAAO,IAAI,CAACT,OAAO;AACrB;AAEA;;;MAIUU,UAAWC,CAAAA,KAAa,EAAQ;QACxC,IAAI,CAACX,OAAO,GAAGY,IAAKC,CAAAA,GAAG,CAAC,CAAGD,EAAAA,IAAAA,CAAKE,GAAG,CAAC,CAAGH,EAAAA,KAAAA,CAAAA,CAAAA;AACzC;AACF;;;;"}
1
+ {"version":3,"file":"spring_modifier.js","sources":["../../src/animation/spring_modifier.ts"],"sourcesContent":["import { SkeletonModifier } from './skeleton_modifier';\r\nimport type { SkeletonRig } from './skeleton';\r\nimport type { SpringSystem } from './spring/spring_system';\r\n\r\n/**\r\n * Post-processor wrapper for spring physics systems.\r\n *\r\n * Integrates spring-based physics simulation into the skeleton post-processing pipeline.\r\n * The spring system is updated each frame and results are blended with the base animation.\r\n *\r\n * @deprecated Use the new {@link JointDynamicsModifier} class instead.\r\n *\r\n * @public\r\n */\r\nexport class SpringModifier extends SkeletonModifier {\r\n private _springSystem: SpringSystem;\r\n private _weight: number;\r\n\r\n /**\r\n * Create a spring post-processor.\r\n *\r\n * @param springSystem - The spring system to integrate\r\n * @param weight - Blend weight [0-1] (default: 1.0)\r\n */\r\n constructor(springSystem: SpringSystem, weight: number = 1.0) {\r\n super();\r\n this._weight = weight;\r\n this._springSystem = springSystem;\r\n }\r\n\r\n /**\r\n * Get the spring system.\r\n */\r\n get springSystem(): SpringSystem {\r\n return this._springSystem;\r\n }\r\n\r\n /**\r\n * Apply spring physics to skeleton joints.\r\n */\r\n apply(_skeleton: SkeletonRig, deltaTime: number): void {\r\n if (!this._enabled || this._weight <= 0) {\r\n return;\r\n }\r\n\r\n // Update spring physics simulation\r\n this._springSystem.update(deltaTime);\r\n\r\n // Apply results to scene nodes with blending\r\n this._springSystem.applyToNodes(this._weight);\r\n }\r\n\r\n /**\r\n * Reset the spring system to initial state.\r\n */\r\n reset(): void {\r\n this._springSystem.reset();\r\n }\r\n\r\n /**\r\n * Get the blend weight for this processor.\r\n * @returns The current blend weight (0-1)\r\n */\r\n protected _getWeight(): number {\r\n return this._weight;\r\n }\r\n\r\n /**\r\n * Set the blend weight for this processor.\r\n * @param value - New blend weight (0-1)\r\n */\r\n protected _setWeight(value: number): void {\r\n this._weight = Math.max(0, Math.min(1, value));\r\n }\r\n}\r\n"],"names":["SpringModifier","SkeletonModifier","_springSystem","_weight","springSystem","weight","apply","_skeleton","deltaTime","_enabled","update","applyToNodes","reset","_setWeight","value","Math","max","min"],"mappings":";;AAIA;;;;;;;;;IAUO,MAAMA,cAAuBC,SAAAA,gBAAAA,CAAAA;IAC1BC,aAA4B;IAC5BC,OAAgB;AAExB;;;;;AAKC,MACD,WAAYC,CAAAA,YAA0B,EAAEC,MAAAA,GAAiB,GAAG,CAAE;QAC5D,KAAK,EAAA;QACL,IAAI,CAACF,OAAO,GAAGE,MAAAA;QACf,IAAI,CAACH,aAAa,GAAGE,YAAAA;AACvB;AAEA;;AAEC,MACD,IAAIA,YAA6B,GAAA;QAC/B,OAAO,IAAI,CAACF,aAAa;AAC3B;AAEA;;AAEC,MACDI,KAAMC,CAAAA,SAAsB,EAAEC,SAAiB,EAAQ;QACrD,IAAI,CAAC,IAAI,CAACC,QAAQ,IAAI,IAAI,CAACN,OAAO,IAAI,CAAG,EAAA;AACvC,YAAA;AACF;;AAGA,QAAA,IAAI,CAACD,aAAa,CAACQ,MAAM,CAACF,SAAAA,CAAAA;;AAG1B,QAAA,IAAI,CAACN,aAAa,CAACS,YAAY,CAAC,IAAI,CAACR,OAAO,CAAA;AAC9C;AAEA;;AAEC,MACDS,KAAc,GAAA;QACZ,IAAI,CAACV,aAAa,CAACU,KAAK,EAAA;AAC1B;AAEA;;;AAGC,MACD,UAA+B,GAAA;QAC7B,OAAO,IAAI,CAACT,OAAO;AACrB;AAEA;;;MAIUU,UAAWC,CAAAA,KAAa,EAAQ;QACxC,IAAI,CAACX,OAAO,GAAGY,IAAKC,CAAAA,GAAG,CAAC,CAAGD,EAAAA,IAAAA,CAAKE,GAAG,CAAC,CAAGH,EAAAA,KAAAA,CAAAA,CAAAA;AACzC;AACF;;;;"}
@@ -40,6 +40,9 @@ import { AnimationTrack } from './animationtrack.js';
40
40
  }
41
41
  this._interpolator = interp ?? null;
42
42
  }
43
+ /** {@inheritDoc AnimationTrack.clone} */ clone() {
44
+ return new NodeTranslationTrack(this._interpolator?.clone(), false);
45
+ }
43
46
  /** {@inheritDoc AnimationTrack.calculateState} */ calculateState(target, currentTime) {
44
47
  this._interpolator.interpolate(currentTime, this._state);
45
48
  return this._state;
@@ -1 +1 @@
1
- {"version":3,"file":"translationtrack.js","sources":["../../src/animation/translationtrack.ts"],"sourcesContent":["import type { InterpolationMode } from '@zephyr3d/base';\r\nimport { Interpolator, Vector3 } from '@zephyr3d/base';\r\nimport { AnimationTrack } from './animationtrack';\r\nimport type { SceneNode } from '../scene';\r\n\r\n/**\r\n * Translate animation track\r\n * @public\r\n */\r\nexport class NodeTranslationTrack extends AnimationTrack<Vector3> {\r\n private readonly _state: Vector3;\r\n private _interpolator!: Interpolator;\r\n /**\r\n * Create an instance of TranslationTrack\r\n */\r\n constructor();\r\n /**\r\n * Create an instance of TranslationTrack from keyframe values\r\n * @param interpolator - Interpolator object that contains the keyframe values\r\n * @param embedded - Whether this track be an embedded track\r\n */\r\n constructor(interpolator: Interpolator, embedded?: boolean);\r\n /**\r\n * Create an instance of TranslationTrack from keyframe values\r\n * @param mode - The interpolation mode of keyframes\r\n * @param keyFrames - Keyframe values\r\n * @param embedded - Whether this track be an embedded track\r\n */\r\n constructor(mode: InterpolationMode, keyFrames: { time: number; value: Vector3 }[], embedded?: boolean);\r\n constructor(\r\n modeOrInterpolator?: Interpolator | InterpolationMode,\r\n keyFramesOrEmbedded?: { time: number; value: Vector3 }[] | boolean,\r\n embedded?: boolean\r\n ) {\r\n if (modeOrInterpolator === undefined) {\r\n super(false);\r\n } else if (modeOrInterpolator instanceof Interpolator) {\r\n if (modeOrInterpolator.target !== 'vec3') {\r\n throw new Error(`TranslationTrack(): interpolator target must be 'vec3'`);\r\n }\r\n super((keyFramesOrEmbedded as boolean) ?? false);\r\n this._interpolator = modeOrInterpolator;\r\n } else {\r\n const keyFrames = keyFramesOrEmbedded as { time: number; value: Vector3 }[];\r\n const inputs = new Float32Array(keyFrames.map((val) => val.time));\r\n const outputs = new Float32Array(keyFrames.length * 3);\r\n for (let i = 0; i < keyFrames.length; i++) {\r\n outputs[i * 3 + 0] = keyFrames[i].value.x;\r\n outputs[i * 3 + 1] = keyFrames[i].value.y;\r\n outputs[i * 3 + 2] = keyFrames[i].value.z;\r\n }\r\n super(embedded ?? false);\r\n this._interpolator = new Interpolator(modeOrInterpolator, 'vec3', inputs, outputs);\r\n }\r\n this._state = new Vector3();\r\n this._jointIndex = -1;\r\n }\r\n get interpolator() {\r\n return this._interpolator;\r\n }\r\n set interpolator(interp: Interpolator) {\r\n if (interp && interp.target !== 'vec3') {\r\n throw new Error(`TranslationTrack(): interpolator target must be 'vec3'`);\r\n }\r\n this._interpolator = interp ?? null;\r\n }\r\n /** {@inheritDoc AnimationTrack.calculateState} */\r\n calculateState(target: object, currentTime: number) {\r\n this._interpolator.interpolate(currentTime, this._state);\r\n return this._state;\r\n }\r\n /** {@inheritDoc AnimationTrack.applyState} */\r\n applyState(node: SceneNode, state: Vector3) {\r\n node.position.set(state);\r\n }\r\n /** {@inheritDoc AnimationTrack.mixState} */\r\n mixState(a: Vector3, b: Vector3, t: number) {\r\n return new Vector3(a.x + t * (b.x - a.x), a.y + t * (b.y - a.y), a.z + t * (b.z - a.z));\r\n }\r\n /** {@inheritDoc AnimationTrack.getBlendId} */\r\n getBlendId() {\r\n return 'node-translation';\r\n }\r\n /** {@inheritDoc AnimationTrack.getDuration} */\r\n getDuration() {\r\n return this._interpolator.maxTime;\r\n }\r\n}\r\n"],"names":["NodeTranslationTrack","AnimationTrack","_state","_interpolator","modeOrInterpolator","keyFramesOrEmbedded","embedded","undefined","Interpolator","target","Error","keyFrames","inputs","Float32Array","map","val","time","outputs","length","i","value","x","y","z","Vector3","_jointIndex","interpolator","interp","calculateState","currentTime","interpolate","applyState","node","state","position","set","mixState","a","b","t","getBlendId","getDuration","maxTime"],"mappings":"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"}
1
+ {"version":3,"file":"translationtrack.js","sources":["../../src/animation/translationtrack.ts"],"sourcesContent":["import type { InterpolationMode } from '@zephyr3d/base';\r\nimport { Interpolator, Vector3 } from '@zephyr3d/base';\r\nimport { AnimationTrack } from './animationtrack';\r\nimport type { SceneNode } from '../scene';\r\n\r\n/**\r\n * Translate animation track\r\n * @public\r\n */\r\nexport class NodeTranslationTrack extends AnimationTrack<Vector3> {\r\n private readonly _state: Vector3;\r\n private _interpolator!: Interpolator;\r\n /**\r\n * Create an instance of TranslationTrack\r\n */\r\n constructor();\r\n /**\r\n * Create an instance of TranslationTrack from keyframe values\r\n * @param interpolator - Interpolator object that contains the keyframe values\r\n * @param embedded - Whether this track be an embedded track\r\n */\r\n constructor(interpolator: Interpolator, embedded?: boolean);\r\n /**\r\n * Create an instance of TranslationTrack from keyframe values\r\n * @param mode - The interpolation mode of keyframes\r\n * @param keyFrames - Keyframe values\r\n * @param embedded - Whether this track be an embedded track\r\n */\r\n constructor(mode: InterpolationMode, keyFrames: { time: number; value: Vector3 }[], embedded?: boolean);\r\n constructor(\r\n modeOrInterpolator?: Interpolator | InterpolationMode,\r\n keyFramesOrEmbedded?: { time: number; value: Vector3 }[] | boolean,\r\n embedded?: boolean\r\n ) {\r\n if (modeOrInterpolator === undefined) {\r\n super(false);\r\n } else if (modeOrInterpolator instanceof Interpolator) {\r\n if (modeOrInterpolator.target !== 'vec3') {\r\n throw new Error(`TranslationTrack(): interpolator target must be 'vec3'`);\r\n }\r\n super((keyFramesOrEmbedded as boolean) ?? false);\r\n this._interpolator = modeOrInterpolator;\r\n } else {\r\n const keyFrames = keyFramesOrEmbedded as { time: number; value: Vector3 }[];\r\n const inputs = new Float32Array(keyFrames.map((val) => val.time));\r\n const outputs = new Float32Array(keyFrames.length * 3);\r\n for (let i = 0; i < keyFrames.length; i++) {\r\n outputs[i * 3 + 0] = keyFrames[i].value.x;\r\n outputs[i * 3 + 1] = keyFrames[i].value.y;\r\n outputs[i * 3 + 2] = keyFrames[i].value.z;\r\n }\r\n super(embedded ?? false);\r\n this._interpolator = new Interpolator(modeOrInterpolator, 'vec3', inputs, outputs);\r\n }\r\n this._state = new Vector3();\r\n this._jointIndex = -1;\r\n }\r\n get interpolator() {\r\n return this._interpolator;\r\n }\r\n set interpolator(interp: Interpolator) {\r\n if (interp && interp.target !== 'vec3') {\r\n throw new Error(`TranslationTrack(): interpolator target must be 'vec3'`);\r\n }\r\n this._interpolator = interp ?? null;\r\n }\r\n /** {@inheritDoc AnimationTrack.clone} */\r\n clone(): this {\r\n return new NodeTranslationTrack(this._interpolator?.clone(), false) as this;\r\n }\r\n /** {@inheritDoc AnimationTrack.calculateState} */\r\n calculateState(target: object, currentTime: number) {\r\n this._interpolator.interpolate(currentTime, this._state);\r\n return this._state;\r\n }\r\n /** {@inheritDoc AnimationTrack.applyState} */\r\n applyState(node: SceneNode, state: Vector3) {\r\n node.position.set(state);\r\n }\r\n /** {@inheritDoc AnimationTrack.mixState} */\r\n mixState(a: Vector3, b: Vector3, t: number) {\r\n return new Vector3(a.x + t * (b.x - a.x), a.y + t * (b.y - a.y), a.z + t * (b.z - a.z));\r\n }\r\n /** {@inheritDoc AnimationTrack.getBlendId} */\r\n getBlendId() {\r\n return 'node-translation';\r\n }\r\n /** {@inheritDoc AnimationTrack.getDuration} */\r\n getDuration() {\r\n return this._interpolator.maxTime;\r\n }\r\n}\r\n"],"names":["NodeTranslationTrack","AnimationTrack","_state","_interpolator","modeOrInterpolator","keyFramesOrEmbedded","embedded","undefined","Interpolator","target","Error","keyFrames","inputs","Float32Array","map","val","time","outputs","length","i","value","x","y","z","Vector3","_jointIndex","interpolator","interp","clone","calculateState","currentTime","interpolate","applyState","node","state","position","set","mixState","a","b","t","getBlendId","getDuration","maxTime"],"mappings":";;;AAKA;;;IAIO,MAAMA,oBAA6BC,SAAAA,cAAAA,CAAAA;IACvBC,MAAgB;IACzBC,aAA6B;AAkBrC,IAAA,WAAA,CACEC,kBAAqD,EACrDC,mBAAkE,EAClEC,QAAkB,CAClB;AACA,QAAA,IAAIF,uBAAuBG,SAAW,EAAA;AACpC,YAAA,KAAK,CAAC,KAAA,CAAA;SACD,MAAA,IAAIH,8BAA8BI,YAAc,EAAA;YACrD,IAAIJ,kBAAAA,CAAmBK,MAAM,KAAK,MAAQ,EAAA;AACxC,gBAAA,MAAM,IAAIC,KAAAA,CAAM,CAAC,sDAAsD,CAAC,CAAA;AAC1E;YACA,KAAK,CAAC,mBAAoC,IAAA,KAAA,CAAA;YAC1C,IAAI,CAACP,aAAa,GAAGC,kBAAAA;SAChB,MAAA;AACL,YAAA,MAAMO,SAAYN,GAAAA,mBAAAA;YAClB,MAAMO,MAAAA,GAAS,IAAIC,YAAaF,CAAAA,SAAAA,CAAUG,GAAG,CAAC,CAACC,GAAQA,GAAAA,GAAAA,CAAIC,IAAI,CAAA,CAAA;AAC/D,YAAA,MAAMC,OAAU,GAAA,IAAIJ,YAAaF,CAAAA,SAAAA,CAAUO,MAAM,GAAG,CAAA,CAAA;AACpD,YAAA,IAAK,IAAIC,CAAI,GAAA,CAAA,EAAGA,IAAIR,SAAUO,CAAAA,MAAM,EAAEC,CAAK,EAAA,CAAA;gBACzCF,OAAO,CAACE,CAAI,GAAA,CAAA,GAAI,CAAE,CAAA,GAAGR,SAAS,CAACQ,CAAE,CAAA,CAACC,KAAK,CAACC,CAAC;gBACzCJ,OAAO,CAACE,CAAI,GAAA,CAAA,GAAI,CAAE,CAAA,GAAGR,SAAS,CAACQ,CAAE,CAAA,CAACC,KAAK,CAACE,CAAC;gBACzCL,OAAO,CAACE,CAAI,GAAA,CAAA,GAAI,CAAE,CAAA,GAAGR,SAAS,CAACQ,CAAE,CAAA,CAACC,KAAK,CAACG,CAAC;AAC3C;AACA,YAAA,KAAK,CAACjB,QAAY,IAAA,KAAA,CAAA;AAClB,YAAA,IAAI,CAACH,aAAa,GAAG,IAAIK,YAAaJ,CAAAA,kBAAAA,EAAoB,QAAQQ,MAAQK,EAAAA,OAAAA,CAAAA;AAC5E;QACA,IAAI,CAACf,MAAM,GAAG,IAAIsB,OAAAA,EAAAA;QAClB,IAAI,CAACC,WAAW,GAAG,EAAC;AACtB;AACA,IAAA,IAAIC,YAAe,GAAA;QACjB,OAAO,IAAI,CAACvB,aAAa;AAC3B;IACA,IAAIuB,YAAAA,CAAaC,MAAoB,EAAE;AACrC,QAAA,IAAIA,MAAUA,IAAAA,MAAAA,CAAOlB,MAAM,KAAK,MAAQ,EAAA;AACtC,YAAA,MAAM,IAAIC,KAAAA,CAAM,CAAC,sDAAsD,CAAC,CAAA;AAC1E;QACA,IAAI,CAACP,aAAa,GAAGwB,MAAU,IAAA,IAAA;AACjC;AACA,8CACAC,KAAc,GAAA;AACZ,QAAA,OAAO,IAAI5B,oBAAqB,CAAA,IAAI,CAACG,aAAa,EAAEyB,KAAS,EAAA,EAAA,KAAA,CAAA;AAC/D;AACA,uDACAC,cAAAA,CAAepB,MAAc,EAAEqB,WAAmB,EAAE;QAClD,IAAI,CAAC3B,aAAa,CAAC4B,WAAW,CAACD,WAAa,EAAA,IAAI,CAAC5B,MAAM,CAAA;QACvD,OAAO,IAAI,CAACA,MAAM;AACpB;AACA,mDACA8B,UAAAA,CAAWC,IAAe,EAAEC,KAAc,EAAE;QAC1CD,IAAKE,CAAAA,QAAQ,CAACC,GAAG,CAACF,KAAAA,CAAAA;AACpB;AACA,iDACAG,QAASC,CAAAA,CAAU,EAAEC,CAAU,EAAEC,CAAS,EAAE;AAC1C,QAAA,OAAO,IAAIhB,OAAQc,CAAAA,CAAAA,CAAEjB,CAAC,GAAGmB,KAAKD,CAAAA,CAAElB,CAAC,GAAGiB,EAAEjB,CAAAA,CAAIiB,EAAAA,CAAAA,CAAEhB,CAAC,GAAGkB,CAAAA,IAAKD,CAAAA,CAAEjB,CAAC,GAAGgB,CAAAA,CAAEhB,CAAAA,GAAIgB,CAAEf,CAAAA,CAAC,GAAGiB,CAAAA,IAAKD,CAAEhB,CAAAA,CAAC,GAAGe,CAAAA,CAAEf,CAAC,CAADA,CAAAA;AACtF;AACA,mDACAkB,UAAa,GAAA;QACX,OAAO,kBAAA;AACT;AACA,oDACAC,WAAc,GAAA;AACZ,QAAA,OAAO,IAAI,CAACvC,aAAa,CAACwC,OAAO;AACnC;AACF;;;;"}
@@ -29,22 +29,22 @@ import '../utility/blueprint/material/texture.js';
29
29
  import { ScreenAdapter } from './screen.js';
30
30
  import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js';
31
31
 
32
- /**
33
- * Core engine class managing scripting, serialization, and rendering.
34
- *
35
- * Responsibilities:
36
- * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.
37
- * - Manages a {@link ResourceManager} for loading scenes and assets.
38
- * - Maintains a list of active renderable objects to be rendered each frame.
39
- * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.
40
- * - Supports enabling/disabling of runtime operations.
41
- *
42
- * @remarks
43
- * The engine can be configured with a virtual file system (VFS) and script root path.
44
- * It exposes methods to manage scripts on host objects, update scripts each frame,
45
- * load scenes from files, and render active objects.
46
- *
47
- * @public
32
+ /**
33
+ * Core engine class managing scripting, serialization, and rendering.
34
+ *
35
+ * Responsibilities:
36
+ * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.
37
+ * - Manages a {@link ResourceManager} for loading scenes and assets.
38
+ * - Maintains a list of active renderable objects to be rendered each frame.
39
+ * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.
40
+ * - Supports enabling/disabling of runtime operations.
41
+ *
42
+ * @remarks
43
+ * The engine can be configured with a virtual file system (VFS) and script root path.
44
+ * It exposes methods to manage scripts on host objects, update scripts each frame,
45
+ * load scenes from files, and render active objects.
46
+ *
47
+ * @public
48
48
  */ class Engine {
49
49
  _builtinsVFS;
50
50
  _scriptingSystem;
@@ -54,12 +54,12 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
54
54
  _screen;
55
55
  _activeRenderables;
56
56
  _loadingScenes;
57
- /**
58
- * Creates a new runtime manager.
59
- *
60
- * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.
61
- * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.
62
- * @param enabled - Whether runtime operations are active. Defaults to `true`.
57
+ /**
58
+ * Creates a new runtime manager.
59
+ *
60
+ * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.
61
+ * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.
62
+ * @param enabled - Whether runtime operations are active. Defaults to `true`.
63
63
  */ constructor(VFS, scriptsRoot, enabled){
64
64
  VFS = VFS ?? new HttpFS('./');
65
65
  this._builtinsVFS = null;
@@ -74,17 +74,24 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
74
74
  this._loadingScenes = {};
75
75
  this._screen = new ScreenAdapter();
76
76
  }
77
- /**
78
- * Exposes the instance of {@link ScriptingSystem}.
77
+ /**
78
+ * Exposes the instance of {@link ScriptingSystem}.
79
79
  */ get scriptingSystem() {
80
80
  return this._scriptingSystem;
81
81
  }
82
- /**
83
- * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.
82
+ /**
83
+ * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.
84
84
  */ get VFS() {
85
85
  return this._scriptingSystem.registry.VFS;
86
86
  }
87
- set VFS(vfs) {
87
+ /**
88
+ * Replaces the virtual file system used by the engine.
89
+ *
90
+ * The previous resource manager VFS is closed, the scripting registry is updated,
91
+ * and built-in assets are remounted on the new VFS.
92
+ *
93
+ * @param vfs - New virtual file system.
94
+ */ set VFS(vfs) {
88
95
  if (vfs !== this._resourceManager.VFS) {
89
96
  this._resourceManager.VFS?.close();
90
97
  this._resourceManager.VFS = vfs;
@@ -92,24 +99,24 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
92
99
  this.ensureBuiltinVFS();
93
100
  }
94
101
  }
95
- /**
96
- * Exposes the instance of {@link ResourceManager}.
102
+ /**
103
+ * Exposes the instance of {@link ResourceManager}.
97
104
  */ get resourceManager() {
98
105
  return this._resourceManager;
99
106
  }
100
- /**
101
- * Exposes the shared runtime MSDF text atlas manager.
107
+ /**
108
+ * Exposes the shared runtime MSDF text atlas manager.
102
109
  */ get msdfTextAtlasManager() {
103
110
  return this._msdfTextAtlasManager;
104
111
  }
105
- /**
106
- * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.
107
- *
108
- * Existing scene nodes that still reference this font asset are not updated automatically.
109
- * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.
110
- *
111
- * @param fontAsset - The loaded font asset to release.
112
- * @returns `true` if either the atlas cache or the font cache had an entry to remove.
112
+ /**
113
+ * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.
114
+ *
115
+ * Existing scene nodes that still reference this font asset are not updated automatically.
116
+ * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.
117
+ *
118
+ * @param font - The loaded font asset path to release.
119
+ * @returns `true` if either the atlas cache or the font cache had an entry to remove.
113
120
  */ releaseFontAsset(font) {
114
121
  const fontAsset = this._resourceManager.getFontAsset(font);
115
122
  if (!fontAsset) {
@@ -119,21 +126,21 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
119
126
  const fontReleased = this._resourceManager.releaseFontAsset(fontAsset);
120
127
  return atlasReleased || fontReleased;
121
128
  }
122
- /**
123
- * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.
124
- *
125
- * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.
126
- * Existing scene nodes that reference this font asset will use the updated atlas automatically.
127
- *
128
- * @param font - The font asset path to configure the MSDF atlas for.
129
- * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).
130
- * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).
131
- * @param distanceRange - The distance range for MSDF generation. Defaults to 4.
132
- * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.
133
- * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.
134
- *
135
- * @remarks
136
- * The font asset must be loaded and available in the resource manager for the atlas to be configured.
129
+ /**
130
+ * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.
131
+ *
132
+ * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.
133
+ * Existing scene nodes that reference this font asset will use the updated atlas automatically.
134
+ *
135
+ * @param font - The font asset path to configure the MSDF atlas for.
136
+ * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).
137
+ * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).
138
+ * @param distanceRange - The distance range for MSDF generation. Defaults to 4.
139
+ * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.
140
+ * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.
141
+ *
142
+ * @remarks
143
+ * The font asset must be loaded and available in the resource manager for the atlas to be configured.
137
144
  */ configureMSDFAtlas(font, pageSize, glyphSize, distanceRange, padding) {
138
145
  const fontAsset = this._resourceManager.getFontAsset(font);
139
146
  if (!fontAsset) {
@@ -143,94 +150,131 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
143
150
  this._msdfTextAtlasManager.configureAtlas(fontAsset, pageSize, glyphSize, distanceRange, padding);
144
151
  return true;
145
152
  }
146
- /**
147
- * Exposes the active {@link ScreenAdapter}.
153
+ /**
154
+ * Exposes the active {@link ScreenAdapter}.
148
155
  */ get screen() {
149
156
  return this._screen;
150
157
  }
151
158
  /** @internal */ async init() {
152
159
  await this.ensureBuiltinVFS();
153
160
  }
154
- /**
155
- * Detaches all scripts from all hosts, if enabled.
156
- *
157
- * No-op when `enabled === false`.
161
+ /**
162
+ * Detaches all scripts from all hosts, if enabled.
163
+ *
164
+ * No-op when `enabled === false`.
158
165
  */ detachAllScripts() {
159
166
  if (this._enabled) {
160
167
  this._scriptingSystem.detachAllScripts();
161
168
  }
162
169
  }
163
- /**
164
- * Loads a runtime script class from file
165
- * @param module - file path
166
- * @returns The runtime script class or null
170
+ /**
171
+ * Loads a runtime script class from file
172
+ * @param module - file path
173
+ * @returns The runtime script class or null
167
174
  */ async loadRuntimeScriptClass(module) {
168
175
  return await this._scriptingSystem.loadRuntimeScriptClass(module);
169
176
  }
170
- /**
171
- * Attaches a script module to the given host, if enabled.
172
- *
173
- * When disabled, this method resolves to `null` without side effects.
174
- *
175
- * @typeParam T - Host type.
176
- * @param host - Host object to attach the script to.
177
- * @param module - Module identifier to resolve and load.
178
- * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.
177
+ /**
178
+ * Attaches a script module to the given host, if enabled.
179
+ *
180
+ * When disabled, this method resolves to `null` without side effects.
181
+ *
182
+ * @typeParam T - Host type.
183
+ * @param host - Host object to attach the script to.
184
+ * @param module - Module identifier to resolve and load.
185
+ * @param config - Optional configuration passed to the script instance.
186
+ * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.
179
187
  */ async attachScript(host, module, config) {
180
188
  return this._enabled ? await this._scriptingSystem.attachScript(host, module, config) : null;
181
189
  }
182
- /**
183
- * Detaches a script from a host, by module ID or instance, if enabled.
184
- *
185
- * No-op when disabled.
186
- *
187
- * @typeParam T - Host type.
188
- * @param host - Host to detach from.
189
- * @param idOrInstance - Target script by module ID or instance reference.
190
+ /**
191
+ * Detaches a script from a host, by module ID or instance, if enabled.
192
+ *
193
+ * No-op when disabled.
194
+ *
195
+ * @typeParam T - Host type.
196
+ * @param host - Host to detach from.
197
+ * @param idOrInstance - Target script by module ID or instance reference.
190
198
  */ detachScript(host, idOrInstance) {
191
199
  if (this._enabled) {
192
200
  this._scriptingSystem.detachScript(host, idOrInstance);
193
201
  }
194
202
  }
195
- /**
196
- * Gets all scripts attached to a host.
197
- *
198
- * Delegates to {@link ScriptingSystem.getScriptObjects}.
199
- *
200
- * @typeParam T - Expected script type.
201
- * @param host - Host object to query.
202
- * @returns Script instances attached to the host, or an empty array.
203
+ /**
204
+ * Gets all scripts attached to a host.
205
+ *
206
+ * Delegates to {@link ScriptingSystem.getScriptObjects}.
207
+ *
208
+ * @typeParam T - Expected script type.
209
+ * @param host - Host object to query.
210
+ * @returns Script instances attached to the host, or an empty array.
203
211
  */ getScriptObjects(host) {
204
212
  return this._scriptingSystem.getScriptObjects(host);
205
213
  }
206
- /**
207
- * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.
208
- *
209
- * @param deltaTime - Time since last update in Seconds.
210
- * @param elapsedTime - Total elapsed time in Seconds.
214
+ /**
215
+ * Ticks all attached scripts by calling their `onUpdate` hooks, if enabled.
216
+ *
217
+ * @param deltaTime - Time since last update in Seconds.
218
+ * @param elapsedTime - Total elapsed time in Seconds.
211
219
  */ update(deltaTime, elapsedTime) {
212
220
  if (this._enabled) {
213
221
  this._scriptingSystem.update(deltaTime, elapsedTime);
214
222
  }
215
223
  }
216
- async loadSceneFromFile(path) {
224
+ /**
225
+ * Loads a scene from a file path.
226
+ *
227
+ * Concurrent requests for the same normalized path share the same loading promise.
228
+ * Scripts declared on the scene and its nodes are attached after the scene is loaded.
229
+ *
230
+ * @param path - Scene file path in the current VFS.
231
+ * @returns The loaded scene, or `null` when loading fails.
232
+ */ async loadSceneFromFile(path) {
217
233
  path = this.VFS.normalizePath(path);
218
234
  if (!this._loadingScenes[path]) {
219
235
  this._loadingScenes[path] = this._loadScene(path);
220
236
  }
221
237
  return this._loadingScenes[path];
222
238
  }
223
- setRenderable(renderable, layer = 0, hook) {
224
- if (!this._activeRenderables[layer]) {
239
+ /**
240
+ * Sets or clears the renderable for a render layer.
241
+ *
242
+ * Passing `null` clears the layer. Object renderables are held through a strong reference wrapper,
243
+ * while render functions are stored directly.
244
+ *
245
+ * @param renderable - Renderable object or render function to assign, or `null` to clear.
246
+ * @param layer - Render layer index. Defaults to `0`.
247
+ * @param hook - Optional render hook invoked before and after this layer renders.
248
+ */ setRenderable(renderable, layer = 0, hook) {
249
+ const entry = this._activeRenderables[layer];
250
+ if (!entry) {
225
251
  this._activeRenderables[layer] = {
226
- renderable: new DRef(null),
227
- hook: null
252
+ renderable: renderable ? typeof renderable === 'function' ? renderable : new DRef(renderable) : null,
253
+ hook: hook ?? null
228
254
  };
255
+ } else {
256
+ if (entry.renderable) {
257
+ if (entry.renderable instanceof DRef) {
258
+ entry.renderable.dispose();
259
+ }
260
+ entry.renderable = null;
261
+ }
262
+ if (typeof renderable === 'function') {
263
+ entry.renderable = renderable;
264
+ } else if (renderable) {
265
+ entry.renderable = new DRef(renderable);
266
+ }
267
+ entry.hook = hook ?? null;
229
268
  }
230
- this._activeRenderables[layer].hook = hook ?? null;
231
- this._activeRenderables[layer].renderable.set(renderable);
232
269
  }
233
- async readFile(path, encoding) {
270
+ /**
271
+ * Reads a file from the current VFS.
272
+ *
273
+ * @typeParam T - Requested read encoding.
274
+ * @param path - File path to read.
275
+ * @param encoding - Optional read encoding. Defaults to `binary`.
276
+ * @returns The file content, or `null` when the read fails.
277
+ */ async readFile(path, encoding) {
234
278
  try {
235
279
  const content = await this.VFS.readFile(path, {
236
280
  encoding: encoding ?? 'binary'
@@ -241,7 +285,15 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
241
285
  return null;
242
286
  }
243
287
  }
244
- async startup(startupScene, splashScreen, startupScript) {
288
+ /**
289
+ * Starts the runtime by optionally showing a splash screen, running a startup script,
290
+ * and loading the startup scene.
291
+ *
292
+ * @param startupScene - Optional scene path rendered on layer `0` after startup completes.
293
+ * @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.
294
+ * @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`
295
+ * extension is removed before loading.
296
+ */ async startup(startupScene, splashScreen, startupScript) {
245
297
  const splashScreenLayer = 9999;
246
298
  if (splashScreen) {
247
299
  const splashScreenScene = await this.loadSceneFromFile(splashScreen);
@@ -259,14 +311,26 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
259
311
  }
260
312
  this.setRenderable(null, splashScreenLayer);
261
313
  }
262
- render() {
314
+ /**
315
+ * Renders all active render layers.
316
+ *
317
+ * Each layer's `beforeRender` hook can return `false` to skip rendering that layer.
318
+ * The `afterRender` hook is invoked after the render attempt.
319
+ */ render() {
263
320
  this._activeRenderables.forEach((info)=>{
264
- const render = info.hook?.beforeRender ? info.hook.beforeRender(info.renderable.get() ?? null) ?? true : true;
321
+ if (!info.renderable) {
322
+ return;
323
+ }
324
+ const render = info.hook?.beforeRender ? info.hook.beforeRender(typeof info.renderable === 'function' ? info.renderable : info.renderable.get()) ?? true : true;
265
325
  if (render) {
266
- info.renderable.get()?.render();
326
+ if (typeof info.renderable === 'function') {
327
+ info.renderable();
328
+ } else {
329
+ info.renderable.get()?.render();
330
+ }
267
331
  }
268
332
  if (info.hook?.afterRender) {
269
- info.hook.afterRender(info.renderable.get() ?? null);
333
+ info.hook.afterRender(typeof info.renderable === 'function' ? info.renderable : info.renderable.get());
270
334
  }
271
335
  });
272
336
  }
@@ -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 * 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: 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 fontAsset - The loaded font asset 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 * @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 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 setRenderable(renderable: Nullable<IRenderable>, layer = 0, hook?: IRenderHook) {\n if (!this._activeRenderables[layer]) {\n this._activeRenderables[layer] = {\n renderable: new DRef<IRenderable>(null),\n hook: null\n };\n }\n this._activeRenderables[layer].hook = hook ?? null;\n this._activeRenderables[layer].renderable.set(renderable);\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 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 render() {\n this._activeRenderables.forEach((info) => {\n const render = info.hook?.beforeRender\n ? (info.hook.beforeRender(info.renderable.get() ?? null) ?? true)\n : true;\n if (render) {\n info.renderable.get()?.render();\n }\n if (info.hook?.afterRender) {\n info.hook.afterRender(info.renderable.get() ?? null);\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","DRef","set","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","dispose","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\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 /**\r\n * Replaces the virtual file system used by the engine.\r\n *\r\n * The previous resource manager VFS is closed, the scripting registry is updated,\r\n * and built-in assets are remounted on the new VFS.\r\n *\r\n * @param vfs - New virtual file system.\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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"}