@zephyr3d/scene 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/animation.js +4 -33
- package/dist/animation/animation.js.map +1 -1
- package/dist/animation/animationset.js +24 -11
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/animationtrack.js +1 -0
- package/dist/animation/animationtrack.js.map +1 -1
- package/dist/animation/eulerrotationtrack.js +0 -1
- package/dist/animation/eulerrotationtrack.js.map +1 -1
- package/dist/animation/ik/ccd_solver.js +372 -0
- package/dist/animation/ik/ccd_solver.js.map +1 -0
- package/dist/animation/ik/fabrik_solver.js +399 -0
- package/dist/animation/ik/fabrik_solver.js.map +1 -0
- package/dist/animation/ik/ik_angle_constraint.js +181 -0
- package/dist/animation/ik/ik_angle_constraint.js.map +1 -0
- package/dist/animation/ik/ik_chain.js +163 -0
- package/dist/animation/ik/ik_chain.js.map +1 -0
- package/dist/animation/ik/ik_chain_builder.js +68 -0
- package/dist/animation/ik/ik_chain_builder.js.map +1 -0
- package/dist/animation/ik/ik_constraint.js +25 -0
- package/dist/animation/ik/ik_constraint.js.map +1 -0
- package/dist/animation/ik/ik_pole_constraint.js +123 -0
- package/dist/animation/ik/ik_pole_constraint.js.map +1 -0
- package/dist/animation/ik/ik_solver.js +48 -0
- package/dist/animation/ik/ik_solver.js.map +1 -0
- package/dist/animation/ik/ik_track.js +96 -0
- package/dist/animation/ik/ik_track.js.map +1 -0
- package/dist/animation/ik/ik_utils.js +270 -0
- package/dist/animation/ik/ik_utils.js.map +1 -0
- package/dist/animation/ik/two_bone_ik_solver.js +332 -0
- package/dist/animation/ik/two_bone_ik_solver.js.map +1 -0
- package/dist/animation/ik_modifier.js +61 -0
- package/dist/animation/ik_modifier.js.map +1 -0
- package/dist/animation/ik_postprocessor.js +71 -0
- package/dist/animation/ik_postprocessor.js.map +1 -0
- package/dist/animation/manual_transform_processor.js +156 -0
- package/dist/animation/manual_transform_processor.js.map +1 -0
- package/dist/animation/morphtarget.js +7 -1
- package/dist/animation/morphtarget.js.map +1 -1
- package/dist/animation/morphtrack.js +3 -3
- package/dist/animation/morphtrack.js.map +1 -1
- package/dist/animation/proptrack.js +37 -41
- package/dist/animation/proptrack.js.map +1 -1
- package/dist/animation/rotationtrack.js +0 -1
- package/dist/animation/rotationtrack.js.map +1 -1
- package/dist/animation/scaletrack.js +0 -1
- package/dist/animation/scaletrack.js.map +1 -1
- package/dist/animation/skeleton.js +57 -60
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skeleton_modifier.js +38 -0
- package/dist/animation/skeleton_modifier.js.map +1 -0
- package/dist/animation/skeleton_postprocessor.js +50 -0
- package/dist/animation/skeleton_postprocessor.js.map +1 -0
- package/dist/animation/spring/multi_chain_spring_system.js +503 -0
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -0
- package/dist/animation/spring/spring_chain.js +103 -0
- package/dist/animation/spring/spring_chain.js.map +1 -0
- package/dist/animation/spring/spring_collider.js +247 -0
- package/dist/animation/spring/spring_collider.js.map +1 -0
- package/dist/animation/spring/spring_constraint.js +21 -0
- package/dist/animation/spring/spring_constraint.js.map +1 -0
- package/dist/animation/spring/spring_particle.js +20 -0
- package/dist/animation/spring/spring_particle.js.map +1 -0
- package/dist/animation/spring/spring_system.js +526 -0
- package/dist/animation/spring/spring_system.js.map +1 -0
- package/dist/animation/spring_modifier.js +45 -0
- package/dist/animation/spring_modifier.js.map +1 -0
- package/dist/animation/spring_postprocessor.js +54 -0
- package/dist/animation/spring_postprocessor.js.map +1 -0
- package/dist/animation/translationtrack.js +0 -1
- package/dist/animation/translationtrack.js.map +1 -1
- package/dist/app/api.js +13 -4
- package/dist/app/api.js.map +1 -1
- package/dist/app/app.js +13 -1
- package/dist/app/app.js.map +1 -1
- package/dist/app/engine.js +33 -45
- package/dist/app/engine.js.map +1 -1
- package/dist/app/inputmgr.js.map +1 -1
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/screen.js +318 -0
- package/dist/app/screen.js.map +1 -0
- package/dist/app/scriptingsystem.js +10 -6
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +11 -22
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/assetmanager.js +79 -58
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/builtin.js +5 -5
- package/dist/asset/builtin.js.map +1 -1
- package/dist/asset/loaders/dds/dds.js +6 -2
- package/dist/asset/loaders/dds/dds.js.map +1 -1
- package/dist/asset/loaders/dds/dds_loader.js +1 -1
- package/dist/asset/loaders/dds/dds_loader.js.map +1 -1
- package/dist/asset/loaders/gltf/gltf_loader.js +14 -6
- package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
- package/dist/asset/loaders/gltf/helpers.js +6 -2
- package/dist/asset/loaders/gltf/helpers.js.map +1 -1
- package/dist/asset/loaders/hdr/hdr.js +22 -15
- package/dist/asset/loaders/hdr/hdr.js.map +1 -1
- package/dist/asset/loaders/image/tga_Loader.js +2 -1
- package/dist/asset/loaders/image/tga_Loader.js.map +1 -1
- package/dist/asset/loaders/image/webimage_loader.js.map +1 -1
- package/dist/asset/loaders/loader.js +2 -2
- package/dist/asset/loaders/loader.js.map +1 -1
- package/dist/asset/model.js +9 -5
- package/dist/asset/model.js.map +1 -1
- package/dist/blitter/bilateralblur.js.map +1 -1
- package/dist/blitter/blitter.js +9 -11
- package/dist/blitter/blitter.js.map +1 -1
- package/dist/blitter/box.js +0 -1
- package/dist/blitter/box.js.map +1 -1
- package/dist/blitter/copy.js.map +1 -1
- package/dist/blitter/gaussianblur.js.map +1 -1
- package/dist/camera/base.js +1 -3
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +121 -37
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/fps.js +19 -17
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +45 -43
- package/dist/camera/orbit.js.map +1 -1
- package/dist/camera/orthocamera.js +27 -21
- package/dist/camera/orthocamera.js.map +1 -1
- package/dist/camera/perspectivecamera.js +28 -19
- package/dist/camera/perspectivecamera.js.map +1 -1
- package/dist/index.d.ts +15802 -15577
- package/dist/index.js +33 -11
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js.map +1 -1
- package/dist/material/grassmaterial.js.map +1 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +11 -5
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +10 -9
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/albedocolor.js.map +1 -1
- package/dist/material/mixins/foliage.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +66 -4
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +7 -0
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +3 -3
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/brdf.js.map +1 -1
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mixins/texture.js +3 -0
- package/dist/material/mixins/texture.js.map +1 -1
- package/dist/material/mixins/vertexcolor.js.map +1 -1
- package/dist/material/particle.js.map +1 -1
- package/dist/material/pbrblueprint.js +180 -22
- package/dist/material/pbrblueprint.js.map +1 -1
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/shader/helper.js +41 -56
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/sprite.js +301 -0
- package/dist/material/sprite.js.map +1 -0
- package/dist/material/sprite3d.js +301 -0
- package/dist/material/sprite3d.js.map +1 -0
- package/dist/material/sprite3d_std.js +116 -0
- package/dist/material/sprite3d_std.js.map +1 -0
- package/dist/material/sprite3dblueprint.js +235 -0
- package/dist/material/sprite3dblueprint.js.map +1 -0
- package/dist/material/sprite_std.js +116 -0
- package/dist/material/sprite_std.js.map +1 -0
- package/dist/material/spriteblueprint.js +235 -0
- package/dist/material/spriteblueprint.js.map +1 -0
- package/dist/material/terrain-cm.js +0 -1
- package/dist/material/terrain-cm.js.map +1 -1
- package/dist/material/unlit.js.map +1 -1
- package/dist/material/water.js.map +1 -1
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/compositor.js.map +1 -1
- package/dist/posteffect/fxaa.js.map +1 -1
- package/dist/posteffect/grayscale.js.map +1 -1
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/posteffect.js.map +1 -1
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/ssr.js +7 -5
- package/dist/posteffect/ssr.js.map +1 -1
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/posteffect/tonemap.js.map +1 -1
- package/dist/render/abuffer_oit.js +8 -6
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +0 -10
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cluster_light.js +4 -4
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/cull_visitor.js +15 -17
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/depthpass.js +3 -4
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable.js +15 -0
- package/dist/render/drawable.js.map +1 -0
- package/dist/render/drawable_mixin.js +8 -4
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +3 -1
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +67 -64
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/fullscreenquad.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +3 -1
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/globalbindgroup_allocator.js +3 -1
- package/dist/render/globalbindgroup_allocator.js.map +1 -1
- package/dist/render/hzb.js +1 -2
- package/dist/render/hzb.js.map +1 -1
- package/dist/render/lightpass.js +13 -13
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/objectcolorpass.js +4 -7
- package/dist/render/objectcolorpass.js.map +1 -1
- package/dist/render/primitive.js +4 -5
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/render_queue.js +10 -5
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +16 -22
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/renderpass.js +27 -52
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/rendertarget.js +5 -0
- package/dist/render/rendertarget.js.map +1 -0
- package/dist/render/screenrendertarget.js +56 -0
- package/dist/render/screenrendertarget.js.map +1 -0
- package/dist/render/shadowmap_pass.js +4 -5
- package/dist/render/shadowmap_pass.js.map +1 -1
- package/dist/render/sky.js +16 -14
- package/dist/render/sky.js.map +1 -1
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/basesprite.js +296 -0
- package/dist/scene/basesprite.js.map +1 -0
- package/dist/scene/batchgroup.js +4 -2
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +9 -10
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/graph_node.js.map +1 -1
- package/dist/scene/light.js +22 -4
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +96 -26
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/octree.js.map +1 -1
- package/dist/scene/particlesys.js +25 -22
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/raycast_visitor.js +0 -16
- package/dist/scene/raycast_visitor.js.map +1 -1
- package/dist/scene/scene.js +7 -4
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +20 -35
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/sprite.js +18 -0
- package/dist/scene/sprite.js.map +1 -0
- package/dist/scene/sprite3d.js +18 -0
- package/dist/scene/sprite3d.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +5 -4
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/grassmaterial.js +3 -1
- package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +65 -48
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/water.js +35 -30
- package/dist/scene/water.js.map +1 -1
- package/dist/shaders/atmosphere.js +17 -29
- package/dist/shaders/atmosphere.js.map +1 -1
- package/dist/shaders/fog.js.map +1 -1
- package/dist/shaders/misc.js.map +1 -1
- package/dist/shaders/noise.js.map +1 -1
- package/dist/shaders/pbr.js.map +1 -1
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shaders/ssr.js.map +1 -1
- package/dist/shaders/temporal.js.map +1 -1
- package/dist/shaders/water.js.map +1 -1
- package/dist/shadow/esm.js +1 -1
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/pcf_opt.js.map +1 -1
- package/dist/shadow/pcf_pd.js.map +1 -1
- package/dist/shadow/shader.js +3 -1
- package/dist/shadow/shader.js.map +1 -1
- package/dist/shadow/shadow_impl.js.map +1 -1
- package/dist/shadow/shadowmapper.js +6 -18
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/ssm.js.map +1 -1
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/box.js +9 -3
- package/dist/shapes/box.js.map +1 -1
- package/dist/shapes/cylinder.js +2 -2
- package/dist/shapes/cylinder.js.map +1 -1
- package/dist/shapes/plane.js +2 -2
- package/dist/shapes/plane.js.map +1 -1
- package/dist/shapes/shape.js +2 -1
- package/dist/shapes/shape.js.map +1 -1
- package/dist/shapes/sphere.js +2 -2
- package/dist/shapes/sphere.js.map +1 -1
- package/dist/shapes/tetrahedron.js +5 -6
- package/dist/shapes/tetrahedron.js.map +1 -1
- package/dist/shapes/torus.js +2 -2
- package/dist/shapes/torus.js.map +1 -1
- package/dist/utility/aabbtree.js +1 -1
- package/dist/utility/aabbtree.js.map +1 -1
- package/dist/utility/blueprint/common/constants.js +578 -104
- package/dist/utility/blueprint/common/constants.js.map +1 -1
- package/dist/utility/blueprint/common/math.js +471 -9
- package/dist/utility/blueprint/common/math.js.map +1 -1
- package/dist/utility/blueprint/common.js +1 -1
- package/dist/utility/blueprint/common.js.map +1 -1
- package/dist/utility/blueprint/material/func.js +9 -5
- package/dist/utility/blueprint/material/func.js.map +1 -1
- package/dist/utility/blueprint/material/inputs.js.map +1 -1
- package/dist/utility/blueprint/material/ir.js +288 -80
- package/dist/utility/blueprint/material/ir.js.map +1 -1
- package/dist/utility/blueprint/material/pbr.js +92 -4
- package/dist/utility/blueprint/material/pbr.js.map +1 -1
- package/dist/utility/blueprint/material/texture.js +62 -45
- package/dist/utility/blueprint/material/texture.js.map +1 -1
- package/dist/utility/blueprint/node.js +28 -1
- package/dist/utility/blueprint/node.js.map +1 -1
- package/dist/utility/bounding_volume.js.map +1 -1
- package/dist/utility/debug.js.map +1 -1
- package/dist/utility/draco/decoder.js.map +1 -1
- package/dist/utility/misc.js +1 -1
- package/dist/utility/misc.js.map +1 -1
- package/dist/utility/panorama.js.map +1 -1
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/rendermipmap.js.map +1 -1
- package/dist/utility/serialization/json.js +19 -15
- package/dist/utility/serialization/json.js.map +1 -1
- package/dist/utility/serialization/manager.js +89 -22
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +44 -41
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +4 -3
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +97 -9
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/common.js +102 -28
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +14 -12
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +216 -26
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +71 -100
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/misc.js +3 -2
- package/dist/utility/serialization/scene/misc.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +42 -9
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/particle.js +7 -5
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/primitive.js +18 -15
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +3 -2
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/sprite.js +164 -0
- package/dist/utility/serialization/scene/sprite.js.map +1 -0
- package/dist/utility/serialization/scene/terrain.js +8 -6
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +11 -9
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js +6 -0
- package/dist/utility/serialization/types.js.map +1 -0
- package/dist/utility/shprojector.js.map +1 -1
- package/dist/utility/textures/ggxlut.js.map +1 -1
- package/dist/utility/textures/gradientnoise.js.map +1 -1
- package/dist/utility/textures/randomnoise.js.map +1 -1
- package/dist/values.js +14 -14
- package/dist/values.js.map +1 -1
- package/package.json +80 -80
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptingsystem.js","sources":["../../src/app/scriptingsystem.ts"],"sourcesContent":["import type { IDisposable, VFS } from '@zephyr3d/base';\r\nimport { HttpFS } from '@zephyr3d/base';\r\nimport { ScriptRegistry } from './scriptregistry';\r\nimport { RuntimeScript } from './runtimescript';\r\n\r\n/**\r\n * A host object that supports disposal.\r\n *\r\n * Hosts are objects to which scripts can be attached. They are expected to\r\n * emit a `'dispose'` event compatible with `IDisposable` so that scripts\r\n * can be automatically detached when the host is destroyed.\r\n *\r\n * @public\r\n */\r\nexport type Host = IDisposable;\r\n\r\n/**\r\n * Options for configuring a `ScriptingSystem`.\r\n *\r\n * @public\r\n */\r\nexport type ScriptingSystemOptions = {\r\n /** Virtual file system used by the script registry. Defaults to `new HttpFS('./')`. */\r\n VFS?: VFS;\r\n /** Root path for scripts within the VFS. Defaults to `/`. */\r\n scriptsRoot?: string;\r\n /** If true, enables editor-oriented behaviors in the registry. Defaults to `false`. */\r\n editorMode?: boolean;\r\n /**\r\n * Optional string appended to dynamic import URLs (e.g., for cache busting).\r\n * Example: `'?v=' + Date.now()`\r\n */\r\n importComment?: string;\r\n /**\r\n * Optional callback invoked when a module fails to load.\r\n * @param e - The error that occurred.\r\n * @param id - The module ID that failed to load.\r\n */\r\n onLoadError?: (e: unknown, id: string) => void;\r\n};\r\n\r\n/**\r\n * Information about a script attached to a host.\r\n *\r\n * @public\r\n */\r\nexport interface IAttachedScript {\r\n /** The logical module identifier used to resolve the script. */\r\n id: string;\r\n /** The resolved runtime URL used for dynamic import. */\r\n url: string;\r\n /** The instantiated runtime script. */\r\n instance: RuntimeScript<any>;\r\n}\r\n\r\n/**\r\n * Script system that resolves, loads, and manages lifecycle of runtime scripts.\r\n *\r\n * Responsibilities:\r\n * - Resolves module IDs to URLs via {@link ScriptRegistry}\r\n * - Dynamically imports modules and instantiates a `RuntimeScript` (default export)\r\n * - Tracks attachments between hosts and script instances\r\n * - Bridges script lifecycle hooks: `onCreated`, `onAttached`, `onDetached`, `onDestroy`, `onUpdate`\r\n * - Auto-detaches scripts when a host is disposed\r\n *\r\n * Notes:\r\n * - Multiple hosts can reference the same `RuntimeScript` instance; destruction\r\n * occurs when the last host detaches.\r\n * - Errors during load/attach/update are caught and logged; an optional\r\n * `onLoadError` callback can be provided.\r\n *\r\n * @public\r\n */\r\nexport class ScriptingSystem {\r\n private _registry: ScriptRegistry;\r\n private _hostScripts: Map<Host, IAttachedScript[]>;\r\n private _scriptHosts: Map<RuntimeScript<any>, Host[]>;\r\n private _onLoadError?: (e: unknown, id: string) => void;\r\n private _importComment?: string;\r\n\r\n /**\r\n * Constructs a new scripting system.\r\n *\r\n * @param opts - Optional configuration.\r\n */\r\n constructor(opts: ScriptingSystemOptions = {}) {\r\n this._registry = new ScriptRegistry(\r\n opts.VFS ?? new HttpFS('./'),\r\n opts.scriptsRoot ?? '/',\r\n opts.editorMode ?? false\r\n );\r\n this._hostScripts = new Map();\r\n this._scriptHosts = new Map();\r\n this._importComment = opts.importComment;\r\n this._onLoadError = opts.onLoadError;\r\n }\r\n\r\n /**\r\n * Accessor for the underlying script registry used for module resolution.\r\n */\r\n get registry() {\r\n return this._registry;\r\n }\r\n\r\n /**\r\n * Attaches a script to a host and returns the `RuntimeScript` instance.\r\n *\r\n * Process:\r\n * 1. Resolve module ID to a runtime URL via the registry.\r\n * 2. Dynamically import the module.\r\n * 3. Instantiate the default export if it is a constructor.\r\n * 4. If this is the first time the instance is seen, call `onCreated()`.\r\n * 5. Link the instance to the host, and call `onAttached(host)`.\r\n * 6. Subscribe to the host's `'dispose'` event to auto-detach.\r\n *\r\n * If the module cannot be resolved or does not export a default `RuntimeScript`\r\n * subclass, a warning is logged and `null` is returned.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - The host object to attach the script to.\r\n * @param module - Module identifier used by the registry (logical ID or path).\r\n * @returns The instantiated `RuntimeScript<T>` or `null` on failure.\r\n */\r\n async attachScript<T extends Host>(host: T, module: string): Promise<RuntimeScript<T>> {\r\n try {\r\n const url = await this._registry.resolveRuntimeUrl(module);\r\n if (!url) {\r\n return null;\r\n }\r\n const mod = await import(url + (this._importComment ?? ''));\r\n let instance: RuntimeScript<T> = null;\r\n if (typeof mod?.default === 'function') {\r\n // default export\r\n instance = new mod.default();\r\n if (instance instanceof RuntimeScript) {\r\n if (!this._scriptHosts.has(instance)) {\r\n const P = instance.onCreated();\r\n if (P instanceof Promise) {\r\n await P;\r\n }\r\n }\r\n } else {\r\n instance = null;\r\n }\r\n }\r\n if (!instance) {\r\n console.warn(`Script '${module}' does not have RuntimeScript class exported as default`);\r\n return null;\r\n }\r\n\r\n let hostList = this._scriptHosts.get(instance);\r\n if (!hostList) {\r\n hostList = [];\r\n this._scriptHosts.set(instance, hostList);\r\n }\r\n if (hostList.includes(host)) {\r\n console.warn(`Script '${module}' already attached`);\r\n return instance;\r\n }\r\n hostList.push(host);\r\n\r\n const P = instance.onAttached(host);\r\n if (P instanceof Promise) {\r\n await P;\r\n }\r\n\r\n const attached: IAttachedScript = {\r\n id: module,\r\n url,\r\n instance\r\n };\r\n\r\n let list = this._hostScripts.get(host);\r\n if (!list) {\r\n list = [];\r\n this._hostScripts.set(host, list);\r\n if (host) {\r\n host.on('dispose', () => {\r\n this.detachScript(host);\r\n });\r\n }\r\n }\r\n list.push(attached);\r\n\r\n return attached.instance;\r\n } catch (e) {\r\n const moduleName = module ? String(module).slice(0, 64) : '';\r\n console.error(`Load module '${moduleName}' failed: ${e}`);\r\n this._onLoadError?.(e, module);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Detaches script(s) from a host.\r\n *\r\n * Behavior:\r\n * - If `idOrInstance` is omitted, detaches all scripts from the host.\r\n * - If a module ID is provided, detaches only the matching script.\r\n * - If a `RuntimeScript` instance is provided, detaches that instance.\r\n * - Invokes `onDetached(host)` on each detached instance.\r\n * - If the instance has no remaining hosts, invokes `onDestroy()` and disposes tracking.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - The host to detach from.\r\n * @param idOrInstance - Optional module ID or script instance to target.\r\n */\r\n detachScript<T extends Host>(host: T, idOrInstance?: string | RuntimeScript<T>) {\r\n const list = this._hostScripts.get(host);\r\n if (!list || list.length === 0) {\r\n return;\r\n }\r\n for (let i = list.length - 1; i >= 0; i--) {\r\n const it = list[i];\r\n const hit =\r\n !idOrInstance || typeof idOrInstance === 'string'\r\n ? it.id === idOrInstance\r\n : it.instance === idOrInstance;\r\n if (hit) {\r\n list.splice(i, 1);\r\n try {\r\n it.instance.onDetached(host);\r\n } catch (err) {\r\n console.error(`Error occured at onDetach() of module '${it.id}': ${err}`);\r\n }\r\n\r\n const hostList = this._scriptHosts.get(it.instance);\r\n const index = hostList.indexOf(host);\r\n if (index >= 0) {\r\n hostList.splice(index, 1);\r\n }\r\n\r\n if (hostList.length === 0) {\r\n try {\r\n it.instance.onDestroy();\r\n } catch (err) {\r\n console.error(`Error occured at onDestroy() of module '${it.id}': ${err}`);\r\n } finally {\r\n this._scriptHosts.delete(it.instance);\r\n }\r\n }\r\n }\r\n }\r\n if (list.length === 0) {\r\n this._hostScripts.delete(host);\r\n }\r\n }\r\n\r\n /**\r\n * Get all script instances attached to a host.\r\n *\r\n * @typeParam T - Expected script type.\r\n * @param host - The host whose scripts to retrieve.\r\n * @returns Script instances attached to the host, or an empty array if none.\r\n */\r\n getScriptObjects<T extends RuntimeScript<any>>(host: unknown): T[] {\r\n return (this._hostScripts.get(host as Host) as unknown as T[]) || [];\r\n }\r\n\r\n /**\r\n * Ticks all attached script instances.\r\n *\r\n * Calls `onUpdate(deltaTime, elapsedTime)` on every attached script instance\r\n * across all hosts. Exceptions thrown by a script are caught and logged,\r\n * allowing other scripts to continue updating.\r\n *\r\n * @param deltaTime - Time in seconds since last update.\r\n * @param elapsedTime - Total time in seconds since start.\r\n */\r\n update(deltaTime: number, elapsedTime: number): void {\r\n if (this._hostScripts.size === 0) {\r\n return;\r\n }\r\n for (const list of this._hostScripts.values()) {\r\n for (const s of list) {\r\n try {\r\n s.instance.onUpdate(deltaTime, elapsedTime);\r\n } catch (err) {\r\n console.error(`Error occured at onUpdate() of module '${s.id}': ${err}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Detaches all scripts from all hosts.\r\n *\r\n * Iteratively calls {@link ScriptingSystem.detachScript} on each host until no attachments remain.\r\n */\r\n detachAllScripts() {\r\n while (this._hostScripts.size > 0) {\r\n for (const entry of this._hostScripts) {\r\n this.detachScript(entry[0]);\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["ScriptingSystem","_registry","_hostScripts","_scriptHosts","_onLoadError","_importComment","opts","ScriptRegistry","VFS","HttpFS","scriptsRoot","editorMode","Map","importComment","onLoadError","registry","attachScript","host","module","url","resolveRuntimeUrl","mod","instance","default","RuntimeScript","has","P","onCreated","Promise","console","warn","hostList","get","set","includes","push","onAttached","attached","id","list","on","detachScript","e","moduleName","String","slice","error","idOrInstance","length","i","it","hit","splice","onDetached","err","index","indexOf","onDestroy","delete","getScriptObjects","update","deltaTime","elapsedTime","size","values","s","onUpdate","detachAllScripts","entry"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scriptingsystem.js","sources":["../../src/app/scriptingsystem.ts"],"sourcesContent":["import type { IDisposable, Nullable, VFS } from '@zephyr3d/base';\r\nimport { HttpFS } from '@zephyr3d/base';\r\nimport { ScriptRegistry } from './scriptregistry';\r\nimport { RuntimeScript } from './runtimescript';\r\n\r\n/**\r\n * A host object that supports disposal.\r\n *\r\n * Hosts are objects to which scripts can be attached. They are expected to\r\n * emit a `'dispose'` event compatible with `IDisposable` so that scripts\r\n * can be automatically detached when the host is destroyed.\r\n *\r\n * @public\r\n */\r\nexport type Host = IDisposable;\r\n\r\n/**\r\n * Options for configuring a `ScriptingSystem`.\r\n *\r\n * @public\r\n */\r\nexport type ScriptingSystemOptions = {\r\n /** Virtual file system used by the script registry. Defaults to `new HttpFS('./')`. */\r\n VFS?: VFS;\r\n /** Root path for scripts within the VFS. Defaults to `/`. */\r\n scriptsRoot?: string;\r\n /**\r\n * Optional string appended to dynamic import URLs (e.g., for cache busting).\r\n * Example: `'?v=' + Date.now()`\r\n */\r\n importComment?: string;\r\n /**\r\n * Optional callback invoked when a module fails to load.\r\n * @param e - The error that occurred.\r\n * @param id - The module ID that failed to load.\r\n */\r\n onLoadError?: (e: unknown, id: string) => void;\r\n};\r\n\r\n/**\r\n * Information about a script attached to a host.\r\n *\r\n * @public\r\n */\r\nexport interface IAttachedScript {\r\n /** The logical module identifier used to resolve the script. */\r\n id: string;\r\n /** The resolved runtime URL used for dynamic import. */\r\n url: string;\r\n /** The instantiated runtime script. */\r\n instance: RuntimeScript<any>;\r\n}\r\n\r\n/**\r\n * Script system that resolves, loads, and manages lifecycle of runtime scripts.\r\n *\r\n * Responsibilities:\r\n * - Resolves module IDs to URLs via {@link ScriptRegistry}\r\n * - Dynamically imports modules and instantiates a `RuntimeScript` (default export)\r\n * - Tracks attachments between hosts and script instances\r\n * - Bridges script lifecycle hooks: `onCreated`, `onAttached`, `onDetached`, `onDestroy`, `onUpdate`\r\n * - Auto-detaches scripts when a host is disposed\r\n *\r\n * Notes:\r\n * - Multiple hosts can reference the same `RuntimeScript` instance; destruction\r\n * occurs when the last host detaches.\r\n * - Errors during load/attach/update are caught and logged; an optional\r\n * `onLoadError` callback can be provided.\r\n *\r\n * @public\r\n */\r\nexport class ScriptingSystem {\r\n private _registry: ScriptRegistry;\r\n private _hostScripts: Map<Nullable<Host>, IAttachedScript[]>;\r\n private _scriptHosts: Map<RuntimeScript<any>, Nullable<Host>[]>;\r\n private _onLoadError?: (e: unknown, id: string) => void;\r\n private _importComment?: string;\r\n\r\n /**\r\n * Constructs a new scripting system.\r\n *\r\n * @param opts - Optional configuration.\r\n */\r\n constructor(opts: ScriptingSystemOptions = {}) {\r\n this._registry = new ScriptRegistry(opts.VFS ?? new HttpFS('./'), opts.scriptsRoot ?? '/');\r\n this._hostScripts = new Map();\r\n this._scriptHosts = new Map();\r\n this._importComment = opts.importComment;\r\n this._onLoadError = opts.onLoadError;\r\n }\r\n\r\n /**\r\n * Accessor for the underlying script registry used for module resolution.\r\n */\r\n get registry() {\r\n return this._registry;\r\n }\r\n\r\n /**\r\n * Attaches a script to a host and returns the `RuntimeScript` instance.\r\n *\r\n * Process:\r\n * 1. Resolve module ID to a runtime URL via the registry.\r\n * 2. Dynamically import the module.\r\n * 3. Instantiate the default export if it is a constructor.\r\n * 4. If this is the first time the instance is seen, call `onCreated()`.\r\n * 5. Link the instance to the host, and call `onAttached(host)`.\r\n * 6. Subscribe to the host's `'dispose'` event to auto-detach.\r\n *\r\n * If the module cannot be resolved or does not export a default `RuntimeScript`\r\n * subclass, a warning is logged and `null` is returned.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - The host object to attach the script to.\r\n * @param module - Module identifier used by the registry (logical ID or path).\r\n * @returns The instantiated `RuntimeScript<T>` or `null` on failure.\r\n */\r\n async attachScript<T extends Host>(host: Nullable<T>, module: string): Promise<Nullable<RuntimeScript<T>>> {\r\n try {\r\n const url = await this._registry.resolveRuntimeUrl(module);\r\n if (!url) {\r\n return null;\r\n }\r\n const mod = await import(url + (this._importComment ?? ''));\r\n let instance: Nullable<RuntimeScript<T>> = null;\r\n if (typeof mod?.default === 'function') {\r\n // default export\r\n instance = new mod.default();\r\n if (instance instanceof RuntimeScript) {\r\n if (!this._scriptHosts.has(instance)) {\r\n const P = instance.onCreated();\r\n if (P instanceof Promise) {\r\n await P;\r\n }\r\n }\r\n } else {\r\n instance = null;\r\n }\r\n }\r\n if (!instance) {\r\n console.warn(`Script '${module}' does not have RuntimeScript class exported as default`);\r\n return null;\r\n }\r\n\r\n let hostList = this._scriptHosts.get(instance);\r\n if (!hostList) {\r\n hostList = [];\r\n this._scriptHosts.set(instance, hostList);\r\n }\r\n if (hostList.includes(host)) {\r\n console.warn(`Script '${module}' already attached`);\r\n return instance;\r\n }\r\n hostList.push(host);\r\n\r\n const P = instance.onAttached(host);\r\n if (P instanceof Promise) {\r\n await P;\r\n }\r\n\r\n const attached: IAttachedScript = {\r\n id: module,\r\n url,\r\n instance\r\n };\r\n\r\n let list = this._hostScripts.get(host);\r\n if (!list) {\r\n list = [];\r\n this._hostScripts.set(host, list);\r\n if (host) {\r\n host.on('dispose', () => {\r\n this.detachScript(host);\r\n });\r\n }\r\n }\r\n list.push(attached);\r\n\r\n return attached.instance;\r\n } catch (e) {\r\n const moduleName = module ? String(module).slice(0, 64) : '';\r\n console.error(`Load module '${moduleName}' failed: ${e}`);\r\n this._onLoadError?.(e, module);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Detaches script(s) from a host.\r\n *\r\n * Behavior:\r\n * - If `idOrInstance` is omitted, detaches all scripts from the host.\r\n * - If a module ID is provided, detaches only the matching script.\r\n * - If a `RuntimeScript` instance is provided, detaches that instance.\r\n * - Invokes `onDetached(host)` on each detached instance.\r\n * - If the instance has no remaining hosts, invokes `onDestroy()` and disposes tracking.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - The host to detach from.\r\n * @param idOrInstance - Optional module ID or script instance to target.\r\n */\r\n detachScript<T extends Host>(host: T, idOrInstance?: string | RuntimeScript<T>) {\r\n const list = this._hostScripts.get(host);\r\n if (!list || list.length === 0) {\r\n return;\r\n }\r\n for (let i = list.length - 1; i >= 0; i--) {\r\n const it = list[i];\r\n const hit =\r\n !idOrInstance || typeof idOrInstance === 'string'\r\n ? it.id === idOrInstance\r\n : it.instance === idOrInstance;\r\n if (hit) {\r\n list.splice(i, 1);\r\n try {\r\n it.instance.onDetached(host);\r\n } catch (err) {\r\n console.error(`Error occured at onDetach() of module '${it.id}': ${err}`);\r\n }\r\n\r\n const hostList = this._scriptHosts.get(it.instance);\r\n if (hostList) {\r\n const index = hostList.indexOf(host);\r\n if (index >= 0) {\r\n hostList.splice(index, 1);\r\n }\r\n }\r\n if (!hostList || hostList.length === 0) {\r\n try {\r\n it.instance.onDestroy();\r\n } catch (err) {\r\n console.error(`Error occured at onDestroy() of module '${it.id}': ${err}`);\r\n } finally {\r\n this._scriptHosts.delete(it.instance);\r\n }\r\n }\r\n }\r\n }\r\n if (list.length === 0) {\r\n this._hostScripts.delete(host);\r\n }\r\n }\r\n\r\n /**\r\n * Get all script instances attached to a host.\r\n *\r\n * @typeParam T - Expected script type.\r\n * @param host - The host whose scripts to retrieve.\r\n * @returns Script instances attached to the host, or an empty array if none.\r\n */\r\n getScriptObjects<T extends RuntimeScript<any>>(host: unknown): T[] {\r\n return (this._hostScripts.get(host as Host) as unknown as T[]) || [];\r\n }\r\n\r\n /**\r\n * Ticks all attached script instances.\r\n *\r\n * Calls `onUpdate(deltaTime, elapsedTime)` on every attached script instance\r\n * across all hosts. Exceptions thrown by a script are caught and logged,\r\n * allowing other scripts to continue updating.\r\n *\r\n * @param deltaTime - Time in seconds since last update.\r\n * @param elapsedTime - Total time in seconds since start.\r\n */\r\n update(deltaTime: number, elapsedTime: number) {\r\n if (this._hostScripts.size === 0) {\r\n return;\r\n }\r\n for (const list of this._hostScripts.values()) {\r\n for (const s of list) {\r\n try {\r\n s.instance.onUpdate(deltaTime, elapsedTime);\r\n } catch (err) {\r\n console.error(`Error occured at onUpdate() of module '${s.id}': ${err}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Detaches all scripts from all hosts.\r\n *\r\n * Iteratively calls {@link ScriptingSystem.detachScript} on each host until no attachments remain.\r\n */\r\n detachAllScripts() {\r\n while (this._hostScripts.size > 0) {\r\n for (const entry of this._hostScripts) {\r\n if (entry[0]) {\r\n this.detachScript(entry[0]);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["ScriptingSystem","_registry","_hostScripts","_scriptHosts","_onLoadError","_importComment","opts","ScriptRegistry","VFS","HttpFS","scriptsRoot","Map","importComment","onLoadError","registry","attachScript","host","module","url","resolveRuntimeUrl","mod","instance","default","RuntimeScript","has","P","onCreated","Promise","console","warn","hostList","get","set","includes","push","onAttached","attached","id","list","on","detachScript","e","moduleName","String","slice","error","idOrInstance","length","i","it","hit","splice","onDetached","err","index","indexOf","onDestroy","delete","getScriptObjects","update","deltaTime","elapsedTime","size","values","s","onUpdate","detachAllScripts","entry"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { textToBase64 } from '@zephyr3d/base';
|
|
2
2
|
import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
3
|
+
import { getApp } from './api.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Converts JavaScript source to a data URL tied to a logical module id.
|
|
@@ -50,16 +51,15 @@ import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
|
50
51
|
*/ class ScriptRegistry {
|
|
51
52
|
_vfs;
|
|
52
53
|
_scriptsRoot;
|
|
53
|
-
_built
|
|
54
|
-
_editorMode = false;
|
|
54
|
+
_built;
|
|
55
55
|
/**
|
|
56
56
|
* @param vfs - The virtual file system for existence checks, reads, and path ops.
|
|
57
57
|
* @param scriptsRoot - Root directory for script resolution (used with `#/` specifiers).
|
|
58
58
|
* @param editorMode - Whether to build modules to data URLs and rewrite imports.
|
|
59
|
-
*/ constructor(vfs, scriptsRoot
|
|
59
|
+
*/ constructor(vfs, scriptsRoot){
|
|
60
60
|
this._vfs = vfs;
|
|
61
61
|
this._scriptsRoot = scriptsRoot;
|
|
62
|
-
this.
|
|
62
|
+
this._built = new Map();
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* The active virtual file system.
|
|
@@ -75,14 +75,6 @@ import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* Whether the registry operates in editor mode (rewrite/build to data URLs).
|
|
79
|
-
*/ get editorMode() {
|
|
80
|
-
return this._editorMode;
|
|
81
|
-
}
|
|
82
|
-
set editorMode(val) {
|
|
83
|
-
this._editorMode = val;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
78
|
* The root path used by `#/` specifiers.
|
|
87
79
|
*/ get scriptsRoot() {
|
|
88
80
|
return this._scriptsRoot;
|
|
@@ -161,7 +153,7 @@ import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
|
161
153
|
* @returns A URL string that can be used in `import(...)`.
|
|
162
154
|
*/ async resolveRuntimeUrl(entryId) {
|
|
163
155
|
const id = await this.resolveLogicalId(entryId);
|
|
164
|
-
return
|
|
156
|
+
return getApp().editorMode !== 'none' ? await this.build(String(id)) : id.endsWith('.js') ? id : id.endsWith('.ts') ? `${id.slice(0, -3)}.js` : `${id}.js`;
|
|
165
157
|
}
|
|
166
158
|
/**
|
|
167
159
|
* Recursively gathers direct static and dynamic import dependencies for a module.
|
|
@@ -346,17 +338,16 @@ import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
|
346
338
|
* @returns A normalized logical id or an external specifier string.
|
|
347
339
|
* @throws If a relative import is provided without `fromId`.
|
|
348
340
|
*/ async resolveLogicalId(spec, fromId) {
|
|
349
|
-
let path;
|
|
350
341
|
if (spec.startsWith('#/')) {
|
|
351
|
-
|
|
342
|
+
return this._vfs.normalizePath(this._vfs.join(this._scriptsRoot, spec.slice(2)));
|
|
352
343
|
} else if (spec.startsWith('./') || spec.startsWith('../')) {
|
|
353
344
|
if (!fromId) {
|
|
354
345
|
throw new Error(`Relative import "${spec}" requires fromId`);
|
|
355
346
|
}
|
|
356
|
-
|
|
347
|
+
return this._vfs.normalizePath(this._vfs.join(this._vfs.dirname(this._vfs.normalizePath(fromId)), spec));
|
|
357
348
|
} else if (spec.startsWith('/')) {
|
|
358
|
-
|
|
359
|
-
} else if (
|
|
349
|
+
return spec.replace(/^\/+/, '/');
|
|
350
|
+
} else if (getApp().editorMode !== 'none') {
|
|
360
351
|
// naked module, checking if it is a installed module in editor mode
|
|
361
352
|
const depsExists = await this._vfs.exists('/libs/deps.lock.json');
|
|
362
353
|
if (depsExists) {
|
|
@@ -365,13 +356,11 @@ import { init, parse } from '../node_modules/es-module-lexer/dist/lexer.js';
|
|
|
365
356
|
});
|
|
366
357
|
const depsInfo = JSON.parse(content);
|
|
367
358
|
if (depsInfo?.dependencies[spec]) {
|
|
368
|
-
|
|
359
|
+
return this._vfs.normalizePath(depsInfo.dependencies[spec].entry);
|
|
369
360
|
}
|
|
370
361
|
}
|
|
371
|
-
} else {
|
|
372
|
-
return spec;
|
|
373
362
|
}
|
|
374
|
-
return
|
|
363
|
+
return spec;
|
|
375
364
|
}
|
|
376
365
|
/**
|
|
377
366
|
* Resolves a logical id to a concrete source path and type by probing extensions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptregistry.js","sources":["../../src/app/scriptregistry.ts"],"sourcesContent":["import type * as TS from 'typescript';\r\nimport type { VFS } from '@zephyr3d/base';\r\nimport { textToBase64 } from '@zephyr3d/base';\r\nimport { init, parse } from 'es-module-lexer';\r\n\r\n/**\r\n * Converts JavaScript source to a data URL tied to a logical module id.\r\n *\r\n * @param js - The JavaScript source code to embed.\r\n * @param id - Logical module identifier (used only for sourceURL tagging).\r\n * @returns A `data:text/javascript;base64,...` URL with an encoded `#id` suffix.\r\n * @internal\r\n */\r\nfunction toDataUrl(js: string, id: string): string {\r\n const b64 = textToBase64(js);\r\n return `data:text/javascript;base64,${b64}#${encodeURIComponent(String(id))}`;\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is an absolute HTTP(S) URL.\r\n * @internal\r\n */\r\nfunction isAbsoluteUrl(spec: string): boolean {\r\n return /^https?:\\/\\//i.test(spec);\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is a special URL (data: or blob:).\r\n * @internal\r\n */\r\nfunction isSpecialUrl(spec: string): boolean {\r\n return /^(data|blob):/i.test(spec);\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is a bare module (not starting with ./, ../, /, or #/).\r\n * @internal\r\n */\r\nfunction isBareModule(spec: string): boolean {\r\n return !spec.startsWith('./') && !spec.startsWith('../') && !spec.startsWith('/') && !spec.startsWith('#/');\r\n}\r\n\r\n/**\r\n * Resolves, builds, and serves runtime modules using a VFS.\r\n *\r\n * Responsibilities:\r\n * - Resolve logical module IDs to physical paths or URLs.\r\n * - In editor mode, rewrite import specifiers and serve modules as data URLs after transpile.\r\n * - Transpile TypeScript to JavaScript on the fly (requires `window.ts` TypeScript runtime).\r\n * - Gather static and dynamic import dependencies for tooling.\r\n *\r\n * Modes:\r\n * - Editor mode (`editorMode === true`): modules are rewritten to data URLs after transpile/build.\r\n * - Runtime mode (`editorMode === false`): returns .js URLs directly (with .ts -\\> .js mapping).\r\n *\r\n * Caching:\r\n * - Built modules are memoized in `_built` map keyed by logical ID.\r\n *\r\n * @public\r\n */\r\nexport class ScriptRegistry {\r\n private _vfs: VFS;\r\n private _scriptsRoot: string;\r\n private _built = new Map<string, string>(); // logicalId -> dataURL\r\n private _editorMode = false;\r\n\r\n /**\r\n * @param vfs - The virtual file system for existence checks, reads, and path ops.\r\n * @param scriptsRoot - Root directory for script resolution (used with `#/` specifiers).\r\n * @param editorMode - Whether to build modules to data URLs and rewrite imports.\r\n */\r\n constructor(vfs: VFS, scriptsRoot: string, editorMode: boolean) {\r\n this._vfs = vfs;\r\n this._scriptsRoot = scriptsRoot;\r\n this._editorMode = editorMode;\r\n }\r\n\r\n /**\r\n * The active virtual file system.\r\n *\r\n * Assigning a new VFS clears the build cache.\r\n */\r\n get VFS() {\r\n return this._vfs;\r\n }\r\n set VFS(vfs: VFS) {\r\n if (vfs !== this._vfs) {\r\n this._vfs = vfs;\r\n this._built.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Whether the registry operates in editor mode (rewrite/build to data URLs).\r\n */\r\n get editorMode() {\r\n return this._editorMode;\r\n }\r\n set editorMode(val: boolean) {\r\n this._editorMode = val;\r\n }\r\n\r\n /**\r\n * The root path used by `#/` specifiers.\r\n */\r\n get scriptsRoot() {\r\n return this._scriptsRoot;\r\n }\r\n set scriptsRoot(path: string) {\r\n this._scriptsRoot = path;\r\n }\r\n\r\n /**\r\n * Fetches raw source for a logical module id by probing known extensions.\r\n *\r\n * Search order:\r\n * - If `id` already ends with `.ts` or `.js` and is a file -\\> return it.\r\n * - Else try `.id.ts`, then `.id.js`.\r\n *\r\n * @param id - Logical module identifier (absolute or logical path-like).\r\n * @returns Source code, resolved path, and type (`'js' | 'ts'`), or `undefined` if not found.\r\n */\r\n protected async fetchSource(\r\n id: string\r\n ): Promise<{ code: string; path: string; type: 'js' | 'ts'; sourceMap?: string } | undefined> {\r\n let type: 'js' | 'ts' = null;\r\n let pathWithExt = '';\r\n if (id.endsWith('.ts')) {\r\n pathWithExt = id;\r\n type = 'ts';\r\n } else if (id.endsWith('.js')) {\r\n pathWithExt = id;\r\n type = 'js';\r\n }\r\n if (type) {\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (!exists) {\r\n type = null;\r\n }\r\n const stat = await this._vfs.stat(pathWithExt);\r\n if (stat.isDirectory) {\r\n type = null;\r\n }\r\n }\r\n const types = ['ts', 'js'] as const;\r\n if (!type) {\r\n for (const t of types) {\r\n pathWithExt = `${id}.${t}`;\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (exists) {\r\n const stats = await this._vfs.stat(pathWithExt);\r\n if (stats.isFile) {\r\n type = t;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n if (type) {\r\n const code = (await this._vfs.readFile(pathWithExt, { encoding: 'utf8' })) as string;\r\n return { code, type, path: pathWithExt };\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a module entry to a URL suitable for dynamic import.\r\n *\r\n * Behavior:\r\n * - In editor mode, builds the module to a data URL.\r\n * - Otherwise, returns `.js` URL directly:\r\n * - If `id` ends with `.js`: return as-is.\r\n * - If `id` ends with `.ts`: map to `.js` (assumes pre-built file exists).\r\n * - Else: append `.js`.\r\n *\r\n * @param entryId - Entry module identifier (logical or path-like).\r\n * @returns A URL string that can be used in `import(...)`.\r\n */\r\n async resolveRuntimeUrl(entryId: string): Promise<string> {\r\n const id = await this.resolveLogicalId(entryId);\r\n return this._editorMode\r\n ? await this.build(String(id))\r\n : id.endsWith('.js')\r\n ? id\r\n : id.endsWith('.ts')\r\n ? `${id.slice(0, -3)}.js`\r\n : `${id}.js`;\r\n }\r\n\r\n /**\r\n * Recursively gathers direct static and dynamic import dependencies for a module.\r\n *\r\n * Only relative specifiers (`./` or `../`) are followed. Absolute, special, and bare\r\n * module specifiers are ignored here.\r\n *\r\n * @param entryId - The starting (possibly relative) specifier from `fromId`.\r\n * @param fromId - The logical id of the module containing `entryId`.\r\n * @param dependencies - Output map of `resolvedSourcePath -\\> file contents`.\r\n */\r\n async getDependencies(\r\n entryId: string,\r\n fromId: string,\r\n dependencies: Record<string, string>\r\n ): Promise<void> {\r\n const reStatic = /\\b(?:import|export)\\s+[^\"']*?from\\s+(['\"])([^'\"]+)\\1/g;\r\n const reDynamic = /\\bimport\\s*\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/g;\r\n\r\n const normalizedId = await this.resolveLogicalId(entryId, fromId);\r\n const srcPath = await this.resolveSourcePath(normalizedId);\r\n if (!srcPath || dependencies[srcPath.path] !== undefined) {\r\n return;\r\n }\r\n const code = (await this._vfs.readFile(srcPath.path, { encoding: 'utf8' })) as string;\r\n dependencies[srcPath.path] = code;\r\n\r\n const gather = async (input: string, re: RegExp) => {\r\n for (;;) {\r\n const m = re.exec(input);\r\n if (!m) {\r\n break;\r\n }\r\n\r\n const spec = m[2];\r\n\r\n if (spec.startsWith('./') || spec.startsWith('../')) {\r\n await this.getDependencies(spec, normalizedId, dependencies);\r\n }\r\n }\r\n };\r\n\r\n await gather(code, reStatic);\r\n await gather(code, reDynamic);\r\n }\r\n\r\n /**\r\n * Builds a logical module id into a data URL (editor mode pipeline).\r\n *\r\n * Steps:\r\n * - Resolve source path (.ts/.js) via {@link ScriptRegistry.resolveSourcePath}.\r\n * - Read source code.\r\n * - Rewrite import specifiers via {@link ScriptRegistry.rewriteImports}.\r\n * - Transpile TypeScript if needed via {@link ScriptRegistry.transpile}.\r\n * - Convert to `data:` URL and memoize in `_built`.\r\n *\r\n * @param id - Logical module id to build.\r\n * @returns Data URL string for dynamic import, or empty string if not found.\r\n */\r\n private async build(id: string): Promise<string> {\r\n const key = String(id);\r\n const cached = this._built.get(key);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const srcPath = await this.resolveSourcePath(key);\r\n if (!srcPath) {\r\n return '';\r\n }\r\n const code = (await this._vfs.readFile(srcPath.path, { encoding: 'utf8' })) as string;\r\n\r\n const rewritten = await this.rewriteImports(code, key);\r\n const js = await this.transpile(rewritten, key, srcPath.type);\r\n const url = toDataUrl(js, key);\r\n this._built.set(key, url);\r\n return url;\r\n }\r\n\r\n /**\r\n * Transpiles code to JavaScript and appends sourceURL/sourceMap hints.\r\n *\r\n * Behavior:\r\n * - For `'js'`, returns code with `//# sourceURL=logicalId`.\r\n * - For `'ts'`, requires `window.ts` (TypeScript compiler) to be present and\r\n * transpiles to ES2015/ESNext module with inline source maps.\r\n *\r\n * @param code - Source code to transpile.\r\n * @param _id - Logical module id (used for fileName/sourceURL).\r\n * @param type - Source type (`'js' | 'ts'`).\r\n * @returns Transpiled JavaScript source.\r\n * @throws If TypeScript runtime is not found for TS input.\r\n */\r\n private async transpile(code: string, _id: string, type: 'js' | 'ts'): Promise<string> {\r\n const logicalId = String(_id);\r\n\r\n if (type === 'js') {\r\n return `${code}\\n//# sourceURL=${logicalId}`;\r\n }\r\n\r\n const ts = (window as any).ts as typeof TS;\r\n if (!ts) {\r\n throw new Error('TypeScript runtime (window.ts) not found. Load typescript.js first.');\r\n }\r\n\r\n const res = ts.transpileModule(code, {\r\n compilerOptions: {\r\n target: ts.ScriptTarget.ES2015,\r\n module: ts.ModuleKind.ESNext,\r\n sourceMap: true,\r\n inlineSources: true,\r\n experimentalDecorators: true,\r\n useDefineForClassFields: false\r\n },\r\n fileName: logicalId\r\n });\r\n\r\n let out = res.outputText || '';\r\n if (res.sourceMapText) {\r\n const mapBase64 = btoa(unescape(encodeURIComponent(res.sourceMapText)));\r\n out += `\\n//# sourceMappingURL=data:application/json;base64,${mapBase64}`;\r\n }\r\n out += `\\n//# sourceURL=${logicalId}`;\r\n return out;\r\n }\r\n\r\n /**\r\n * Rewrites ESM import specifiers in `code` into runtime-loadable URLs.\r\n *\r\n * Parsing:\r\n * - Uses `es-module-lexer` to find import spans; sorts them ascending by start.\r\n *\r\n * Replacement rules:\r\n * - Skip invalid spans or ones without quoted specifiers.\r\n * - If spec is absolute URL, special URL (data:, blob:), or bare module:\r\n * - If it starts with `@zephyr3d/`, keep as-is (external).\r\n * - Otherwise resolve to a logical id and attempt to `build` it (if available).\r\n * - Else (relative spec), resolve from `fromId` and `build` recursively.\r\n *\r\n * Output:\r\n * - Directly writes the replacement specifier without re-adding quotes,\r\n * so replacements must themselves be quoted or be valid URLs/data URLs.\r\n *\r\n * @param code - Module source code to transform.\r\n * @param fromId - The logical id of the current module (resolution base for relatives).\r\n * @returns Transformed source with rewritten import specifiers.\r\n */\r\n private async rewriteImports(code: string, fromId: string): Promise<string> {\r\n await init;\r\n const [imports] = parse(code);\r\n const list = [...imports].sort((a, b) => (a.s || 0) - (b.s || 0));\r\n let out = '';\r\n let last = 0;\r\n\r\n for (const im of list) {\r\n // must have quotes\r\n const hasQuote = im.ss != null && im.se != null;\r\n if (!hasQuote || im.se <= im.ss) {\r\n continue;\r\n }\r\n // must have contents\r\n if (im.e <= im.s) {\r\n continue;\r\n }\r\n // append [last, s)\r\n out += code.slice(last, im.s);\r\n\r\n const spec = code.slice(im.s, im.e); // original spec\r\n let replacement = spec;\r\n if (isAbsoluteUrl(spec) || isSpecialUrl(spec) || isBareModule(spec)) {\r\n if (spec.startsWith('@zephyr3d/')) {\r\n replacement = spec;\r\n } else {\r\n const depId = await this.resolveLogicalId(spec);\r\n replacement = await this.build(depId); // try build as dependence\r\n }\r\n } else {\r\n const depId = await this.resolveLogicalId(spec, String(fromId));\r\n replacement = await this.build(depId); // recursively build as dataURL\r\n }\r\n out += replacement; // 不加引号\r\n last = im.e;\r\n }\r\n out += code.slice(last);\r\n return out;\r\n }\r\n\r\n /**\r\n * Resolves a specifier to a logical id suitable for further processing.\r\n *\r\n * Resolution rules:\r\n * - `#/path`: resolved against `scriptsRoot` via VFS join/normalize.\r\n * - `./` or `../`: resolved relative to `fromId` directory (requires `fromId`).\r\n * - `/absolute`: treated as absolute from root (normalized).\r\n * - Bare module in editor mode: if `/deps.lock.json` exists and contains an entry,\r\n * map to the dependency's `entry` path; otherwise return as-is.\r\n * - Else (non-editor bare module): return `spec` unchanged (external).\r\n *\r\n * @param spec - Import specifier string.\r\n * @param fromId - Optional base logical id used for relative resolution.\r\n * @returns A normalized logical id or an external specifier string.\r\n * @throws If a relative import is provided without `fromId`.\r\n */\r\n async resolveLogicalId(spec: string, fromId?: string): Promise<string> {\r\n let path: string;\r\n\r\n if (spec.startsWith('#/')) {\r\n path = this._vfs.normalizePath(this._vfs.join(this._scriptsRoot, spec.slice(2)));\r\n } else if (spec.startsWith('./') || spec.startsWith('../')) {\r\n if (!fromId) {\r\n throw new Error(`Relative import \"${spec}\" requires fromId`);\r\n }\r\n path = this._vfs.normalizePath(\r\n this._vfs.join(this._vfs.dirname(this._vfs.normalizePath(fromId)), spec)\r\n );\r\n } else if (spec.startsWith('/')) {\r\n path = spec.replace(/^\\/+/, '/');\r\n } else if (this._editorMode) {\r\n // naked module, checking if it is a installed module in editor mode\r\n const depsExists = await this._vfs.exists('/libs/deps.lock.json');\r\n if (depsExists) {\r\n const content = (await this._vfs.readFile('/libs/deps.lock.json', { encoding: 'utf8' })) as string;\r\n const depsInfo = JSON.parse(content) as { dependencies: Record<string, { entry: string }> };\r\n if (depsInfo?.dependencies[spec]) {\r\n path = this._vfs.normalizePath(depsInfo.dependencies[spec].entry);\r\n }\r\n }\r\n } else {\r\n return spec;\r\n }\r\n return path;\r\n }\r\n\r\n /**\r\n * Resolves a logical id to a concrete source path and type by probing extensions.\r\n *\r\n * Rules:\r\n * - If `logicalId` ends with `.ts` or `.js`/`.mjs` and is a file, return it.\r\n * - Else probe `logicalId.ts`, `logicalId.js`, `logicalId.mjs` in that order.\r\n * - Maps `.mjs` to type `'js'`.\r\n *\r\n * @param logicalId - The normalized logical module id (path-like).\r\n * @returns `{ type, path }` or `null` if not found.\r\n */\r\n async resolveSourcePath(logicalId: string) {\r\n let type: 'js' | 'ts' = null;\r\n let pathWithExt = '';\r\n if (logicalId.endsWith('.ts')) {\r\n pathWithExt = logicalId;\r\n type = 'ts';\r\n } else if (logicalId.endsWith('.js') || logicalId.endsWith('.mjs')) {\r\n pathWithExt = logicalId;\r\n type = 'js';\r\n }\r\n if (type) {\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (!exists) {\r\n type = null;\r\n }\r\n const stat = await this._vfs.stat(pathWithExt);\r\n if (stat.isDirectory) {\r\n type = null;\r\n }\r\n }\r\n const types = ['ts', 'js', 'mjs'] as const;\r\n if (!type) {\r\n for (const t of types) {\r\n pathWithExt = `${logicalId}.${t}`;\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (exists) {\r\n const stats = await this._vfs.stat(pathWithExt);\r\n if (stats.isFile) {\r\n type = t === 'ts' ? 'ts' : 'js';\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n return type ? { type, path: pathWithExt } : null;\r\n }\r\n}\r\n"],"names":["toDataUrl","js","id","b64","textToBase64","encodeURIComponent","String","isAbsoluteUrl","spec","test","isSpecialUrl","isBareModule","startsWith","ScriptRegistry","_vfs","_scriptsRoot","_built","Map","_editorMode","vfs","scriptsRoot","editorMode","VFS","clear","val","path","fetchSource","type","pathWithExt","endsWith","exists","stat","isDirectory","types","t","stats","isFile","code","readFile","encoding","resolveRuntimeUrl","entryId","resolveLogicalId","build","slice","getDependencies","fromId","dependencies","reStatic","reDynamic","normalizedId","srcPath","resolveSourcePath","undefined","gather","input","re","m","exec","key","cached","get","rewritten","rewriteImports","transpile","url","set","_id","logicalId","ts","window","Error","res","transpileModule","compilerOptions","target","ScriptTarget","ES2015","module","ModuleKind","ESNext","sourceMap","inlineSources","experimentalDecorators","useDefineForClassFields","fileName","out","outputText","sourceMapText","mapBase64","btoa","unescape","init","imports","parse","list","sort","a","b","s","last","im","hasQuote","ss","se","e","replacement","depId","normalizePath","join","dirname","replace","depsExists","content","depsInfo","JSON","entry"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scriptregistry.js","sources":["../../src/app/scriptregistry.ts"],"sourcesContent":["import type * as TS from 'typescript';\r\nimport type { Nullable, VFS } from '@zephyr3d/base';\r\nimport { textToBase64 } from '@zephyr3d/base';\r\nimport { init, parse } from 'es-module-lexer';\r\nimport { getApp } from './api';\r\n\r\n/**\r\n * Converts JavaScript source to a data URL tied to a logical module id.\r\n *\r\n * @param js - The JavaScript source code to embed.\r\n * @param id - Logical module identifier (used only for sourceURL tagging).\r\n * @returns A `data:text/javascript;base64,...` URL with an encoded `#id` suffix.\r\n * @internal\r\n */\r\nfunction toDataUrl(js: string, id: string) {\r\n const b64 = textToBase64(js);\r\n return `data:text/javascript;base64,${b64}#${encodeURIComponent(String(id))}`;\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is an absolute HTTP(S) URL.\r\n * @internal\r\n */\r\nfunction isAbsoluteUrl(spec: string) {\r\n return /^https?:\\/\\//i.test(spec);\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is a special URL (data: or blob:).\r\n * @internal\r\n */\r\nfunction isSpecialUrl(spec: string) {\r\n return /^(data|blob):/i.test(spec);\r\n}\r\n\r\n/**\r\n * Checks whether a specifier is a bare module (not starting with ./, ../, /, or #/).\r\n * @internal\r\n */\r\nfunction isBareModule(spec: string) {\r\n return !spec.startsWith('./') && !spec.startsWith('../') && !spec.startsWith('/') && !spec.startsWith('#/');\r\n}\r\n\r\n/**\r\n * Resolves, builds, and serves runtime modules using a VFS.\r\n *\r\n * Responsibilities:\r\n * - Resolve logical module IDs to physical paths or URLs.\r\n * - In editor mode, rewrite import specifiers and serve modules as data URLs after transpile.\r\n * - Transpile TypeScript to JavaScript on the fly (requires `window.ts` TypeScript runtime).\r\n * - Gather static and dynamic import dependencies for tooling.\r\n *\r\n * Modes:\r\n * - Editor mode (`editorMode === true`): modules are rewritten to data URLs after transpile/build.\r\n * - Runtime mode (`editorMode === false`): returns .js URLs directly (with .ts -\\> .js mapping).\r\n *\r\n * Caching:\r\n * - Built modules are memoized in `_built` map keyed by logical ID.\r\n *\r\n * @public\r\n */\r\nexport class ScriptRegistry {\r\n private _vfs: VFS;\r\n private _scriptsRoot: string;\r\n private _built: Map<string, string>; // logicalId -> dataURL\r\n\r\n /**\r\n * @param vfs - The virtual file system for existence checks, reads, and path ops.\r\n * @param scriptsRoot - Root directory for script resolution (used with `#/` specifiers).\r\n * @param editorMode - Whether to build modules to data URLs and rewrite imports.\r\n */\r\n constructor(vfs: VFS, scriptsRoot: string) {\r\n this._vfs = vfs;\r\n this._scriptsRoot = scriptsRoot;\r\n this._built = new Map();\r\n }\r\n\r\n /**\r\n * The active virtual file system.\r\n *\r\n * Assigning a new VFS clears the build cache.\r\n */\r\n get VFS() {\r\n return this._vfs;\r\n }\r\n set VFS(vfs: VFS) {\r\n if (vfs !== this._vfs) {\r\n this._vfs = vfs;\r\n this._built.clear();\r\n }\r\n }\r\n\r\n /**\r\n * The root path used by `#/` specifiers.\r\n */\r\n get scriptsRoot() {\r\n return this._scriptsRoot;\r\n }\r\n set scriptsRoot(path: string) {\r\n this._scriptsRoot = path;\r\n }\r\n\r\n /**\r\n * Fetches raw source for a logical module id by probing known extensions.\r\n *\r\n * Search order:\r\n * - If `id` already ends with `.ts` or `.js` and is a file -\\> return it.\r\n * - Else try `.id.ts`, then `.id.js`.\r\n *\r\n * @param id - Logical module identifier (absolute or logical path-like).\r\n * @returns Source code, resolved path, and type (`'js' | 'ts'`), or `undefined` if not found.\r\n */\r\n protected async fetchSource(id: string) {\r\n let type: Nullable<'js' | 'ts'> = null;\r\n let pathWithExt = '';\r\n if (id.endsWith('.ts')) {\r\n pathWithExt = id;\r\n type = 'ts';\r\n } else if (id.endsWith('.js')) {\r\n pathWithExt = id;\r\n type = 'js';\r\n }\r\n if (type) {\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (!exists) {\r\n type = null;\r\n }\r\n const stat = await this._vfs.stat(pathWithExt);\r\n if (stat.isDirectory) {\r\n type = null;\r\n }\r\n }\r\n const types = ['ts', 'js'] as const;\r\n if (!type) {\r\n for (const t of types) {\r\n pathWithExt = `${id}.${t}`;\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (exists) {\r\n const stats = await this._vfs.stat(pathWithExt);\r\n if (stats.isFile) {\r\n type = t;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n if (type) {\r\n const code = (await this._vfs.readFile(pathWithExt, { encoding: 'utf8' })) as string;\r\n return { code, type, path: pathWithExt };\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a module entry to a URL suitable for dynamic import.\r\n *\r\n * Behavior:\r\n * - In editor mode, builds the module to a data URL.\r\n * - Otherwise, returns `.js` URL directly:\r\n * - If `id` ends with `.js`: return as-is.\r\n * - If `id` ends with `.ts`: map to `.js` (assumes pre-built file exists).\r\n * - Else: append `.js`.\r\n *\r\n * @param entryId - Entry module identifier (logical or path-like).\r\n * @returns A URL string that can be used in `import(...)`.\r\n */\r\n async resolveRuntimeUrl(entryId: string) {\r\n const id = await this.resolveLogicalId(entryId);\r\n return getApp().editorMode !== 'none'\r\n ? await this.build(String(id))\r\n : id.endsWith('.js')\r\n ? id\r\n : id.endsWith('.ts')\r\n ? `${id.slice(0, -3)}.js`\r\n : `${id}.js`;\r\n }\r\n\r\n /**\r\n * Recursively gathers direct static and dynamic import dependencies for a module.\r\n *\r\n * Only relative specifiers (`./` or `../`) are followed. Absolute, special, and bare\r\n * module specifiers are ignored here.\r\n *\r\n * @param entryId - The starting (possibly relative) specifier from `fromId`.\r\n * @param fromId - The logical id of the module containing `entryId`.\r\n * @param dependencies - Output map of `resolvedSourcePath -\\> file contents`.\r\n */\r\n async getDependencies(entryId: string, fromId: string, dependencies: Record<string, string>) {\r\n const reStatic = /\\b(?:import|export)\\s+[^\"']*?from\\s+(['\"])([^'\"]+)\\1/g;\r\n const reDynamic = /\\bimport\\s*\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/g;\r\n\r\n const normalizedId = await this.resolveLogicalId(entryId, fromId);\r\n const srcPath = await this.resolveSourcePath(normalizedId);\r\n if (!srcPath || dependencies[srcPath.path] !== undefined) {\r\n return;\r\n }\r\n const code = (await this._vfs.readFile(srcPath.path, { encoding: 'utf8' })) as string;\r\n dependencies[srcPath.path] = code;\r\n\r\n const gather = async (input: string, re: RegExp) => {\r\n for (;;) {\r\n const m = re.exec(input);\r\n if (!m) {\r\n break;\r\n }\r\n\r\n const spec = m[2];\r\n\r\n if (spec.startsWith('./') || spec.startsWith('../')) {\r\n await this.getDependencies(spec, normalizedId, dependencies);\r\n }\r\n }\r\n };\r\n\r\n await gather(code, reStatic);\r\n await gather(code, reDynamic);\r\n }\r\n\r\n /**\r\n * Builds a logical module id into a data URL (editor mode pipeline).\r\n *\r\n * Steps:\r\n * - Resolve source path (.ts/.js) via {@link ScriptRegistry.resolveSourcePath}.\r\n * - Read source code.\r\n * - Rewrite import specifiers via {@link ScriptRegistry.rewriteImports}.\r\n * - Transpile TypeScript if needed via {@link ScriptRegistry.transpile}.\r\n * - Convert to `data:` URL and memoize in `_built`.\r\n *\r\n * @param id - Logical module id to build.\r\n * @returns Data URL string for dynamic import, or empty string if not found.\r\n */\r\n private async build(id: string) {\r\n const key = String(id);\r\n const cached = this._built.get(key);\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const srcPath = await this.resolveSourcePath(key);\r\n if (!srcPath) {\r\n return '';\r\n }\r\n const code = (await this._vfs.readFile(srcPath.path, { encoding: 'utf8' })) as string;\r\n\r\n const rewritten = await this.rewriteImports(code, key);\r\n const js = await this.transpile(rewritten, key, srcPath.type);\r\n const url = toDataUrl(js, key);\r\n this._built.set(key, url);\r\n return url;\r\n }\r\n\r\n /**\r\n * Transpiles code to JavaScript and appends sourceURL/sourceMap hints.\r\n *\r\n * Behavior:\r\n * - For `'js'`, returns code with `//# sourceURL=logicalId`.\r\n * - For `'ts'`, requires `window.ts` (TypeScript compiler) to be present and\r\n * transpiles to ES2015/ESNext module with inline source maps.\r\n *\r\n * @param code - Source code to transpile.\r\n * @param _id - Logical module id (used for fileName/sourceURL).\r\n * @param type - Source type (`'js' | 'ts'`).\r\n * @returns Transpiled JavaScript source.\r\n * @throws If TypeScript runtime is not found for TS input.\r\n */\r\n private async transpile(code: string, _id: string, type: 'js' | 'ts') {\r\n const logicalId = String(_id);\r\n\r\n if (type === 'js') {\r\n return `${code}\\n//# sourceURL=${logicalId}`;\r\n }\r\n\r\n const ts = (window as any).ts as typeof TS;\r\n if (!ts) {\r\n throw new Error('TypeScript runtime (window.ts) not found. Load typescript.js first.');\r\n }\r\n\r\n const res = ts.transpileModule(code, {\r\n compilerOptions: {\r\n target: ts.ScriptTarget.ES2015,\r\n module: ts.ModuleKind.ESNext,\r\n sourceMap: true,\r\n inlineSources: true,\r\n experimentalDecorators: true,\r\n useDefineForClassFields: false\r\n },\r\n fileName: logicalId\r\n });\r\n\r\n let out = res.outputText || '';\r\n if (res.sourceMapText) {\r\n const mapBase64 = btoa(unescape(encodeURIComponent(res.sourceMapText)));\r\n out += `\\n//# sourceMappingURL=data:application/json;base64,${mapBase64}`;\r\n }\r\n out += `\\n//# sourceURL=${logicalId}`;\r\n return out;\r\n }\r\n\r\n /**\r\n * Rewrites ESM import specifiers in `code` into runtime-loadable URLs.\r\n *\r\n * Parsing:\r\n * - Uses `es-module-lexer` to find import spans; sorts them ascending by start.\r\n *\r\n * Replacement rules:\r\n * - Skip invalid spans or ones without quoted specifiers.\r\n * - If spec is absolute URL, special URL (data:, blob:), or bare module:\r\n * - If it starts with `@zephyr3d/`, keep as-is (external).\r\n * - Otherwise resolve to a logical id and attempt to `build` it (if available).\r\n * - Else (relative spec), resolve from `fromId` and `build` recursively.\r\n *\r\n * Output:\r\n * - Directly writes the replacement specifier without re-adding quotes,\r\n * so replacements must themselves be quoted or be valid URLs/data URLs.\r\n *\r\n * @param code - Module source code to transform.\r\n * @param fromId - The logical id of the current module (resolution base for relatives).\r\n * @returns Transformed source with rewritten import specifiers.\r\n */\r\n private async rewriteImports(code: string, fromId: string) {\r\n await init;\r\n const [imports] = parse(code);\r\n const list = [...imports].sort((a, b) => (a.s || 0) - (b.s || 0));\r\n let out = '';\r\n let last = 0;\r\n\r\n for (const im of list) {\r\n // must have quotes\r\n const hasQuote = im.ss != null && im.se != null;\r\n if (!hasQuote || im.se <= im.ss) {\r\n continue;\r\n }\r\n // must have contents\r\n if (im.e <= im.s) {\r\n continue;\r\n }\r\n // append [last, s)\r\n out += code.slice(last, im.s);\r\n\r\n const spec = code.slice(im.s, im.e); // original spec\r\n let replacement = spec;\r\n if (isAbsoluteUrl(spec) || isSpecialUrl(spec) || isBareModule(spec)) {\r\n if (spec.startsWith('@zephyr3d/')) {\r\n replacement = spec;\r\n } else {\r\n const depId = await this.resolveLogicalId(spec);\r\n replacement = await this.build(depId); // try build as dependence\r\n }\r\n } else {\r\n const depId = await this.resolveLogicalId(spec, String(fromId));\r\n replacement = await this.build(depId); // recursively build as dataURL\r\n }\r\n out += replacement; // 不加引号\r\n last = im.e;\r\n }\r\n out += code.slice(last);\r\n return out;\r\n }\r\n\r\n /**\r\n * Resolves a specifier to a logical id suitable for further processing.\r\n *\r\n * Resolution rules:\r\n * - `#/path`: resolved against `scriptsRoot` via VFS join/normalize.\r\n * - `./` or `../`: resolved relative to `fromId` directory (requires `fromId`).\r\n * - `/absolute`: treated as absolute from root (normalized).\r\n * - Bare module in editor mode: if `/deps.lock.json` exists and contains an entry,\r\n * map to the dependency's `entry` path; otherwise return as-is.\r\n * - Else (non-editor bare module): return `spec` unchanged (external).\r\n *\r\n * @param spec - Import specifier string.\r\n * @param fromId - Optional base logical id used for relative resolution.\r\n * @returns A normalized logical id or an external specifier string.\r\n * @throws If a relative import is provided without `fromId`.\r\n */\r\n async resolveLogicalId(spec: string, fromId?: string) {\r\n if (spec.startsWith('#/')) {\r\n return this._vfs.normalizePath(this._vfs.join(this._scriptsRoot, spec.slice(2)));\r\n } else if (spec.startsWith('./') || spec.startsWith('../')) {\r\n if (!fromId) {\r\n throw new Error(`Relative import \"${spec}\" requires fromId`);\r\n }\r\n return this._vfs.normalizePath(\r\n this._vfs.join(this._vfs.dirname(this._vfs.normalizePath(fromId)), spec)\r\n );\r\n } else if (spec.startsWith('/')) {\r\n return spec.replace(/^\\/+/, '/');\r\n } else if (getApp().editorMode !== 'none') {\r\n // naked module, checking if it is a installed module in editor mode\r\n const depsExists = await this._vfs.exists('/libs/deps.lock.json');\r\n if (depsExists) {\r\n const content = (await this._vfs.readFile('/libs/deps.lock.json', { encoding: 'utf8' })) as string;\r\n const depsInfo = JSON.parse(content) as { dependencies: Record<string, { entry: string }> };\r\n if (depsInfo?.dependencies[spec]) {\r\n return this._vfs.normalizePath(depsInfo.dependencies[spec].entry);\r\n }\r\n }\r\n }\r\n return spec;\r\n }\r\n\r\n /**\r\n * Resolves a logical id to a concrete source path and type by probing extensions.\r\n *\r\n * Rules:\r\n * - If `logicalId` ends with `.ts` or `.js`/`.mjs` and is a file, return it.\r\n * - Else probe `logicalId.ts`, `logicalId.js`, `logicalId.mjs` in that order.\r\n * - Maps `.mjs` to type `'js'`.\r\n *\r\n * @param logicalId - The normalized logical module id (path-like).\r\n * @returns `{ type, path }` or `null` if not found.\r\n */\r\n async resolveSourcePath(logicalId: string) {\r\n let type: Nullable<'js' | 'ts'> = null;\r\n let pathWithExt = '';\r\n if (logicalId.endsWith('.ts')) {\r\n pathWithExt = logicalId;\r\n type = 'ts';\r\n } else if (logicalId.endsWith('.js') || logicalId.endsWith('.mjs')) {\r\n pathWithExt = logicalId;\r\n type = 'js';\r\n }\r\n if (type) {\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (!exists) {\r\n type = null;\r\n }\r\n const stat = await this._vfs.stat(pathWithExt);\r\n if (stat.isDirectory) {\r\n type = null;\r\n }\r\n }\r\n const types = ['ts', 'js', 'mjs'] as const;\r\n if (!type) {\r\n for (const t of types) {\r\n pathWithExt = `${logicalId}.${t}`;\r\n const exists = await this._vfs.exists(pathWithExt);\r\n if (exists) {\r\n const stats = await this._vfs.stat(pathWithExt);\r\n if (stats.isFile) {\r\n type = t === 'ts' ? 'ts' : 'js';\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n return type ? { type, path: pathWithExt } : null;\r\n }\r\n}\r\n"],"names":["toDataUrl","js","id","b64","textToBase64","encodeURIComponent","String","isAbsoluteUrl","spec","test","isSpecialUrl","isBareModule","startsWith","ScriptRegistry","_vfs","_scriptsRoot","_built","vfs","scriptsRoot","Map","VFS","clear","path","fetchSource","type","pathWithExt","endsWith","exists","stat","isDirectory","types","t","stats","isFile","code","readFile","encoding","resolveRuntimeUrl","entryId","resolveLogicalId","getApp","editorMode","build","slice","getDependencies","fromId","dependencies","reStatic","reDynamic","normalizedId","srcPath","resolveSourcePath","undefined","gather","input","re","m","exec","key","cached","get","rewritten","rewriteImports","transpile","url","set","_id","logicalId","ts","window","Error","res","transpileModule","compilerOptions","target","ScriptTarget","ES2015","module","ModuleKind","ESNext","sourceMap","inlineSources","experimentalDecorators","useDefineForClassFields","fileName","out","outputText","sourceMapText","mapBase64","btoa","unescape","init","imports","parse","list","sort","a","b","s","last","im","hasQuote","ss","se","e","replacement","depId","normalizePath","join","dirname","replace","depsExists","content","depsInfo","JSON","entry"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DWeakRef, ASSERT, base64ToUint8Array, Vector3, DRef, Vector4, isPowerOf2, nextPowerOf2
|
|
1
|
+
import { DWeakRef, ASSERT, base64ToUint8Array, Vector3, DRef, Vector4, VFSError, isPowerOf2, nextPowerOf2 } from '@zephyr3d/base';
|
|
2
2
|
import { GLTFLoader } from './loaders/gltf/gltf_loader.js';
|
|
3
3
|
import { WebImageLoader } from './loaders/image/webimage_loader.js';
|
|
4
4
|
import { DDSLoader } from './loaders/dds/dds_loader.js';
|
|
@@ -18,11 +18,13 @@ import '../material/particle.js';
|
|
|
18
18
|
import { Material } from '../material/material.js';
|
|
19
19
|
import '../material/meshmaterial.js';
|
|
20
20
|
import '../material/grassmaterial.js';
|
|
21
|
-
import '../material/terrainmaterial.js';
|
|
22
21
|
import '../material/terrain-cm.js';
|
|
23
22
|
import '../material/pbrmr.js';
|
|
24
23
|
import '../material/pbrsg.js';
|
|
25
24
|
import { PBRBluePrintMaterial } from '../material/pbrblueprint.js';
|
|
25
|
+
import '../material/sprite.js';
|
|
26
|
+
import '../material/sprite_std.js';
|
|
27
|
+
import { SpriteBlueprintMaterial } from '../material/spriteblueprint.js';
|
|
26
28
|
import { BoundingBox } from '../utility/bounding_volume.js';
|
|
27
29
|
import { MaterialBlueprintIR } from '../utility/blueprint/material/ir.js';
|
|
28
30
|
import '../render/renderer.js';
|
|
@@ -76,6 +78,7 @@ import '../shaders/atmosphere.js';
|
|
|
76
78
|
this._models = {};
|
|
77
79
|
this._materials = {};
|
|
78
80
|
this._primitives = {};
|
|
81
|
+
this._skeletons = {};
|
|
79
82
|
this._bluePrints = {};
|
|
80
83
|
this._binaryDatas = {};
|
|
81
84
|
this._textDatas = {};
|
|
@@ -467,27 +470,35 @@ import '../shaders/atmosphere.js';
|
|
|
467
470
|
const m = materials[i];
|
|
468
471
|
if (m instanceof PBRBluePrintMaterial && (!filter || filter(m))) {
|
|
469
472
|
const data = await this.loadBluePrintMaterialData(paths[i], true);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
473
|
+
if (data) {
|
|
474
|
+
m.fragmentIR = data.irFragment;
|
|
475
|
+
m.vertexIR = data.irVertex;
|
|
476
|
+
m.uniformValues = data.uniformValues;
|
|
477
|
+
m.uniformTextures = data.uniformTextures;
|
|
478
|
+
}
|
|
474
479
|
}
|
|
475
480
|
}
|
|
476
481
|
}
|
|
477
482
|
async loadBluePrintMaterialData(url, reload, VFSs) {
|
|
478
483
|
try {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
484
|
+
let irData;
|
|
485
|
+
if (typeof url === 'string') {
|
|
486
|
+
const data = await this.readFileFromVFSs(url, {
|
|
487
|
+
encoding: 'utf8'
|
|
488
|
+
}, VFSs);
|
|
489
|
+
const content = JSON.parse(data);
|
|
490
|
+
ASSERT(content.type === 'PBRBluePrintMaterial' || content.type === 'SpriteBluePrintMaterial', `Unsupported material type: ${content.type}`);
|
|
491
|
+
irData = content.data;
|
|
492
|
+
} else {
|
|
493
|
+
irData = url;
|
|
494
|
+
}
|
|
495
|
+
const ir = reload ? await this.loadBluePrint(irData.IR, VFSs) : await this.fetchBluePrint(irData.IR, VFSs);
|
|
496
|
+
const uniformValues = irData.uniformValues.map((v)=>({
|
|
486
497
|
...v,
|
|
487
498
|
finalValue: v.value.length === 1 ? v.value[0] : new Float32Array(v.value)
|
|
488
499
|
}));
|
|
489
500
|
const uniformTextures = [];
|
|
490
|
-
const textures =
|
|
501
|
+
const textures = irData.uniformTextures;
|
|
491
502
|
for (const v of textures){
|
|
492
503
|
const tex = await this.fetchTexture(v.texture, {
|
|
493
504
|
linearColorSpace: !v.sRGB
|
|
@@ -506,8 +517,8 @@ import '../shaders/atmosphere.js';
|
|
|
506
517
|
});
|
|
507
518
|
}
|
|
508
519
|
return {
|
|
509
|
-
irFragment: ir['fragment'],
|
|
510
|
-
irVertex: ir['vertex'],
|
|
520
|
+
irFragment: ir?.['fragment'] ?? null,
|
|
521
|
+
irVertex: ir?.['vertex'] ?? null,
|
|
511
522
|
uniformValues,
|
|
512
523
|
uniformTextures
|
|
513
524
|
};
|
|
@@ -530,10 +541,14 @@ import '../shaders/atmosphere.js';
|
|
|
530
541
|
encoding: 'utf8'
|
|
531
542
|
}, VFSs);
|
|
532
543
|
const content = JSON.parse(data);
|
|
533
|
-
ASSERT(content.type === 'PBRBluePrintMaterial' || content.type === 'Default', `Unsupported material type: ${content.type}`);
|
|
544
|
+
ASSERT(content.type === 'PBRBluePrintMaterial' || content.type === 'SpriteBluePrintMaterial' || content.type === 'Default', `Unsupported material type: ${content.type}`);
|
|
545
|
+
let mat;
|
|
534
546
|
if (content.type === 'PBRBluePrintMaterial') {
|
|
535
|
-
const data = await this.loadBluePrintMaterialData(
|
|
536
|
-
|
|
547
|
+
const data = await this.loadBluePrintMaterialData(content.data, reload, VFSs);
|
|
548
|
+
mat = new PBRBluePrintMaterial(data.irFragment, data.irVertex, data.uniformValues, data.uniformTextures);
|
|
549
|
+
} else if (content.type === 'SpriteBluePrintMaterial') {
|
|
550
|
+
const data = await this.loadBluePrintMaterialData(content.data, reload, VFSs);
|
|
551
|
+
mat = new SpriteBlueprintMaterial(data.irFragment, data.uniformValues, data.uniformTextures);
|
|
537
552
|
} else {
|
|
538
553
|
const obj = await this._resourceManager.deserializeObject(null, content.data);
|
|
539
554
|
if (!(obj instanceof Material)) {
|
|
@@ -544,6 +559,10 @@ import '../shaders/atmosphere.js';
|
|
|
544
559
|
}
|
|
545
560
|
return obj;
|
|
546
561
|
}
|
|
562
|
+
if (mat && content.props) {
|
|
563
|
+
await this._resourceManager.deserializeObjectProps(mat, content.props);
|
|
564
|
+
}
|
|
565
|
+
return mat;
|
|
547
566
|
} catch (err) {
|
|
548
567
|
console.error(`Load material failed: ${err}`);
|
|
549
568
|
return null;
|
|
@@ -668,13 +687,16 @@ import '../shaders/atmosphere.js';
|
|
|
668
687
|
order: this.getReverseTopologicalOrderFromRoots(gs, nodeMap, roots).order.reverse()
|
|
669
688
|
};
|
|
670
689
|
}
|
|
690
|
+
invalidateBluePrint(path) {
|
|
691
|
+
delete this._bluePrints[path];
|
|
692
|
+
}
|
|
671
693
|
async loadBluePrint(path, VFSs) {
|
|
672
694
|
try {
|
|
673
695
|
const content = await this.readFileFromVFSs(path, {
|
|
674
696
|
encoding: 'utf8'
|
|
675
697
|
}, VFSs);
|
|
676
698
|
const bp = JSON.parse(content);
|
|
677
|
-
ASSERT(bp.type === 'PBRMaterial' || bp.type === 'MaterialFunction', `Unsupported blueprint type: ${bp.type}`);
|
|
699
|
+
ASSERT(bp.type === 'PBRMaterial' || bp.type === 'SpriteMaterial' || bp.type === 'MaterialFunction', `Unsupported blueprint type: ${bp.type}`);
|
|
678
700
|
const states = bp.state;
|
|
679
701
|
const result = {};
|
|
680
702
|
for (const k of Object.keys(states)){
|
|
@@ -689,7 +711,7 @@ import '../shaders/atmosphere.js';
|
|
|
689
711
|
}
|
|
690
712
|
}
|
|
691
713
|
const dag = await this.createBluePrintDAG(nodeMap, roots, state.links);
|
|
692
|
-
result[k] = new MaterialBlueprintIR(dag, path);
|
|
714
|
+
result[k] = new MaterialBlueprintIR(dag, path, state);
|
|
693
715
|
}
|
|
694
716
|
return result;
|
|
695
717
|
} catch (err) {
|
|
@@ -745,7 +767,9 @@ import '../shaders/atmosphere.js';
|
|
|
745
767
|
continue;
|
|
746
768
|
}
|
|
747
769
|
const tex = await this.doLoadTexture(loader, mimeType, data, !!srgb, samplerOptions, texture);
|
|
748
|
-
|
|
770
|
+
if (tex) {
|
|
771
|
+
tex.name = this.vfs.basename(url);
|
|
772
|
+
}
|
|
749
773
|
return tex;
|
|
750
774
|
}
|
|
751
775
|
throw new Error(`Can not find loader for asset ${url}`);
|
|
@@ -768,28 +792,9 @@ import '../shaders/atmosphere.js';
|
|
|
768
792
|
return await loader.load(mimeType, data, srgb, samplerOptions, texture);
|
|
769
793
|
} else {
|
|
770
794
|
let tex = await loader.load(mimeType, data, srgb, samplerOptions);
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
const mipFilter = 'none';
|
|
775
|
-
const sampler = device.createSampler({
|
|
776
|
-
addressU: 'clamp',
|
|
777
|
-
addressV: 'clamp',
|
|
778
|
-
magFilter,
|
|
779
|
-
minFilter,
|
|
780
|
-
mipFilter
|
|
781
|
-
});
|
|
782
|
-
const blitter = new CopyBlitter();
|
|
783
|
-
blitter.blit(tex, texture, sampler);
|
|
784
|
-
tex = texture;
|
|
785
|
-
} else {
|
|
786
|
-
const po2_w = isPowerOf2(tex.width);
|
|
787
|
-
const po2_h = isPowerOf2(tex.height);
|
|
788
|
-
const srgb = tex.isSRGBFormat();
|
|
789
|
-
if (srgb || !po2_w || !po2_h) {
|
|
790
|
-
const newWidth = po2_w ? tex.width : nextPowerOf2(tex.width);
|
|
791
|
-
const newHeight = po2_h ? tex.height : nextPowerOf2(tex.height);
|
|
792
|
-
const magFilter = newWidth !== tex.width || newHeight !== tex.height ? 'linear' : 'nearest';
|
|
795
|
+
if (tex) {
|
|
796
|
+
if (texture) {
|
|
797
|
+
const magFilter = tex.width !== texture.width || tex.height !== texture.height ? 'linear' : 'nearest';
|
|
793
798
|
const minFilter = magFilter;
|
|
794
799
|
const mipFilter = 'none';
|
|
795
800
|
const sampler = device.createSampler({
|
|
@@ -799,12 +804,33 @@ import '../shaders/atmosphere.js';
|
|
|
799
804
|
minFilter,
|
|
800
805
|
mipFilter
|
|
801
806
|
});
|
|
802
|
-
const destFormat = srgb ? 'rgba8unorm' : tex.format;
|
|
803
807
|
const blitter = new CopyBlitter();
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
+
blitter.blit(tex, texture, sampler);
|
|
809
|
+
tex = texture;
|
|
810
|
+
} else {
|
|
811
|
+
const po2_w = isPowerOf2(tex.width);
|
|
812
|
+
const po2_h = isPowerOf2(tex.height);
|
|
813
|
+
const srgb = tex.isSRGBFormat();
|
|
814
|
+
if (srgb || !po2_w || !po2_h) {
|
|
815
|
+
const newWidth = po2_w ? tex.width : nextPowerOf2(tex.width);
|
|
816
|
+
const newHeight = po2_h ? tex.height : nextPowerOf2(tex.height);
|
|
817
|
+
const magFilter = newWidth !== tex.width || newHeight !== tex.height ? 'linear' : 'nearest';
|
|
818
|
+
const minFilter = magFilter;
|
|
819
|
+
const mipFilter = 'none';
|
|
820
|
+
const sampler = device.createSampler({
|
|
821
|
+
addressU: 'clamp',
|
|
822
|
+
addressV: 'clamp',
|
|
823
|
+
magFilter,
|
|
824
|
+
minFilter,
|
|
825
|
+
mipFilter
|
|
826
|
+
});
|
|
827
|
+
const destFormat = srgb ? 'rgba8unorm' : tex.format;
|
|
828
|
+
const blitter = new CopyBlitter();
|
|
829
|
+
const newTexture = tex.isTexture2D() ? device.createTexture2D(destFormat, newWidth, newHeight) : device.createCubeTexture(destFormat, newWidth);
|
|
830
|
+
blitter.blit(tex, newTexture, sampler);
|
|
831
|
+
tex.dispose();
|
|
832
|
+
tex = newTexture;
|
|
833
|
+
}
|
|
808
834
|
}
|
|
809
835
|
}
|
|
810
836
|
return tex;
|
|
@@ -894,7 +920,7 @@ import '../shaders/atmosphere.js';
|
|
|
894
920
|
if (loader) {
|
|
895
921
|
this._builtinTextureLoaders[name] = loader;
|
|
896
922
|
} else {
|
|
897
|
-
this._builtinTextureLoaders[name]
|
|
923
|
+
delete this._builtinTextureLoaders[name];
|
|
898
924
|
}
|
|
899
925
|
}
|
|
900
926
|
/**
|
|
@@ -925,14 +951,9 @@ import '../shaders/atmosphere.js';
|
|
|
925
951
|
this.vfs
|
|
926
952
|
];
|
|
927
953
|
for (const vfs of vfsList){
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
}
|
|
931
|
-
const stat = await vfs.stat(path);
|
|
932
|
-
if (!stat || !stat.isFile) {
|
|
933
|
-
continue;
|
|
934
|
-
}
|
|
935
|
-
return await vfs.readFile(path, options);
|
|
954
|
+
try {
|
|
955
|
+
return await vfs.readFile(path, options);
|
|
956
|
+
} catch {}
|
|
936
957
|
}
|
|
937
958
|
throw new VFSError(`File does not exist: ${path}`, 'ENOENT', path);
|
|
938
959
|
}
|