@zephyr3d/scene 0.9.26 → 0.10.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/README.md +60 -27
- package/dist/animation/animation_bank.js +634 -0
- package/dist/animation/animation_bank.js.map +1 -0
- package/dist/animation/animation_bank_gpu.js +256 -0
- package/dist/animation/animation_bank_gpu.js.map +1 -0
- package/dist/animation/animationset.js +146 -30
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/cloth/gpu_cloth_component.js +406 -0
- package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
- package/dist/animation/cloth/gpu_cloth_system.js +332 -202
- package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
- package/dist/animation/gpu_animation_driver.js +289 -0
- package/dist/animation/gpu_animation_driver.js.map +1 -0
- package/dist/animation/joint_dynamics/collision.js +112 -1
- package/dist/animation/joint_dynamics/collision.js.map +1 -1
- package/dist/animation/joint_dynamics/controller.js +6 -0
- package/dist/animation/joint_dynamics/controller.js.map +1 -1
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
- package/dist/animation/joint_dynamics/solver.js +50 -12
- package/dist/animation/joint_dynamics/solver.js.map +1 -1
- package/dist/animation/joint_dynamics/types.js.map +1 -1
- package/dist/animation/skeleton.js +300 -56
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skin_palette_atlas.js +252 -0
- package/dist/animation/skin_palette_atlas.js.map +1 -0
- package/dist/animation/spring/multi_chain_spring_system.js +298 -38
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
- package/dist/animation/spring/spring_chain.js +2 -0
- package/dist/animation/spring/spring_chain.js.map +1 -1
- package/dist/animation/spring/spring_collider.js +159 -21
- package/dist/animation/spring/spring_collider.js.map +1 -1
- package/dist/animation/spring/spring_particle.js +1 -0
- package/dist/animation/spring/spring_particle.js.map +1 -1
- package/dist/animation/spring/spring_solver.js +173 -0
- package/dist/animation/spring/spring_solver.js.map +1 -0
- package/dist/animation/spring/spring_system.js +249 -24
- package/dist/animation/spring/spring_system.js.map +1 -1
- package/dist/animation/spring_modifier.js +32 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/app/app.js +26 -0
- package/dist/app/app.js.map +1 -1
- package/dist/app/engine.js +86 -15
- package/dist/app/engine.js.map +1 -1
- package/dist/app/gamepad.js +191 -0
- package/dist/app/gamepad.js.map +1 -0
- package/dist/app/inputactions.js +271 -0
- package/dist/app/inputactions.js.map +1 -0
- package/dist/app/inputmgr.js +331 -22
- package/dist/app/inputmgr.js.map +1 -1
- package/dist/app/loading.js +138 -0
- package/dist/app/loading.js.map +1 -0
- package/dist/app/pipelinecache.js +209 -0
- package/dist/app/pipelinecache.js.map +1 -0
- package/dist/app/runtimescript.js +25 -0
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/scriptingsystem.js +54 -0
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +7 -2
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/asset_manifest.js +59 -0
- package/dist/asset/asset_manifest.js.map +1 -0
- package/dist/asset/asset_preload.js +258 -0
- package/dist/asset/asset_preload.js.map +1 -0
- package/dist/asset/assetmanager.js +117 -65
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/dist/asset/loaders/ktx2/basis_location.js +17 -0
- package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
- package/dist/asset/mesh_lod_builder.js +104 -0
- package/dist/asset/mesh_lod_builder.js.map +1 -0
- package/dist/asset/mesh_settings.js +111 -0
- package/dist/asset/mesh_settings.js.map +1 -0
- package/dist/asset/meshopt_decoder.js +18 -0
- package/dist/asset/meshopt_decoder.js.map +1 -0
- package/dist/asset/meshopt_simplifier.js +26 -0
- package/dist/asset/meshopt_simplifier.js.map +1 -0
- package/dist/asset/model.js +177 -3
- package/dist/asset/model.js.map +1 -1
- package/dist/asset/texture_settings.js +231 -0
- package/dist/asset/texture_settings.js.map +1 -0
- package/dist/asset/zmsh_binary.js +131 -0
- package/dist/asset/zmsh_binary.js.map +1 -0
- package/dist/asset/zsdf_binary.js +111 -0
- package/dist/asset/zsdf_binary.js.map +1 -0
- package/dist/blitter/bilateralblur.js +1 -2
- package/dist/blitter/bilateralblur.js.map +1 -1
- package/dist/blitter/gaussianblur.js +1 -6
- package/dist/blitter/gaussianblur.js.map +1 -1
- package/dist/camera/base.js +31 -10
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +178 -200
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/follow.js +342 -0
- package/dist/camera/follow.js.map +1 -0
- package/dist/camera/fps.js +9 -7
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +46 -19
- package/dist/camera/orbit.js.map +1 -1
- package/dist/index.d.ts +30475 -19865
- package/dist/index.js +67 -12
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js +3 -0
- package/dist/material/blinn.js.map +1 -1
- package/dist/material/eye.js +1 -1
- package/dist/material/eye.js.map +1 -1
- package/dist/material/hair.js +2 -3
- package/dist/material/hair.js.map +1 -1
- package/dist/material/hairstrand.js +235 -235
- package/dist/material/hairstrand.js.map +1 -1
- package/dist/material/lambert.js +4 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +362 -300
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +118 -45
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js +1 -1
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +223 -83
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +31 -206
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mtoon.js +1 -1
- package/dist/material/mtoon.js.map +1 -1
- package/dist/material/pbrmr.js +3 -0
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/pbrsg.js +3 -0
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/sdf_debug.js +78 -0
- package/dist/material/sdf_debug.js.map +1 -0
- package/dist/material/shader/helper.js +733 -190
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/shader/terrain_blend.js +204 -43
- package/dist/material/shader/terrain_blend.js.map +1 -1
- package/dist/material/skin.js +331 -297
- package/dist/material/skin.js.map +1 -1
- package/dist/material/skinprofile.js +1058 -0
- package/dist/material/skinprofile.js.map +1 -0
- package/dist/material/sss.js +353 -0
- package/dist/material/sss.js.map +1 -0
- package/dist/material/sss_kernel.js +265 -0
- package/dist/material/sss_kernel.js.map +1 -0
- package/dist/material/sssprofile.js +879 -0
- package/dist/material/sssprofile.js.map +1 -0
- package/dist/material/subsurfaceprofile.js +4 -8
- package/dist/material/subsurfaceprofile.js.map +1 -1
- package/dist/material/terrain-cm.js +464 -188
- package/dist/material/terrain-cm.js.map +1 -1
- package/dist/material/unlit.js +3 -0
- package/dist/material/unlit.js.map +1 -1
- package/dist/material/water.js +2009 -201
- package/dist/material/water.js.map +1 -1
- package/dist/node_modules/meshoptimizer/LICENSE +21 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
- package/dist/physics/character.js +226 -0
- package/dist/physics/character.js.map +1 -0
- package/dist/physics/collider.js +209 -0
- package/dist/physics/collider.js.map +1 -0
- package/dist/physics/events.js +79 -0
- package/dist/physics/events.js.map +1 -0
- package/dist/physics/joint.js +272 -0
- package/dist/physics/joint.js.map +1 -0
- package/dist/physics/node_physics.js +234 -0
- package/dist/physics/node_physics.js.map +1 -0
- package/dist/physics/part.js +91 -0
- package/dist/physics/part.js.map +1 -0
- package/dist/physics/rigid_body.js +379 -0
- package/dist/physics/rigid_body.js.map +1 -0
- package/dist/physics/vehicle.js +335 -0
- package/dist/physics/vehicle.js.map +1 -0
- package/dist/physics/world.js +25 -0
- package/dist/physics/world.js.map +1 -0
- package/dist/posteffect/bloom.js +49 -14
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/motionblur.js +668 -63
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/posteffect.js +12 -1
- package/dist/posteffect/posteffect.js.map +1 -1
- package/dist/posteffect/postsss.js +572 -0
- package/dist/posteffect/postsss.js.map +1 -0
- package/dist/posteffect/sao.js +48 -50
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/skinsss.js +605 -355
- package/dist/posteffect/skinsss.js.map +1 -1
- package/dist/posteffect/ssgi.js +91 -162
- package/dist/posteffect/ssgi.js.map +1 -1
- package/dist/posteffect/ssr.js +3 -11
- package/dist/posteffect/ssr.js.map +1 -1
- package/dist/posteffect/sss.js +34 -15
- package/dist/posteffect/sss.js.map +1 -1
- package/dist/posteffect/taa.js +1 -0
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/render/abuffer_oit.js +40 -39
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +328 -62
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cluster_light.js +958 -224
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/cull_visitor.js +26 -5
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/debug_views.js +37 -0
- package/dist/render/debug_views.js.map +1 -0
- package/dist/render/depthpass.js +5 -1
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable_mixin.js +53 -6
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/dualdepthpeeling_oit.js +53 -53
- package/dist/render/dualdepthpeeling_oit.js.map +1 -1
- package/dist/render/envlight.js +196 -113
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +8 -13
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +268 -136
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +113 -28
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/gi/probe_volume.js +1334 -0
- package/dist/render/gi/probe_volume.js.map +1 -0
- package/dist/render/gi/scene_gi.js +282 -0
- package/dist/render/gi/scene_gi.js.map +1 -0
- package/dist/render/gi/voxel_atlas.js +198 -0
- package/dist/render/gi/voxel_atlas.js.map +1 -0
- package/dist/render/gi/voxel_lighting.js +652 -0
- package/dist/render/gi/voxel_lighting.js.map +1 -0
- package/dist/render/gi/voxel_scene.js +642 -0
- package/dist/render/gi/voxel_scene.js.map +1 -0
- package/dist/render/gi/voxelize_pass.js +223 -0
- package/dist/render/gi/voxelize_pass.js.map +1 -0
- package/dist/render/globalbindgroup_allocator.js +3 -2
- package/dist/render/globalbindgroup_allocator.js.map +1 -1
- package/dist/render/gpu_picking.js +9 -36
- package/dist/render/gpu_picking.js.map +1 -1
- package/dist/render/hzb.js +80 -22
- package/dist/render/hzb.js.map +1 -1
- package/dist/render/instance_culling.js +499 -0
- package/dist/render/instance_culling.js.map +1 -0
- package/dist/render/lightpass.js +23 -9
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/lod.js +46 -0
- package/dist/render/lod.js.map +1 -0
- package/dist/render/oit.js +11 -11
- package/dist/render/oit.js.map +1 -1
- package/dist/render/primitive.js +301 -9
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/primitive_readback.js +209 -0
- package/dist/render/primitive_readback.js.map +1 -0
- package/dist/render/render_queue.js +198 -11
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +14 -7
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +15 -1
- package/dist/render/rendergraph/blackboard.js.map +1 -1
- package/dist/render/rendergraph/executor.js +136 -0
- package/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +585 -59
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
- package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
- package/dist/render/rendergraph/history_resources.js +8 -1
- package/dist/render/rendergraph/history_resources.js.map +1 -1
- package/dist/render/rendergraph/scene_render_context.js +31 -2
- package/dist/render/rendergraph/scene_render_context.js.map +1 -1
- package/dist/render/rendergraph/types.js.map +1 -1
- package/dist/render/renderpass.js +28 -5
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/sdf/box_allocator.js +98 -0
- package/dist/render/sdf/box_allocator.js.map +1 -0
- package/dist/render/sdf/global_sdf.js +865 -0
- package/dist/render/sdf/global_sdf.js.map +1 -0
- package/dist/render/sdf/scene_sdf.js +562 -0
- package/dist/render/sdf/scene_sdf.js.map +1 -0
- package/dist/render/sdf/sdf_atlas.js +227 -0
- package/dist/render/sdf/sdf_atlas.js.map +1 -0
- package/dist/render/sdf/sdf_programs.js +42 -0
- package/dist/render/sdf/sdf_programs.js.map +1 -0
- package/dist/render/sdf/sdf_view.js +199 -0
- package/dist/render/sdf/sdf_view.js.map +1 -0
- package/dist/render/sdf/waterline.js +610 -0
- package/dist/render/sdf/waterline.js.map +1 -0
- package/dist/render/shadow_mask_pass.js +142 -25
- package/dist/render/shadow_mask_pass.js.map +1 -1
- package/dist/render/shore_wave_generator.js +1193 -0
- package/dist/render/shore_wave_generator.js.map +1 -0
- package/dist/render/sky.js +516 -86
- package/dist/render/sky.js.map +1 -1
- package/dist/render/transmission_thickness_pass.js +477 -0
- package/dist/render/transmission_thickness_pass.js.map +1 -0
- package/dist/render/underwater.js +524 -0
- package/dist/render/underwater.js.map +1 -0
- package/dist/render/virtualtexture/virtual_texture.js +1214 -0
- package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_common.js +472 -0
- package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
- package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
- package/dist/render/volumetric_cloud/debug_view.js +131 -0
- package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
- package/dist/render/volumetric_cloud/resources.js +380 -0
- package/dist/render/volumetric_cloud/resources.js.map +1 -0
- package/dist/render/volumetric_cloud/sky_cache.js +380 -0
- package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
- package/dist/render/water_caustics.js +1195 -0
- package/dist/render/water_caustics.js.map +1 -0
- package/dist/render/water_foam.js +627 -0
- package/dist/render/water_foam.js.map +1 -0
- package/dist/render/water_interaction.js +1795 -0
- package/dist/render/water_interaction.js.map +1 -0
- package/dist/render/weightedblended_oit.js +36 -36
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/basesprite.js +9 -4
- package/dist/scene/basesprite.js.map +1 -1
- package/dist/scene/batchgroup.js +108 -12
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +28 -7
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/foliage.js +1020 -0
- package/dist/scene/foliage.js.map +1 -0
- package/dist/scene/foliage_buckets.js +147 -0
- package/dist/scene/foliage_buckets.js.map +1 -0
- package/dist/scene/foliage_mask.js +358 -0
- package/dist/scene/foliage_mask.js.map +1 -0
- package/dist/scene/hair.js +15 -4
- package/dist/scene/hair.js.map +1 -1
- package/dist/scene/light.js +179 -13
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +327 -45
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/meshdrawable.js +6 -0
- package/dist/scene/meshdrawable.js.map +1 -1
- package/dist/scene/msdftext.js +9 -3
- package/dist/scene/msdftext.js.map +1 -1
- package/dist/scene/msdftextsprite.js +9 -3
- package/dist/scene/msdftextsprite.js.map +1 -1
- package/dist/scene/particlesys.js +8 -2
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/physics_settings.js +157 -0
- package/dist/scene/physics_settings.js.map +1 -0
- package/dist/scene/scene.js +190 -44
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +147 -6
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
- package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +881 -42
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/grass_gpu.js +929 -0
- package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
- package/dist/scene/terrain-cm/grassmaterial.js +180 -9
- package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +465 -36
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
- package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
- package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
- package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
- package/dist/scene/update_queue.js +54 -0
- package/dist/scene/update_queue.js.map +1 -0
- package/dist/scene/water.js +997 -96
- package/dist/scene/water.js.map +1 -1
- package/dist/scene/water_surface_sampler.js +324 -0
- package/dist/scene/water_surface_sampler.js.map +1 -0
- package/dist/scene/wind.js +317 -0
- package/dist/scene/wind.js.map +1 -0
- package/dist/shaders/atmosphere.js +388 -166
- package/dist/shaders/atmosphere.js.map +1 -1
- package/dist/shaders/fog.js +100 -32
- package/dist/shaders/fog.js.map +1 -1
- package/dist/shaders/gi.js +365 -0
- package/dist/shaders/gi.js.map +1 -0
- package/dist/shaders/ltc_rect.js +202 -0
- package/dist/shaders/ltc_rect.js.map +1 -0
- package/dist/shaders/misc.js +1 -10
- package/dist/shaders/misc.js.map +1 -1
- package/dist/shaders/noise.js +5 -1
- package/dist/shaders/noise.js.map +1 -1
- package/dist/shaders/probes.js +309 -0
- package/dist/shaders/probes.js.map +1 -0
- package/dist/shaders/sdf.js +537 -0
- package/dist/shaders/sdf.js.map +1 -0
- package/dist/shaders/shadow.js +104 -70
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shaders/skin_brdf.js +243 -0
- package/dist/shaders/skin_brdf.js.map +1 -0
- package/dist/shaders/ssr.js +6 -159
- package/dist/shaders/ssr.js.map +1 -1
- package/dist/shaders/temporal.js +38 -27
- package/dist/shaders/temporal.js.map +1 -1
- package/dist/shaders/water.js +40 -87
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +42 -0
- package/dist/shaders/water_medium.js.map +1 -0
- package/dist/shadow/dom.js +110 -19
- package/dist/shadow/dom.js.map +1 -1
- package/dist/shadow/esm.js +3 -3
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/pcf_opt.js +15 -48
- package/dist/shadow/pcf_opt.js.map +1 -1
- package/dist/shadow/pcf_pd.js +15 -53
- package/dist/shadow/pcf_pd.js.map +1 -1
- package/dist/shadow/pcss.js +34 -9
- package/dist/shadow/pcss.js.map +1 -1
- package/dist/shadow/shadow_impl.js +3 -8
- package/dist/shadow/shadow_impl.js.map +1 -1
- package/dist/shadow/shadow_region.js +87 -49
- package/dist/shadow/shadow_region.js.map +1 -1
- package/dist/shadow/shadowmapper.js +93 -53
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/ssm.js +18 -72
- package/dist/shadow/ssm.js.map +1 -1
- package/dist/shadow/vsm.js +3 -3
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/shape.js +44 -1
- package/dist/shapes/shape.js.map +1 -1
- package/dist/utility/buoyancy.js +287 -0
- package/dist/utility/buoyancy.js.map +1 -0
- package/dist/utility/physical.js +10 -1
- package/dist/utility/physical.js.map +1 -1
- package/dist/utility/pmrem.js +17 -43
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/sdf/bake.js +435 -0
- package/dist/utility/sdf/bake.js.map +1 -0
- package/dist/utility/sdf/bvh.js +576 -0
- package/dist/utility/sdf/bvh.js.map +1 -0
- package/dist/utility/serialization/manager.js +36 -6
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +77 -7
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +11 -4
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +140 -279
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/cloth.js +25 -0
- package/dist/utility/serialization/scene/cloth.js.map +1 -0
- package/dist/utility/serialization/scene/common.js +14 -6
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/foliage.js +821 -0
- package/dist/utility/serialization/scene/foliage.js.map +1 -0
- package/dist/utility/serialization/scene/hair.js +11 -4
- package/dist/utility/serialization/scene/hair.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +115 -7
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +388 -220
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +69 -4
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +140 -5
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/node_physics.js +1318 -0
- package/dist/utility/serialization/scene/node_physics.js.map +1 -0
- package/dist/utility/serialization/scene/particle.js +11 -4
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/physics.js +120 -0
- package/dist/utility/serialization/scene/physics.js.map +1 -0
- package/dist/utility/serialization/scene/primitive.js +124 -10
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +1687 -51
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/sprite.js +11 -4
- package/dist/utility/serialization/scene/sprite.js.map +1 -1
- package/dist/utility/serialization/scene/terrain.js +163 -33
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/text.js +11 -4
- package/dist/utility/serialization/scene/text.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +2473 -114
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/shprojector.js +97 -109
- package/dist/utility/shprojector.js.map +1 -1
- package/dist/utility/textures/foam.js +170 -0
- package/dist/utility/textures/foam.js.map +1 -0
- package/dist/utility/textures/ggxlut.js +17 -43
- package/dist/utility/textures/ggxlut.js.map +1 -1
- package/dist/utility/textures/ltcdata.js +4 -4
- package/dist/utility/textures/ltcdata.js.map +1 -1
- package/dist/utility/textures/ltclut.js +16 -6
- package/dist/utility/textures/ltclut.js.map +1 -1
- package/dist/utility/unsupported.js +24 -0
- package/dist/utility/unsupported.js.map +1 -0
- package/dist/values.js +13 -1
- package/dist/values.js.map +1 -1
- package/package.json +25 -12
- package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/src/asset/meshoptimizer/LICENSE +21 -0
package/dist/app/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sources":["../../src/app/app.ts"],"sourcesContent":["import type { Nullable, RequireOptionals, VFS } from '@zephyr3d/base';\r\nimport { Observable, flushPendingDisposals } from '@zephyr3d/base';\r\nimport type { AbstractDevice, DeviceBackend } from '@zephyr3d/device';\r\nimport { InputManager } from './inputmgr';\r\nimport { Engine } from './engine';\r\nimport { getApp, setApp } from './api';\r\nimport type { ScreenConfig } from './screen';\r\n\r\ntype appEventMap = {\r\n /**\r\n * Emitted when the drawing surface (canvas/device) is resized.\r\n *\r\n * @param width - New drawable width in device pixels.\r\n * @param height - New drawable height in device pixels.\r\n */\r\n resize: [width: number, height: number];\r\n /**\r\n * Emitted every frame with timing information.\r\n *\r\n * @param deltaTimeMs - Elapsed time since last frame in milliseconds.\r\n * @param elapsedTimeMs - Elapsed time since app start in milliseconds.\r\n */\r\n tick: [deltaTimeMs: number, elapsedTimeMs: number];\r\n /** Pointer/mouse and keyboard input events forwarded by the Application. */\r\n click: [evt: PointerEvent];\r\n dblclick: [evt: PointerEvent];\r\n pointerdown: [evt: PointerEvent];\r\n pointerup: [evt: PointerEvent];\r\n pointermove: [evt: PointerEvent];\r\n pointercancel: [evt: PointerEvent];\r\n pointerenter: [evt: PointerEvent];\r\n pointerleave: [evt: PointerEvent];\r\n pointerover: [evt: PointerEvent];\r\n pointerout: [evt: PointerEvent];\r\n wheel: [evt: WheelEvent];\r\n keydown: [evt: KeyboardEvent];\r\n keyup: [evt: KeyboardEvent];\r\n keypress: [evt: KeyboardEvent];\r\n drag: [evt: DragEvent];\r\n dragenter: [evt: DragEvent];\r\n dragleave: [evt: DragEvent];\r\n dragover: [evt: DragEvent];\r\n dragstart: [evt: DragEvent];\r\n dragend: [evt: DragEvent];\r\n drop: [evt: DragEvent];\r\n};\r\n\r\n/**\r\n * Application editor/runtime mode.\r\n *\r\n * @public\r\n */\r\nexport type EditorMode = 'editor' | 'editor-preview' | 'none';\r\n\r\n/**\r\n * Options for Application.\r\n *\r\n * @public\r\n */\r\nexport interface AppOptions {\r\n /**\r\n * Target canvas element to attach the rendering device to.\r\n */\r\n canvas: HTMLCanvasElement;\r\n /**\r\n * Device backend implementation to use for GPU creation (e.g., WebGL/WebGPU backend).\r\n */\r\n backend: DeviceBackend;\r\n /**\r\n * Whether to enable multi-sample anti-aliasing (MSAA) if supported by the backend.\r\n * Defaults to false.\r\n */\r\n enableMSAA?: boolean;\r\n /**\r\n * Device pixel ratio used when creating the device. Defaults to `window.devicePixelRatio` or `1`.\r\n */\r\n pixelRatio?: number;\r\n}\r\n\r\n/**\r\n * Creation options for Application.\r\n *\r\n * Provides the canvas, device backend, and optional runtime and device configuration.\r\n * @public\r\n */\r\nexport interface AppCreationOptions extends AppOptions {\r\n /**\r\n * Options for the runtime scripting system.\r\n */\r\n runtimeOptions?: {\r\n /**\r\n * Virtual file system used to load scripts. Defaults to HttpFS at '.' if not provided.\r\n */\r\n VFS?: VFS;\r\n /**\r\n * Root directory for script files. Defaults to '/'.\r\n */\r\n scriptsRoot?: string;\r\n /**\r\n * Whether the application is running in editor mode. Should be true for user applications.\r\n */\r\n editorMode?: EditorMode;\r\n /**\r\n * Whether the runtime scripting system is enabled. Should be true for user applications.\r\n */\r\n enabled?: boolean;\r\n /**\r\n * Screen configuration\r\n */\r\n screen?: ScreenConfig;\r\n };\r\n}\r\n\r\n/**\r\n * Log severity levels.\r\n * @public\r\n */\r\nexport type LogMode = 'info' | 'warn' | 'error' | 'debug';\r\n\r\n/**\r\n * Application\r\n *\r\n * Entry-point and lifecycle coordinator for the engine. Responsible for:\r\n * - Creating and owning the rendering device from a chosen backend.\r\n * - Managing the per-frame loop, including timing and viewport setup.\r\n * - Forwarding device/DOM input events via an observable event map.\r\n * - Hosting the runtime scripting system and input manager.\r\n *\r\n * Singleton:\r\n * - Only one instance may exist at a time. Access via `{@link getApp}`.\r\n *\r\n * Events:\r\n * - See `appEventMap` for all emitted events (resize, tick, pointer/keyboard/drag).\r\n *\r\n * Usage:\r\n * - Construct with `AppOptions`, await `ready()`, then call `run()` to start the loop.\r\n *\r\n * @public\r\n */\r\nexport class Application extends Observable<appEventMap> {\r\n private readonly _options: RequireOptionals<AppOptions>;\r\n private _device: Nullable<AbstractDevice>;\r\n private readonly _inputManager: InputManager;\r\n private readonly _engine: Engine;\r\n private readonly _editorMode: EditorMode;\r\n private _ready: boolean;\r\n /**\r\n * Construct the Application singleton with the provided options.\r\n *\r\n * Throws if an instance already exists.\r\n *\r\n * @param opt - Application creation options (canvas, backend, and optional runtime/device settings).\r\n */\r\n constructor(opt: AppCreationOptions) {\r\n super();\r\n if (getApp()) {\r\n throw new Error('It is not allowed to have multiple Application instances');\r\n }\r\n setApp(this);\r\n\r\n this._options = {\r\n backend: opt.backend,\r\n enableMSAA: opt.enableMSAA ?? false,\r\n pixelRatio: opt.pixelRatio ?? window.devicePixelRatio ?? 1,\r\n canvas: opt.canvas\r\n };\r\n this._inputManager = new InputManager(this);\r\n this._engine = new Engine(\r\n opt.runtimeOptions?.VFS,\r\n opt.runtimeOptions?.scriptsRoot,\r\n opt.runtimeOptions?.enabled\r\n );\r\n if (opt.runtimeOptions?.screen) {\r\n this._engine.screen.config = opt.runtimeOptions.screen;\r\n }\r\n this._editorMode = opt.runtimeOptions?.editorMode ?? 'none';\r\n this._device = null;\r\n this._ready = false;\r\n }\r\n /**\r\n * Editor mode\r\n */\r\n get editorMode() {\r\n return this._editorMode;\r\n }\r\n /**\r\n * The input manager instance handling pointer/keyboard event routing.\r\n */\r\n get inputManager() {\r\n return this._inputManager;\r\n }\r\n /**\r\n * Get the instanceof {@link Engine}.\r\n */\r\n get engine() {\r\n return this._engine;\r\n }\r\n /**\r\n * The (sanitized) options used to create this application.\r\n *\r\n * Note: Defaults are applied for `enableMSAA` and `pixelRatio` if omitted.\r\n */\r\n get options() {\r\n return this._options;\r\n }\r\n /**\r\n * The initialized rendering device.\r\n *\r\n * Available after `await ready()`.\r\n */\r\n get device() {\r\n return this._device!;\r\n }\r\n /**\r\n * Convenience accessor for the device type name provided by the backend.\r\n */\r\n get deviceType() {\r\n return this._options.backend.typeName();\r\n }\r\n /**\r\n * Set keyboard focus to the device's canvas element.\r\n */\r\n focus() {\r\n this._device!.canvas.focus();\r\n }\r\n /**\r\n * Initialize the rendering device and start input processing.\r\n *\r\n * @throws If device creation fails.\r\n */\r\n async ready() {\r\n if (!this._ready) {\r\n this._device = await this._options.backend.createDevice(this._options.canvas, {\r\n dpr: this._options.pixelRatio,\r\n msaa: !!this._options.enableMSAA\r\n });\r\n if (!this._device) {\r\n throw new Error('App.init(): create device failed');\r\n }\r\n this._device.canvas.focus();\r\n await this._engine.init();\r\n this._inputManager.start();\r\n this._device.on('resize', (width, height) => {\r\n this._engine.screen.resolveViewport();\r\n this.dispatchEvent('resize', width, height);\r\n });\r\n this._ready = true;\r\n }\r\n }\r\n /**\r\n * Render a single frame.\r\n *\r\n * Steps:\r\n * - Flushes pending disposals from the previous frame.\r\n * - Clears device state (framebuffer, viewport, scissor).\r\n * - Queries frame timing from the device (`elapsedFrame`, `elapsedOverall`).\r\n * - Updates the runtime manager (scripting/behaviors).\r\n * - Emits `tick` with delta/elapsed times.\r\n *\r\n * Safe to call manually; also used by the run loop.\r\n */\r\n frame() {\r\n // Processes all pending disposals from the previous frame.\r\n flushPendingDisposals();\r\n if (this._ready) {\r\n this.device.setFramebuffer(null);\r\n this.device.setViewport(null);\r\n this.device.setScissor(null);\r\n const dt = this.device.frameInfo.elapsedFrame;\r\n const elapsed = this.device.frameInfo.elapsedOverall;\r\n this.dispatchEvent('tick', dt, elapsed);\r\n this._engine.update(dt * 0.001, elapsed * 0.001);\r\n this._engine.render();\r\n }\r\n }\r\n /**\r\n * Advances exactly one frame outside the run loop.\r\n *\r\n * @remarks\r\n * Uses the same `beginFrame()`/`frame()`/`endFrame()` sequence as the run\r\n * loop, so per-frame non-idempotent state (history buffer ping-pong, frame\r\n * counter, motion vector matrices) advances exactly once. Must not be called\r\n * while the run loop started by {@link Application.run} is active.\r\n *\r\n * @returns true if the frame was rendered; false if the device skipped it\r\n * (e.g. the rendering context is lost).\r\n */\r\n stepFrame(): boolean {\r\n if (this.device.isRendering) {\r\n console.error('Application.stepFrame(): can not be called while the run loop is active');\r\n return false;\r\n }\r\n if (this.device.beginFrame()) {\r\n this.frame();\r\n this.device.endFrame();\r\n return true;\r\n }\r\n return false;\r\n }\r\n /**\r\n * Start the application's render loop.\r\n *\r\n * Uses the device's internal scheduling (`device.runLoop`) to repeatedly call `frame()`.\r\n */\r\n run() {\r\n this.device.runLoop(() => {\r\n this.frame();\r\n });\r\n }\r\n /**\r\n * Stop the application's render loop.\r\n *\r\n * Uses `device.exitLoop()` to end the scheduling started by `run()`.\r\n */\r\n stop() {\r\n this.device.exitLoop();\r\n }\r\n}\r\n"],"names":["Application","Observable","_options","_device","_inputManager","_engine","_editorMode","_ready","opt","getApp","Error","setApp","backend","enableMSAA","pixelRatio","window","devicePixelRatio","canvas","InputManager","Engine","runtimeOptions","VFS","scriptsRoot","enabled","screen","config","editorMode","inputManager","engine","options","device","deviceType","typeName","focus","ready","createDevice","dpr","msaa","init","start","on","width","height","resolveViewport","dispatchEvent","frame","flushPendingDisposals","setFramebuffer","setViewport","setScissor","dt","frameInfo","elapsedFrame","elapsed","elapsedOverall","update","render","stepFrame","isRendering","console","error","beginFrame","endFrame","run","runLoop","stop","exitLoop"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app.js","sources":["../../src/app/app.ts"],"sourcesContent":["import type { Nullable, RequireOptionals, VFS } from '@zephyr3d/base';\r\nimport { Observable, flushPendingDisposals } from '@zephyr3d/base';\r\nimport type { AbstractDevice, DeviceBackend } from '@zephyr3d/device';\r\nimport { InputManager } from './inputmgr';\r\nimport { Engine } from './engine';\r\nimport { getApp, setApp } from './api';\r\nimport type { ScreenConfig } from './screen';\r\n\r\ntype appEventMap = {\r\n /**\r\n * Emitted when the drawing surface (canvas/device) is resized.\r\n *\r\n * @param width - New drawable width in device pixels.\r\n * @param height - New drawable height in device pixels.\r\n */\r\n resize: [width: number, height: number];\r\n /**\r\n * Emitted every frame with timing information.\r\n *\r\n * @param deltaTimeMs - Elapsed time since last frame in milliseconds.\r\n * @param elapsedTimeMs - Elapsed time since app start in milliseconds.\r\n */\r\n tick: [deltaTimeMs: number, elapsedTimeMs: number];\r\n /** Pointer/mouse and keyboard input events forwarded by the Application. */\r\n click: [evt: PointerEvent];\r\n dblclick: [evt: PointerEvent];\r\n pointerdown: [evt: PointerEvent];\r\n pointerup: [evt: PointerEvent];\r\n pointermove: [evt: PointerEvent];\r\n pointercancel: [evt: PointerEvent];\r\n pointerenter: [evt: PointerEvent];\r\n pointerleave: [evt: PointerEvent];\r\n pointerover: [evt: PointerEvent];\r\n pointerout: [evt: PointerEvent];\r\n wheel: [evt: WheelEvent];\r\n keydown: [evt: KeyboardEvent];\r\n keyup: [evt: KeyboardEvent];\r\n keypress: [evt: KeyboardEvent];\r\n drag: [evt: DragEvent];\r\n dragenter: [evt: DragEvent];\r\n dragleave: [evt: DragEvent];\r\n dragover: [evt: DragEvent];\r\n dragstart: [evt: DragEvent];\r\n dragend: [evt: DragEvent];\r\n drop: [evt: DragEvent];\r\n};\r\n\r\n/**\r\n * Application editor/runtime mode.\r\n *\r\n * @public\r\n */\r\nexport type EditorMode = 'editor' | 'editor-preview' | 'none';\r\n\r\n/**\r\n * Options for Application.\r\n *\r\n * @public\r\n */\r\nexport interface AppOptions {\r\n /**\r\n * Target canvas element to attach the rendering device to.\r\n */\r\n canvas: HTMLCanvasElement;\r\n /**\r\n * Device backend implementation to use for GPU creation (e.g., WebGL/WebGPU backend).\r\n */\r\n backend: DeviceBackend;\r\n /**\r\n * Whether to enable multi-sample anti-aliasing (MSAA) if supported by the backend.\r\n * Defaults to false.\r\n */\r\n enableMSAA?: boolean;\r\n /**\r\n * Device pixel ratio used when creating the device. Defaults to `window.devicePixelRatio` or `1`.\r\n */\r\n pixelRatio?: number;\r\n}\r\n\r\n/**\r\n * Creation options for Application.\r\n *\r\n * Provides the canvas, device backend, and optional runtime and device configuration.\r\n * @public\r\n */\r\nexport interface AppCreationOptions extends AppOptions {\r\n /**\r\n * Options for the runtime scripting system.\r\n */\r\n runtimeOptions?: {\r\n /**\r\n * Virtual file system used to load scripts. Defaults to HttpFS at '.' if not provided.\r\n */\r\n VFS?: VFS;\r\n /**\r\n * Root directory for script files. Defaults to '/'.\r\n */\r\n scriptsRoot?: string;\r\n /**\r\n * Whether the application is running in editor mode. Should be true for user applications.\r\n */\r\n editorMode?: EditorMode;\r\n /**\r\n * Whether the runtime scripting system is enabled. Should be true for user applications.\r\n */\r\n enabled?: boolean;\r\n /**\r\n * Screen configuration\r\n */\r\n screen?: ScreenConfig;\r\n };\r\n}\r\n\r\n/**\r\n * Log severity levels.\r\n * @public\r\n */\r\nexport type LogMode = 'info' | 'warn' | 'error' | 'debug';\r\n\r\n/**\r\n * Application\r\n *\r\n * Entry-point and lifecycle coordinator for the engine. Responsible for:\r\n * - Creating and owning the rendering device from a chosen backend.\r\n * - Managing the per-frame loop, including timing and viewport setup.\r\n * - Forwarding device/DOM input events via an observable event map.\r\n * - Hosting the runtime scripting system and input manager.\r\n *\r\n * Singleton:\r\n * - Only one instance may exist at a time. Access via `{@link getApp}`.\r\n *\r\n * Events:\r\n * - See `appEventMap` for all emitted events (resize, tick, pointer/keyboard/drag).\r\n *\r\n * Usage:\r\n * - Construct with `AppOptions`, await `ready()`, then call `run()` to start the loop.\r\n *\r\n * @public\r\n */\r\nexport class Application extends Observable<appEventMap> {\r\n private readonly _options: RequireOptionals<AppOptions>;\r\n private _device: Nullable<AbstractDevice>;\r\n private readonly _inputManager: InputManager;\r\n private readonly _engine: Engine;\r\n private readonly _editorMode: EditorMode;\r\n private _ready: boolean;\r\n private _frameWaiters: (() => void)[];\r\n /**\r\n * Construct the Application singleton with the provided options.\r\n *\r\n * Throws if an instance already exists.\r\n *\r\n * @param opt - Application creation options (canvas, backend, and optional runtime/device settings).\r\n */\r\n constructor(opt: AppCreationOptions) {\r\n super();\r\n if (getApp()) {\r\n throw new Error('It is not allowed to have multiple Application instances');\r\n }\r\n setApp(this);\r\n\r\n this._options = {\r\n backend: opt.backend,\r\n enableMSAA: opt.enableMSAA ?? false,\r\n pixelRatio: opt.pixelRatio ?? window.devicePixelRatio ?? 1,\r\n canvas: opt.canvas\r\n };\r\n this._inputManager = new InputManager(this);\r\n this._engine = new Engine(\r\n opt.runtimeOptions?.VFS,\r\n opt.runtimeOptions?.scriptsRoot,\r\n opt.runtimeOptions?.enabled\r\n );\r\n if (opt.runtimeOptions?.screen) {\r\n this._engine.screen.config = opt.runtimeOptions.screen;\r\n }\r\n this._editorMode = opt.runtimeOptions?.editorMode ?? 'none';\r\n this._device = null;\r\n this._ready = false;\r\n this._frameWaiters = [];\r\n }\r\n /**\r\n * Editor mode\r\n */\r\n get editorMode() {\r\n return this._editorMode;\r\n }\r\n /**\r\n * The input manager instance handling pointer/keyboard event routing.\r\n */\r\n get inputManager() {\r\n return this._inputManager;\r\n }\r\n /**\r\n * Get the instanceof {@link Engine}.\r\n */\r\n get engine() {\r\n return this._engine;\r\n }\r\n /**\r\n * The (sanitized) options used to create this application.\r\n *\r\n * Note: Defaults are applied for `enableMSAA` and `pixelRatio` if omitted.\r\n */\r\n get options() {\r\n return this._options;\r\n }\r\n /**\r\n * The initialized rendering device.\r\n *\r\n * Available after `await ready()`.\r\n */\r\n get device() {\r\n return this._device!;\r\n }\r\n /**\r\n * Convenience accessor for the device type name provided by the backend.\r\n */\r\n get deviceType() {\r\n return this._options.backend.typeName();\r\n }\r\n /**\r\n * Set keyboard focus to the device's canvas element.\r\n */\r\n focus() {\r\n this._device!.canvas.focus();\r\n }\r\n /**\r\n * Initialize the rendering device and start input processing.\r\n *\r\n * @throws If device creation fails.\r\n */\r\n async ready() {\r\n if (!this._ready) {\r\n this._device = await this._options.backend.createDevice(this._options.canvas, {\r\n dpr: this._options.pixelRatio,\r\n msaa: !!this._options.enableMSAA\r\n });\r\n if (!this._device) {\r\n throw new Error('App.init(): create device failed');\r\n }\r\n this._device.canvas.focus();\r\n await this._engine.init();\r\n this._inputManager.start();\r\n this._device.on('resize', (width, height) => {\r\n this._engine.screen.resolveViewport();\r\n this.dispatchEvent('resize', width, height);\r\n });\r\n this._ready = true;\r\n }\r\n }\r\n /**\r\n * Render a single frame.\r\n *\r\n * Steps:\r\n * - Flushes pending disposals from the previous frame.\r\n * - Clears device state (framebuffer, viewport, scissor).\r\n * - Queries frame timing from the device (`elapsedFrame`, `elapsedOverall`).\r\n * - Starts a new input frame: input state, gamepads and action maps.\r\n * - Updates the runtime manager (scripting/behaviors).\r\n * - Emits `tick` with delta/elapsed times.\r\n *\r\n * Safe to call manually; also used by the run loop.\r\n */\r\n frame() {\r\n // Processes all pending disposals from the previous frame.\r\n flushPendingDisposals();\r\n if (this._ready) {\r\n this.device.setFramebuffer(null);\r\n this.device.setViewport(null);\r\n this.device.setScissor(null);\r\n const dt = this.device.frameInfo.elapsedFrame;\r\n const elapsed = this.device.frameInfo.elapsedOverall;\r\n this._inputManager._beginFrame(dt * 0.001);\r\n this.dispatchEvent('tick', dt, elapsed);\r\n this._engine.update(dt * 0.001, elapsed * 0.001);\r\n this._engine.render();\r\n if (this._frameWaiters.length > 0) {\r\n // Resolution callbacks run as microtasks, after the caller's endFrame()\r\n const waiters = this._frameWaiters;\r\n this._frameWaiters = [];\r\n waiters.forEach((resolve) => resolve());\r\n }\r\n }\r\n }\r\n /**\r\n * Waits for the next frame to be rendered.\r\n *\r\n * @remarks\r\n * Resolves once the next call to {@link Application.frame} has rendered every\r\n * active layer and the frame has been ended, so what was set up before calling\r\n * this is on screen when the promise settles. Use it to hide a loading overlay\r\n * only after the first frame of a scene has been drawn.\r\n *\r\n * Never resolves while no frame is rendered (run loop not started, or the\r\n * device skips frames because the rendering context is lost).\r\n */\r\n nextFrame(): Promise<void> {\r\n return new Promise((resolve) => {\r\n this._frameWaiters.push(resolve);\r\n });\r\n }\r\n /**\r\n * Advances exactly one frame outside the run loop.\r\n *\r\n * @remarks\r\n * Uses the same `beginFrame()`/`frame()`/`endFrame()` sequence as the run\r\n * loop, so per-frame non-idempotent state (history buffer ping-pong, frame\r\n * counter, motion vector matrices) advances exactly once. Must not be called\r\n * while the run loop started by {@link Application.run} is active.\r\n *\r\n * @returns true if the frame was rendered; false if the device skipped it\r\n * (e.g. the rendering context is lost).\r\n */\r\n stepFrame(): boolean {\r\n if (this.device.isRendering) {\r\n console.error('Application.stepFrame(): can not be called while the run loop is active');\r\n return false;\r\n }\r\n if (this.device.beginFrame()) {\r\n this.frame();\r\n this.device.endFrame();\r\n return true;\r\n }\r\n return false;\r\n }\r\n /**\r\n * Start the application's render loop.\r\n *\r\n * Uses the device's internal scheduling (`device.runLoop`) to repeatedly call `frame()`.\r\n */\r\n run() {\r\n this.device.runLoop(() => {\r\n this.frame();\r\n });\r\n }\r\n /**\r\n * Stop the application's render loop.\r\n *\r\n * Uses `device.exitLoop()` to end the scheduling started by `run()`.\r\n */\r\n stop() {\r\n this.device.exitLoop();\r\n }\r\n}\r\n"],"names":["Application","Observable","_options","_device","_inputManager","_engine","_editorMode","_ready","_frameWaiters","opt","getApp","Error","setApp","backend","enableMSAA","pixelRatio","window","devicePixelRatio","canvas","InputManager","Engine","runtimeOptions","VFS","scriptsRoot","enabled","screen","config","editorMode","inputManager","engine","options","device","deviceType","typeName","focus","ready","createDevice","dpr","msaa","init","start","on","width","height","resolveViewport","dispatchEvent","frame","flushPendingDisposals","setFramebuffer","setViewport","setScissor","dt","frameInfo","elapsedFrame","elapsed","elapsedOverall","_beginFrame","update","render","length","waiters","forEach","resolve","nextFrame","Promise","push","stepFrame","isRendering","console","error","beginFrame","endFrame","run","runLoop","stop","exitLoop"],"mappings":"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"}
|
package/dist/app/engine.js
CHANGED
|
@@ -2,6 +2,7 @@ import { HttpFS, DRef, MemoryFS, objectEntries } from '@zephyr3d/base';
|
|
|
2
2
|
import { ScriptingSystem, createDeclarativeScriptSignature } from './scriptingsystem.js';
|
|
3
3
|
import { ResourceManager } from '../utility/serialization/manager.js';
|
|
4
4
|
import '../render/primitive.js';
|
|
5
|
+
import '../node_modules/meshoptimizer/meshopt_simplifier.js';
|
|
5
6
|
import { BoxShape } from '../shapes/box.js';
|
|
6
7
|
import { CapsuleShape } from '../shapes/capsule.js';
|
|
7
8
|
import { CylinderShape } from '../shapes/cylinder.js';
|
|
@@ -13,13 +14,14 @@ import '../material/shader/helper.js';
|
|
|
13
14
|
import { LambertMaterial } from '../material/lambert.js';
|
|
14
15
|
import { BlinnMaterial } from '../material/blinn.js';
|
|
15
16
|
import { UnlitMaterial } from '../material/unlit.js';
|
|
17
|
+
import '../material/meshmaterial.js';
|
|
16
18
|
import '../material/particle.js';
|
|
17
19
|
import '../material/subsurfaceprofile.js';
|
|
18
|
-
import
|
|
20
|
+
import '../material/sssprofile.js';
|
|
21
|
+
import { SSSMaterial } from '../material/sss.js';
|
|
19
22
|
import { EyeMaterial } from '../material/eye.js';
|
|
20
23
|
import '@zephyr3d/device';
|
|
21
24
|
import '../values.js';
|
|
22
|
-
import '../material/meshmaterial.js';
|
|
23
25
|
import { HairMaterial } from '../material/hair.js';
|
|
24
26
|
import '../material/hairstrand.js';
|
|
25
27
|
import '../material/grassmaterial.js';
|
|
@@ -32,7 +34,10 @@ import '../material/sprite.js';
|
|
|
32
34
|
import { StandardSpriteMaterial } from '../material/sprite_std.js';
|
|
33
35
|
import '../utility/blueprint/material/texture.js';
|
|
34
36
|
import { ScreenAdapter } from './screen.js';
|
|
37
|
+
import { PipelineCacheManager } from './pipelinecache.js';
|
|
38
|
+
import { AssetPreloader } from '../asset/asset_preload.js';
|
|
35
39
|
import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js';
|
|
40
|
+
import { readAssetManifest, createManifestSourceResolver, ASSET_MANIFEST_FILE } from '../asset/asset_manifest.js';
|
|
36
41
|
|
|
37
42
|
/**
|
|
38
43
|
* Core engine class managing scripting, serialization, and rendering.
|
|
@@ -57,6 +62,9 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
57
62
|
_msdfTextAtlasManager;
|
|
58
63
|
_enabled;
|
|
59
64
|
_screen;
|
|
65
|
+
_pipelineCache;
|
|
66
|
+
_assetPreloader;
|
|
67
|
+
/** Resolver this engine installed from a build's asset manifest */ _manifestResolver = null;
|
|
60
68
|
_activeRenderables;
|
|
61
69
|
_loadingScenes;
|
|
62
70
|
/**
|
|
@@ -78,6 +86,8 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
78
86
|
this._activeRenderables = [];
|
|
79
87
|
this._loadingScenes = {};
|
|
80
88
|
this._screen = new ScreenAdapter();
|
|
89
|
+
this._pipelineCache = new PipelineCacheManager(()=>this.VFS);
|
|
90
|
+
this._assetPreloader = new AssetPreloader(()=>this.VFS, ()=>this._resourceManager.assetManager);
|
|
81
91
|
}
|
|
82
92
|
/**
|
|
83
93
|
* Exposes the instance of {@link ScriptingSystem}.
|
|
@@ -95,7 +105,38 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
95
105
|
this._resourceManager.VFS = vfs;
|
|
96
106
|
this._scriptingSystem.registry.VFS = vfs;
|
|
97
107
|
this.ensureBuiltinVFS();
|
|
108
|
+
// A manifest belongs to the file system it was read from
|
|
109
|
+
const assetManager = this._resourceManager.assetManager;
|
|
110
|
+
if (this._manifestResolver && assetManager.assetSourceResolver === this._manifestResolver) {
|
|
111
|
+
assetManager.assetSourceResolver = null;
|
|
112
|
+
this._manifestResolver = null;
|
|
113
|
+
void this.loadAssetManifest();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reads the asset manifest of a build (`/asset-manifest.json`, written by the
|
|
119
|
+
* editor's build) from the engine's VFS and routes the assets it lists to the
|
|
120
|
+
* compressed copies shipped for them, so code loading `/assets/rock.png` gets
|
|
121
|
+
* `/assets/rock.<hash>.ktx2`. Called by {@link Engine.init}, so a project using
|
|
122
|
+
* the editor's asset pipeline with its own code needs no setup; call it again
|
|
123
|
+
* with another path for a manifest kept elsewhere.
|
|
124
|
+
*
|
|
125
|
+
* A resolver installed by someone else (the editor installs its own) is left
|
|
126
|
+
* in place.
|
|
127
|
+
*
|
|
128
|
+
* @param path - VFS path of the manifest
|
|
129
|
+
* @returns true if a manifest was found and is now in use
|
|
130
|
+
*/ async loadAssetManifest(path = `/${ASSET_MANIFEST_FILE}`) {
|
|
131
|
+
const vfs = this.VFS;
|
|
132
|
+
const manifest = await readAssetManifest(vfs, path);
|
|
133
|
+
const assetManager = this._resourceManager.assetManager;
|
|
134
|
+
if (vfs !== this.VFS || assetManager.assetSourceResolver && assetManager.assetSourceResolver !== this._manifestResolver) {
|
|
135
|
+
return false;
|
|
98
136
|
}
|
|
137
|
+
this._manifestResolver = manifest ? createManifestSourceResolver(vfs, manifest) : null;
|
|
138
|
+
assetManager.assetSourceResolver = this._manifestResolver;
|
|
139
|
+
return !!manifest;
|
|
99
140
|
}
|
|
100
141
|
/**
|
|
101
142
|
* Exposes the instance of {@link ResourceManager}.
|
|
@@ -153,8 +194,21 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
153
194
|
*/ get screen() {
|
|
154
195
|
return this._screen;
|
|
155
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Reads pipeline cache files and compiles the pipelines they record ahead of time.
|
|
199
|
+
* The engine never calls it by itself.
|
|
200
|
+
*/ get pipelineCache() {
|
|
201
|
+
return this._pipelineCache;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Loads assets ahead of time from requests recorded while scenes were loaded.
|
|
205
|
+
* The engine never calls it by itself.
|
|
206
|
+
*/ get assetPreloader() {
|
|
207
|
+
return this._assetPreloader;
|
|
208
|
+
}
|
|
156
209
|
/** @internal */ async init() {
|
|
157
210
|
await this.ensureBuiltinVFS();
|
|
211
|
+
await this.loadAssetManifest();
|
|
158
212
|
}
|
|
159
213
|
/**
|
|
160
214
|
* Detaches all scripts from all hosts, if enabled.
|
|
@@ -240,6 +294,28 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
240
294
|
}
|
|
241
295
|
}
|
|
242
296
|
/**
|
|
297
|
+
* Calls the `onFixedUpdate` hooks of scripts, if enabled. Driven by a physics
|
|
298
|
+
* world before each of its fixed steps.
|
|
299
|
+
*
|
|
300
|
+
* @param fixedDeltaTime - Length of the step in seconds.
|
|
301
|
+
* @param filter - Only scripts whose host passes are called.
|
|
302
|
+
*/ fixedUpdate(fixedDeltaTime, filter) {
|
|
303
|
+
if (this._enabled) {
|
|
304
|
+
this._scriptingSystem.fixedUpdate(fixedDeltaTime, filter);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Calls the `onLateUpdate` hooks of scripts, if enabled. Driven by a scene once
|
|
309
|
+
* per frame, after its physics world has stepped.
|
|
310
|
+
*
|
|
311
|
+
* @param deltaTime - Time since last frame in seconds.
|
|
312
|
+
* @param filter - Only scripts whose host passes are called.
|
|
313
|
+
*/ lateUpdate(deltaTime, filter) {
|
|
314
|
+
if (this._enabled) {
|
|
315
|
+
this._scriptingSystem.lateUpdate(deltaTime, filter);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
243
319
|
* Loads a scene from a file path.
|
|
244
320
|
*
|
|
245
321
|
* Concurrent requests for the same normalized path share the same loading promise.
|
|
@@ -304,21 +380,17 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
304
380
|
}
|
|
305
381
|
}
|
|
306
382
|
/**
|
|
307
|
-
* Starts the runtime by
|
|
308
|
-
*
|
|
383
|
+
* Starts the runtime by running a startup script and loading the startup scene.
|
|
384
|
+
*
|
|
385
|
+
* @remarks
|
|
386
|
+
* A loading screen covering the startup belongs to the page (an HTML overlay shown
|
|
387
|
+
* before any script loads): hide it once this resolves and
|
|
388
|
+
* {@link Application.nextFrame} reports the startup scene drawn.
|
|
309
389
|
*
|
|
310
390
|
* @param startupScene - Optional scene path rendered on layer `0` after startup completes.
|
|
311
|
-
* @param splashScreen - Optional scene path rendered on a temporary splash layer during startup.
|
|
312
391
|
* @param startupScript - Optional startup script module path. A trailing `.ts` or `.js`
|
|
313
392
|
* extension is removed before loading.
|
|
314
|
-
*/ async startup(startupScene,
|
|
315
|
-
const splashScreenLayer = 9999;
|
|
316
|
-
if (splashScreen) {
|
|
317
|
-
const splashScreenScene = await this.loadSceneFromFile(splashScreen);
|
|
318
|
-
if (splashScreenScene) {
|
|
319
|
-
this.setRenderable(splashScreenScene, splashScreenLayer);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
393
|
+
*/ async startup(startupScene, startupScript) {
|
|
322
394
|
if (startupScript) {
|
|
323
395
|
const path = startupScript.toLowerCase().endsWith('.ts') || startupScript.toLowerCase().endsWith('.js') ? startupScript.slice(0, -3) : startupScript;
|
|
324
396
|
await this.attachScript(null, path);
|
|
@@ -327,7 +399,6 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
327
399
|
const scene = await this.loadSceneFromFile(startupScene);
|
|
328
400
|
this.setRenderable(scene, 0);
|
|
329
401
|
}
|
|
330
|
-
this.setRenderable(null, splashScreenLayer);
|
|
331
402
|
}
|
|
332
403
|
/**
|
|
333
404
|
* Renders all active render layers.
|
|
@@ -375,7 +446,7 @@ import { MSDFTextAtlasManager } from '../text/runtime/msdf_text_atlas_manager.js
|
|
|
375
446
|
'/materials/pbr_metallic_roughness.zmtl': PBRMetallicRoughnessMaterial,
|
|
376
447
|
'/materials/pbr_specular_glossiness.zmtl': PBRSpecularGlossinessMaterial,
|
|
377
448
|
'/materials/sprite_std.zmtl': StandardSpriteMaterial,
|
|
378
|
-
'/materials/
|
|
449
|
+
'/materials/sss.zmtl': SSSMaterial,
|
|
379
450
|
'/materials/hair.zmtl': HairMaterial,
|
|
380
451
|
'/materials/eye.zmtl': EyeMaterial
|
|
381
452
|
};
|
package/dist/app/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 { createDeclarativeScriptSignature, 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, SceneNode } 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 EyeMaterial,\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 { SkinMaterial } from '../material/skin';\r\nimport { HairMaterial } from '../material/hair';\r\nimport { ScreenAdapter } from './screen';\r\nimport { MSDFTextAtlasManager } from '../text/runtime';\r\n\r\n/**\r\n * Interface for objects that can be rendered.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderable extends IDisposable {\r\n render(): void;\r\n}\r\n\r\n/**\r\n * Type for render functions that can be registered as renderables.\r\n *\r\n * @public\r\n */\r\nexport type RenderFunc = () => void;\r\n\r\n/**\r\n * Interface for render hooks to customize rendering behavior.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderHook {\r\n // If presents, called before rendering the renderable. Return `false` to skip rendering.\r\n beforeRender?: (renderable: any) => boolean | void;\r\n // If presents, called after rendering the renderable.\r\n afterRender?: (renderable: any) => void;\r\n}\r\n\r\n/**\r\n * Core engine class managing scripting, serialization, and rendering.\r\n *\r\n * Responsibilities:\r\n * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.\r\n * - Manages a {@link ResourceManager} for loading scenes and assets.\r\n * - Maintains a list of active renderable objects to be rendered each frame.\r\n * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.\r\n * - Supports enabling/disabling of runtime operations.\r\n *\r\n * @remarks\r\n * The engine can be configured with a virtual file system (VFS) and script root path.\r\n * It exposes methods to manage scripts on host objects, update scripts each frame,\r\n * load scenes from files, and render active objects.\r\n *\r\n * @public\r\n */\r\nexport class Engine {\r\n private _builtinsVFS: Nullable<MemoryFS>;\r\n private _scriptingSystem: ScriptingSystem;\r\n private _resourceManager: ResourceManager;\r\n private _msdfTextAtlasManager: MSDFTextAtlasManager;\r\n private _enabled: boolean;\r\n private _screen: ScreenAdapter;\r\n protected _activeRenderables: {\r\n renderable: Nullable<RenderFunc> | DRef<IRenderable>;\r\n hook: Nullable<IRenderHook>;\r\n }[];\r\n private _loadingScenes: Partial<Record<string, Promise<Nullable<Scene>>>>;\r\n /**\r\n * Creates a new runtime manager.\r\n *\r\n * @param VFS - Optional virtual file system passed to the internal {@link ScriptingSystem}.\r\n * @param scriptsRoot - Optional scripts root path within the VFS. Defaults as in `ScriptingSystem`.\r\n * @param enabled - Whether runtime operations are active. Defaults to `true`.\r\n */\r\n constructor(VFS?: VFS, scriptsRoot?: string, enabled?: boolean) {\r\n VFS = VFS ?? new HttpFS('./');\r\n this._builtinsVFS = null;\r\n this._scriptingSystem = new ScriptingSystem({ VFS, scriptsRoot });\r\n this._resourceManager = new ResourceManager(VFS);\r\n this._msdfTextAtlasManager = new MSDFTextAtlasManager();\r\n this._enabled = enabled ?? true;\r\n this._activeRenderables = [];\r\n this._loadingScenes = {};\r\n this._screen = new ScreenAdapter();\r\n }\r\n /**\r\n * Exposes the instance of {@link ScriptingSystem}.\r\n */\r\n get scriptingSystem() {\r\n return this._scriptingSystem;\r\n }\r\n /**\r\n * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.\r\n */\r\n get VFS() {\r\n return this._scriptingSystem.registry.VFS;\r\n }\r\n set VFS(vfs: VFS) {\r\n if (vfs !== this._resourceManager.VFS) {\r\n this._resourceManager.VFS?.close();\r\n this._resourceManager.VFS = vfs;\r\n this._scriptingSystem.registry.VFS = vfs;\r\n this.ensureBuiltinVFS();\r\n }\r\n }\r\n /**\r\n * Exposes the instance of {@link ResourceManager}.\r\n */\r\n get resourceManager() {\r\n return this._resourceManager;\r\n }\r\n /**\r\n * Exposes the shared runtime MSDF text atlas manager.\r\n */\r\n get msdfTextAtlasManager() {\r\n return this._msdfTextAtlasManager;\r\n }\r\n /**\r\n * Releases a loaded font asset from the resource cache and disposes its shared MSDF atlas textures.\r\n *\r\n * Existing scene nodes that still reference this font asset are not updated automatically.\r\n * Call this only after you have stopped using the font, or when you intentionally want it to rebuild later.\r\n *\r\n * @param font - The loaded font asset path to release.\r\n * @returns `true` if either the atlas cache or the font cache had an entry to remove.\r\n */\r\n releaseFontAsset(font: string) {\r\n const fontAsset = this._resourceManager.getFontAsset(font);\r\n if (!fontAsset) {\r\n return false;\r\n }\r\n const atlasReleased = this._msdfTextAtlasManager.releaseAtlas(fontAsset);\r\n const fontReleased = this._resourceManager.releaseFontAsset(fontAsset);\r\n return atlasReleased || fontReleased;\r\n }\r\n /**\r\n * Configures the MSDF atlas for a given font asset, creating or replacing the atlas as needed.\r\n *\r\n * This is useful to customize the glyph size, atlas page size, distance range, and padding for MSDF text rendering.\r\n * Existing scene nodes that reference this font asset will use the updated atlas automatically.\r\n *\r\n * @param font - The font asset path to configure the MSDF atlas for.\r\n * @param pageSize - The size of each atlas page in pixels (e.g., 512, 1024).\r\n * @param glyphSize - The size of each glyph in pixels (e.g., 32, 64).\r\n * @param distanceRange - The distance range for MSDF generation. Defaults to 4.\r\n * @param padding - The padding between glyphs in the atlas in pixels. Defaults to 2.\r\n * @returns `true` if the atlas was successfully configured, or `false` if the font asset was not found.\r\n *\r\n * @remarks\r\n * The font asset must be loaded and available in the resource manager for the atlas to be configured.\r\n */\r\n configureMSDFAtlas(\r\n font: string,\r\n pageSize: number,\r\n glyphSize: number,\r\n distanceRange?: number,\r\n padding?: number\r\n ) {\r\n const fontAsset = this._resourceManager.getFontAsset(font);\r\n if (!fontAsset) {\r\n console.warn(`Font asset '${font}' not found for MSDF atlas configuration.`);\r\n return false;\r\n }\r\n this._msdfTextAtlasManager.configureAtlas(fontAsset, pageSize, glyphSize, distanceRange, padding);\r\n return true;\r\n }\r\n /**\r\n * Exposes the active {@link ScreenAdapter}.\r\n */\r\n get screen() {\r\n return this._screen;\r\n }\r\n /** @internal */\r\n async init() {\r\n await this.ensureBuiltinVFS();\r\n }\r\n /**\r\n * Detaches all scripts from all hosts, if enabled.\r\n *\r\n * No-op when `enabled === false`.\r\n */\r\n detachAllScripts() {\r\n if (this._enabled) {\r\n this._scriptingSystem.detachAllScripts();\r\n }\r\n }\r\n /**\r\n * Loads a runtime script class from file\r\n * @param module - file path\r\n * @returns The runtime script class or null\r\n */\r\n async loadRuntimeScriptClass<T extends Host = Host>(\r\n module: string\r\n ): Promise<Nullable<{ url: string; cls: GenericConstructor<RuntimeScript<T>> }>> {\r\n return await this._scriptingSystem.loadRuntimeScriptClass(module);\r\n }\r\n /**\r\n * Attaches a script module to the given host, if enabled.\r\n *\r\n * When disabled, this method resolves to `null` without side effects.\r\n *\r\n * @typeParam T - Host type.\r\n * @param host - Host object to attach the script to.\r\n * @param module - Module identifier to resolve and load.\r\n * @param config - Optional configuration passed to the script instance.\r\n * @returns The `RuntimeScript<T>` instance, or `null` if disabled or on failure.\r\n */\r\n async attachScript<T extends Host>(\r\n host: Nullable<T>,\r\n module: string,\r\n config?: Nullable<RuntimeScriptConfig>\r\n ) {\r\n return this._enabled ? await this._scriptingSystem.attachScript(host, module, config) : null;\r\n }\r\n /**\r\n * Attaches all serialized script declarations on a scene node subtree.\r\n *\r\n * The operation is explicit and idempotent. Repeated or concurrent calls reuse\r\n * instances already attached for the same declaration, while duplicate declarations\r\n * within one host remain distinct.\r\n *\r\n * @param root - Root node whose own declarations and descendants are processed.\r\n * @returns Script instances in host/declaration order. Failed declarations are omitted.\r\n */\r\n async attachScriptsInSubtree(root: SceneNode) {\r\n if (!this._enabled) {\r\n return [];\r\n }\r\n const nodes: SceneNode[] = [];\r\n root.iterate((node) => {\r\n nodes.push(node);\r\n });\r\n const results = await Promise.all(nodes.map((node) => this.attachDeclaredScripts(node)));\r\n return results.flat();\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 '/materials/skin.zmtl': SkinMaterial,\r\n '/materials/hair.zmtl': HairMaterial,\r\n '/materials/eye.zmtl': EyeMaterial\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 await this.attachDeclaredScripts(scene);\r\n await this.attachScriptsInSubtree(scene.rootNode);\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 private async attachDeclaredScripts<\r\n T extends Host & {\r\n scripts: { script: string; config: unknown }[];\r\n script: string;\r\n scriptConfig: unknown;\r\n }\r\n >(host: T) {\r\n const attachments =\r\n host.scripts.length > 0\r\n ? host.scripts\r\n : host.script\r\n ? [{ script: host.script, config: host.scriptConfig }]\r\n : [];\r\n const occurrences = new Map<string, number>();\r\n const declarationKeys = new Set<string>();\r\n const requests = attachments\r\n .filter((attachment) => !!attachment.script)\r\n .map((attachment) => {\r\n const config = (attachment.config ?? null) as RuntimeScriptConfig | null;\r\n const signature = createDeclarativeScriptSignature(attachment.script, config);\r\n const occurrence = occurrences.get(signature) ?? 0;\r\n occurrences.set(signature, occurrence + 1);\r\n declarationKeys.add(`${signature}\\n${occurrence}`);\r\n return this._scriptingSystem\r\n .attachDeclarativeScript(host, attachment.script, config, occurrence)\r\n .catch((err) => {\r\n console.error(`Attach script '${attachment.script}' failed: ${err}`);\r\n return null;\r\n });\r\n });\r\n this._scriptingSystem.synchronizeDeclarativeScripts(host, declarationKeys);\r\n const instances = await Promise.all(requests);\r\n return instances.filter((instance): instance is RuntimeScript<T> => !!instance);\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","attachScriptsInSubtree","root","nodes","iterate","node","push","results","Promise","all","map","attachDeclaredScripts","flat","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","SkinMaterial","HairMaterial","EyeMaterial","key","objectEntries","obj","writeSerializableObject","readOnly","type","data","serializeObject","JSON","stringify","writeFile","create","loadScene","rootNode","attachments","scripts","length","script","scriptConfig","occurrences","Map","declarationKeys","Set","requests","filter","attachment","signature","createDeclarativeScriptSignature","occurrence","set","add","attachDeclarativeScript","catch","synchronizeDeclarativeScripts","instances","instance"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA;;;;;;;;;;;;;;;;AAgBC,IACM,MAAMA,MAAAA,CAAAA;IACHC,YAAiC;IACjCC,gBAAkC;IAClCC,gBAAkC;IAClCC,qBAA4C;IAC5CC,QAAkB;IAClBC,OAAuB;IACrBC,kBAGN;IACIC,cAAkE;AAC1E;;;;;;AAMC,MACD,YAAYC,GAAS,EAAEC,WAAoB,EAAEC,OAAiB,CAAE;QAC9DF,GAAMA,GAAAA,GAAAA,IAAO,IAAIG,MAAO,CAAA,IAAA,CAAA;QACxB,IAAI,CAACX,YAAY,GAAG,IAAA;AACpB,QAAA,IAAI,CAACC,gBAAgB,GAAG,IAAIW,eAAgB,CAAA;AAAEJ,YAAAA,GAAAA;AAAKC,YAAAA;AAAY,SAAA,CAAA;AAC/D,QAAA,IAAI,CAACP,gBAAgB,GAAG,IAAIW,eAAgBL,CAAAA,GAAAA,CAAAA;QAC5C,IAAI,CAACL,qBAAqB,GAAG,IAAIW,oBAAAA,EAAAA;QACjC,IAAI,CAACV,QAAQ,GAAGM,OAAW,IAAA,IAAA;QAC3B,IAAI,CAACJ,kBAAkB,GAAG,EAAE;QAC5B,IAAI,CAACC,cAAc,GAAG,EAAC;QACvB,IAAI,CAACF,OAAO,GAAG,IAAIU,aAAAA,EAAAA;AACrB;AACA;;AAEC,MACD,IAAIC,eAAkB,GAAA;QACpB,OAAO,IAAI,CAACf,gBAAgB;AAC9B;AACA;;AAEC,MACD,IAAIO,GAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAACP,gBAAgB,CAACgB,QAAQ,CAACT,GAAG;AAC3C;IACA,IAAIA,GAAAA,CAAIU,GAAQ,EAAE;AAChB,QAAA,IAAIA,QAAQ,IAAI,CAAChB,gBAAgB,CAACM,GAAG,EAAE;AACrC,YAAA,IAAI,CAACN,gBAAgB,CAACM,GAAG,EAAEW,KAAAA,EAAAA;AAC3B,YAAA,IAAI,CAACjB,gBAAgB,CAACM,GAAG,GAAGU,GAAAA;AAC5B,YAAA,IAAI,CAACjB,gBAAgB,CAACgB,QAAQ,CAACT,GAAG,GAAGU,GAAAA;AACrC,YAAA,IAAI,CAACE,gBAAgB,EAAA;AACvB;AACF;AACA;;AAEC,MACD,IAAIC,eAAkB,GAAA;QACpB,OAAO,IAAI,CAACnB,gBAAgB;AAC9B;AACA;;AAEC,MACD,IAAIoB,oBAAuB,GAAA;QACzB,OAAO,IAAI,CAACnB,qBAAqB;AACnC;AACA;;;;;;;;MASAoB,gBAAAA,CAAiBC,IAAY,EAAE;AAC7B,QAAA,MAAMC,YAAY,IAAI,CAACvB,gBAAgB,CAACwB,YAAY,CAACF,IAAAA,CAAAA;AACrD,QAAA,IAAI,CAACC,SAAW,EAAA;YACd,OAAO,KAAA;AACT;AACA,QAAA,MAAME,gBAAgB,IAAI,CAACxB,qBAAqB,CAACyB,YAAY,CAACH,SAAAA,CAAAA;AAC9D,QAAA,MAAMI,eAAe,IAAI,CAAC3B,gBAAgB,CAACqB,gBAAgB,CAACE,SAAAA,CAAAA;AAC5D,QAAA,OAAOE,aAAiBE,IAAAA,YAAAA;AAC1B;AACA;;;;;;;;;;;;;;;MAgBAC,kBAAAA,CACEN,IAAY,EACZO,QAAgB,EAChBC,SAAiB,EACjBC,aAAsB,EACtBC,OAAgB,EAChB;AACA,QAAA,MAAMT,YAAY,IAAI,CAACvB,gBAAgB,CAACwB,YAAY,CAACF,IAAAA,CAAAA;AACrD,QAAA,IAAI,CAACC,SAAW,EAAA;AACdU,YAAAA,OAAAA,CAAQC,IAAI,CAAC,CAAC,YAAY,EAAEZ,IAAAA,CAAK,yCAAyC,CAAC,CAAA;YAC3E,OAAO,KAAA;AACT;QACA,IAAI,CAACrB,qBAAqB,CAACkC,cAAc,CAACZ,SAAWM,EAAAA,QAAAA,EAAUC,WAAWC,aAAeC,EAAAA,OAAAA,CAAAA;QACzF,OAAO,IAAA;AACT;AACA;;AAEC,MACD,IAAII,MAAS,GAAA;QACX,OAAO,IAAI,CAACjC,OAAO;AACrB;qBAEA,MAAMkC,IAAO,GAAA;QACX,MAAM,IAAI,CAACnB,gBAAgB,EAAA;AAC7B;AACA;;;;AAIC,MACDoB,gBAAmB,GAAA;QACjB,IAAI,IAAI,CAACpC,QAAQ,EAAE;YACjB,IAAI,CAACH,gBAAgB,CAACuC,gBAAgB,EAAA;AACxC;AACF;AACA;;;;MAKA,MAAMC,sBACJC,CAAAA,MAAc,EACiE;AAC/E,QAAA,OAAO,MAAM,IAAI,CAACzC,gBAAgB,CAACwC,sBAAsB,CAACC,MAAAA,CAAAA;AAC5D;AACA;;;;;;;;;;AAUC,MACD,MAAMC,YACJC,CAAAA,IAAiB,EACjBF,MAAc,EACdG,MAAsC,EACtC;AACA,QAAA,OAAO,IAAI,CAACzC,QAAQ,GAAG,MAAM,IAAI,CAACH,gBAAgB,CAAC0C,YAAY,CAACC,IAAAA,EAAMF,QAAQG,MAAU,CAAA,GAAA,IAAA;AAC1F;AACA;;;;;;;;;MAUA,MAAMC,sBAAuBC,CAAAA,IAAe,EAAE;AAC5C,QAAA,IAAI,CAAC,IAAI,CAAC3C,QAAQ,EAAE;AAClB,YAAA,OAAO,EAAE;AACX;AACA,QAAA,MAAM4C,QAAqB,EAAE;QAC7BD,IAAKE,CAAAA,OAAO,CAAC,CAACC,IAAAA,GAAAA;AACZF,YAAAA,KAAAA,CAAMG,IAAI,CAACD,IAAAA,CAAAA;AACb,SAAA,CAAA;AACA,QAAA,MAAME,OAAU,GAAA,MAAMC,OAAQC,CAAAA,GAAG,CAACN,KAAAA,CAAMO,GAAG,CAAC,CAACL,IAAAA,GAAS,IAAI,CAACM,qBAAqB,CAACN,IAAAA,CAAAA,CAAAA,CAAAA;AACjF,QAAA,OAAOE,QAAQK,IAAI,EAAA;AACrB;AACA;;;;;;;;AAQC,MACDC,YAA6Bd,CAAAA,IAAO,EAAEe,YAAuC,EAAE;QAC7E,IAAI,IAAI,CAACvD,QAAQ,EAAE;AACjB,YAAA,IAAI,CAACH,gBAAgB,CAACyD,YAAY,CAACd,IAAMe,EAAAA,YAAAA,CAAAA;AAC3C;AACF;AACA;;;;;;;;MASAC,gBAAAA,CAA+ChB,IAAa,EAAE;AAC5D,QAAA,OAAO,IAAI,CAAC3C,gBAAgB,CAAC2D,gBAAgB,CAAChB,IAAAA,CAAAA;AAChD;AACA;;;;;AAKC,MACDiB,MAAOC,CAAAA,SAAiB,EAAEC,WAAmB,EAAE;QAC7C,IAAI,IAAI,CAAC3D,QAAQ,EAAE;AACjB,YAAA,IAAI,CAACH,gBAAgB,CAAC4D,MAAM,CAACC,SAAWC,EAAAA,WAAAA,CAAAA;AAC1C;AACF;AACA;;;;;;;;MASA,MAAMC,iBAAkBC,CAAAA,IAAY,EAAE;AACpCA,QAAAA,IAAAA,GAAO,IAAI,CAACzD,GAAG,CAAC0D,aAAa,CAACD,IAAAA,CAAAA;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC1D,cAAc,CAAC0D,KAAK,EAAE;YAC9B,IAAI,CAAC1D,cAAc,CAAC0D,IAAAA,CAAK,GAAG,IAAI,CAACE,UAAU,CAACF,IAAAA,CAAAA;AAC9C;AACA,QAAA,OAAO,IAAI,CAAC1D,cAAc,CAAC0D,IAAK,CAAA;AAClC;AACA;;;;;;;;;AASC,MACDG,cAAcC,UAA8C,EAAEC,QAAQ,CAAC,EAAEC,IAAkB,EAAE;AAC3F,QAAA,MAAMC,KAAQ,GAAA,IAAI,CAAClE,kBAAkB,CAACgE,KAAM,CAAA;AAC5C,QAAA,IAAI,CAACE,KAAO,EAAA;AACV,YAAA,IAAI,CAAClE,kBAAkB,CAACgE,KAAAA,CAAM,GAAG;AAC/BD,gBAAAA,UAAAA,EAAYA,aACR,OAAOA,UAAAA,KAAe,aACpBA,UACA,GAAA,IAAII,KAAkBJ,UACxB,CAAA,GAAA,IAAA;AACJE,gBAAAA,IAAAA,EAAMA,IAAQ,IAAA;AAChB,aAAA;SACK,MAAA;YACL,IAAIC,KAAAA,CAAMH,UAAU,EAAE;gBACpB,IAAIG,KAAAA,CAAMH,UAAU,YAAYI,IAAM,EAAA;oBACpCD,KAAMH,CAAAA,UAAU,CAACK,OAAO,EAAA;AAC1B;AACAF,gBAAAA,KAAAA,CAAMH,UAAU,GAAG,IAAA;AACrB;YACA,IAAI,OAAOA,eAAe,UAAY,EAAA;AACpCG,gBAAAA,KAAAA,CAAMH,UAAU,GAAGA,UAAAA;AACrB,aAAA,MAAO,IAAIA,UAAY,EAAA;gBACrBG,KAAMH,CAAAA,UAAU,GAAG,IAAII,IAAkBJ,CAAAA,UAAAA,CAAAA;AAC3C;YACAG,KAAMD,CAAAA,IAAI,GAAGA,IAAQ,IAAA,IAAA;AACvB;AACF;AACA;;;;;;;AAOC,MACD,MAAMI,QAAAA,CAAuDV,IAAY,EAAEW,QAAY,EAAE;QACvF,IAAI;YACF,MAAMC,OAAAA,GAAU,MAAM,IAAI,CAACrE,GAAG,CAACmE,QAAQ,CAACV,IAAM,EAAA;AAAEW,gBAAAA,QAAAA,EAAUA,QAAY,IAAA;AAAS,aAAA,CAAA;YAC/E,OAAOC,OAAAA;AACT,SAAA,CAAE,OAAOC,GAAK,EAAA;YACZ3C,OAAQ4C,CAAAA,KAAK,CAAC,CAAC,WAAW,EAAEd,IAAK,CAAA,UAAU,EAAEa,GAAK,CAAA,CAAA,CAAA;YAClD,OAAO,IAAA;AACT;AACF;AACA;;;;;;;;AAQC,MACD,MAAME,OACJC,CAAAA,YAA+B,EAC/BC,YAA+B,EAC/BC,aAAgC,EAChC;AACA,QAAA,MAAMC,iBAAoB,GAAA,IAAA;AAC1B,QAAA,IAAIF,YAAc,EAAA;AAChB,YAAA,MAAMG,iBAAoB,GAAA,MAAM,IAAI,CAACrB,iBAAiB,CAACkB,YAAAA,CAAAA;AACvD,YAAA,IAAIG,iBAAmB,EAAA;gBACrB,IAAI,CAACjB,aAAa,CAACiB,iBAAmBD,EAAAA,iBAAAA,CAAAA;AACxC;AACF;AACA,QAAA,IAAID,aAAe,EAAA;AACjB,YAAA,MAAMlB,OACJkB,aAAcG,CAAAA,WAAW,GAAGC,QAAQ,CAAC,UAAUJ,aAAcG,CAAAA,WAAW,EAAGC,CAAAA,QAAQ,CAAC,KAChFJ,CAAAA,GAAAA,aAAAA,CAAcK,KAAK,CAAC,CAAA,EAAG,EACvBL,CAAAA,GAAAA,aAAAA;AACN,YAAA,MAAM,IAAI,CAACxC,YAAY,CAAC,IAAMsB,EAAAA,IAAAA,CAAAA;AAChC;AACA,QAAA,IAAIgB,YAAc,EAAA;AAChB,YAAA,MAAMQ,KAAQ,GAAA,MAAM,IAAI,CAACzB,iBAAiB,CAACiB,YAAAA,CAAAA;YAC3C,IAAI,CAACb,aAAa,CAACqB,KAAO,EAAA,CAAA,CAAA;AAC5B;QACA,IAAI,CAACrB,aAAa,CAAC,IAAMgB,EAAAA,iBAAAA,CAAAA;AAC3B;AACA;;;;;AAKC,MACDM,MAAS,GAAA;AACP,QAAA,IAAI,CAACpF,kBAAkB,CAACqF,OAAO,CAAC,CAACC,IAAAA,GAAAA;YAC/B,IAAI,CAACA,IAAKvB,CAAAA,UAAU,EAAE;AACpB,gBAAA;AACF;YACA,MAAMqB,MAAAA,GAASE,KAAKrB,IAAI,EAAEsB,eACrBD,IAAKrB,CAAAA,IAAI,CAACsB,YAAY,CACrB,OAAOD,KAAKvB,UAAU,KAAK,UAAauB,GAAAA,IAAAA,CAAKvB,UAAU,GAAGuB,KAAKvB,UAAU,CAACyB,GAAG,EAAA,CAAA,IAC1E,IACL,GAAA,IAAA;AACJ,YAAA,IAAIJ,MAAQ,EAAA;AACV,gBAAA,IAAI,OAAOE,IAAAA,CAAKvB,UAAU,KAAK,UAAY,EAAA;AACzCuB,oBAAAA,IAAAA,CAAKvB,UAAU,EAAA;iBACV,MAAA;oBACLuB,IAAKvB,CAAAA,UAAU,CAACyB,GAAG,EAAIJ,EAAAA,MAAAA,EAAAA;AACzB;AACF;YACA,IAAIE,IAAAA,CAAKrB,IAAI,EAAEwB,WAAa,EAAA;AAC1BH,gBAAAA,IAAAA,CAAKrB,IAAI,CAACwB,WAAW,CACnB,OAAOH,IAAKvB,CAAAA,UAAU,KAAK,UAAA,GAAauB,KAAKvB,UAAU,GAAGuB,IAAKvB,CAAAA,UAAU,CAACyB,GAAG,EAAA,CAAA;AAEjF;AACF,SAAA,CAAA;AACF;AACA,IAAA,MAAc1E,gBAAmB,GAAA;AAC/B,QAAA,IAAI,CAAC,IAAI,CAACpB,YAAY,EAAE;AACtB,YAAA,IAAI,CAACA,YAAY,GAAG,MAAM,IAAI,CAACgG,gBAAgB,EAAA;AACjD;AACA,QAAA,IAAI,CAACxF,GAAG,CAACyF,OAAO,CAAC,mBAAA,CAAA;QACjB,IAAI,CAACzF,GAAG,CAAC0F,KAAK,CAAC,mBAAqB,EAAA,IAAI,CAAClG,YAAY,CAAA;AACvD;AACA,IAAA,MAAcgG,gBAAmB,GAAA;AAC/B,QAAA,MAAMG,KAAK,IAAIC,QAAAA,EAAAA;AACf,QAAA,MAAMC,WAAc,GAAA;YAClB,sBAAwBC,EAAAA,QAAAA;YACxB,yBAA2BC,EAAAA,WAAAA;YAC3B,2BAA6BC,EAAAA,aAAAA;YAC7B,wBAA0BC,EAAAA,UAAAA;YAC1B,wBAA0BC,EAAAA,UAAAA;YAC1B,8BAAgCC,EAAAA,gBAAAA;YAChC,0BAA4BC,EAAAA,YAAAA;YAC5B,uBAAyBC,EAAAA,aAAAA;YACzB,yBAA2BC,EAAAA,eAAAA;YAC3B,4BAA8BC,EAAAA,aAAAA;YAC9B,wCAA0CC,EAAAA,4BAAAA;YAC1C,yCAA2CC,EAAAA,6BAAAA;YAC3C,4BAA8BC,EAAAA,sBAAAA;YAC9B,sBAAwBC,EAAAA,YAAAA;YACxB,sBAAwBC,EAAAA,YAAAA;YACxB,qBAAuBC,EAAAA;AACzB,SAAA;AACA,QAAA,KAAK,MAAM,CAACC,GAAI,CAAA,IAAIC,cAAclB,WAAc,CAAA,CAAA;AAC9C,YAAA,MAAMmB,GAAM,GAAA,IAAInB,WAAW,CAACiB,GAAI,CAAA,EAAA;AAChC,YAAA,MAAM,IAAI,CAACG,uBAAuB,CAACtB,EAAAA,EAAI,WAAWqB,GAAKF,EAAAA,GAAAA,CAAAA;AACvDE,YAAAA,GAAAA,CAAI9C,OAAO,EAAA;AACb;AACAyB,QAAAA,EAAAA,CAAGuB,QAAQ,GAAG,IAAA;QACd,OAAOvB,EAAAA;AACT;IACA,MAAcsB,uBAAAA,CAAwBjH,GAAQ,EAAEmH,IAAY,EAAEH,GAAQ,EAAEvD,IAAY,EAAE;QACpF,IAAI;AACF,YAAA,MAAM2D,OAAO,MAAM,IAAI,CAACvG,eAAe,CAACwG,eAAe,CAACL,GAAAA,CAAAA;YACxD,MAAM3C,OAAAA,GAAUiD,IAAKC,CAAAA,SAAS,CAAC;AAAEJ,gBAAAA,IAAAA;AAAMC,gBAAAA;AAAK,aAAA,EAAG,IAAM,EAAA,CAAA,CAAA;AACrD,YAAA,MAAMpH,GAAIwH,CAAAA,SAAS,CAAC/D,IAAAA,EAAMY,OAAS,EAAA;gBAAED,QAAU,EAAA,MAAA;gBAAQqD,MAAQ,EAAA;AAAK,aAAA,CAAA;AACtE,SAAA,CAAE,OAAOnD,GAAK,EAAA;YACZ3C,OAAQ4C,CAAAA,KAAK,CAAC,CAAC,YAAY,EAAEd,IAAK,CAAA,UAAU,EAAEa,GAAK,CAAA,CAAA,CAAA;AACrD;AACF;IACA,MAAcX,UAAAA,CAAWF,IAAY,EAAE;QACrC,IAAI;AACF,YAAA,MAAMwB,QAAQ,MAAM,IAAI,CAACvF,gBAAgB,CAACgI,SAAS,CAACjE,IAAAA,CAAAA;AACpD,YAAA,IAAIwB,KAAO,EAAA;gBACT,MAAM,IAAI,CAACjC,qBAAqB,CAACiC,KAAAA,CAAAA;AACjC,gBAAA,MAAM,IAAI,CAAC3C,sBAAsB,CAAC2C,MAAM0C,QAAQ,CAAA;AAClD;YACA,OAAO1C,KAAAA;AACT,SAAA,CAAE,OAAOX,GAAK,EAAA;YACZ3C,OAAQ4C,CAAAA,KAAK,CAAC,CAAC,iBAAiB,EAAEd,IAAK,CAAA,UAAU,EAAEa,GAAK,CAAA,CAAA,CAAA;YACxD,OAAO,IAAA;AACT;AACF;IACA,MAActB,qBAAAA,CAMZZ,IAAO,EAAE;AACT,QAAA,MAAMwF,WACJxF,GAAAA,IAAAA,CAAKyF,OAAO,CAACC,MAAM,GAAG,CAClB1F,GAAAA,IAAAA,CAAKyF,OAAO,GACZzF,IAAK2F,CAAAA,MAAM,GACT;AAAC,YAAA;AAAEA,gBAAAA,MAAAA,EAAQ3F,KAAK2F,MAAM;AAAE1F,gBAAAA,MAAAA,EAAQD,KAAK4F;AAAa;AAAE,SAAA,GACpD,EAAE;AACV,QAAA,MAAMC,cAAc,IAAIC,GAAAA,EAAAA;AACxB,QAAA,MAAMC,kBAAkB,IAAIC,GAAAA,EAAAA;AAC5B,QAAA,MAAMC,QAAWT,GAAAA,WAAAA,CACdU,MAAM,CAAC,CAACC,UAAAA,GAAe,CAAC,CAACA,UAAWR,CAAAA,MAAM,CAC1ChF,CAAAA,GAAG,CAAC,CAACwF,UAAAA,GAAAA;YACJ,MAAMlG,MAAAA,GAAUkG,UAAWlG,CAAAA,MAAM,IAAI,IAAA;AACrC,YAAA,MAAMmG,SAAYC,GAAAA,gCAAAA,CAAiCF,UAAWR,CAAAA,MAAM,EAAE1F,MAAAA,CAAAA;AACtE,YAAA,MAAMqG,UAAaT,GAAAA,WAAAA,CAAY3C,GAAG,CAACkD,SAAc,CAAA,IAAA,CAAA;YACjDP,WAAYU,CAAAA,GAAG,CAACH,SAAAA,EAAWE,UAAa,GAAA,CAAA,CAAA;AACxCP,YAAAA,eAAAA,CAAgBS,GAAG,CAAC,CAAA,EAAGJ,SAAU,CAAA,EAAE,EAAEE,UAAY,CAAA,CAAA,CAAA;AACjD,YAAA,OAAO,IAAI,CAACjJ,gBAAgB,CACzBoJ,uBAAuB,CAACzG,IAAAA,EAAMmG,UAAWR,CAAAA,MAAM,EAAE1F,MAAAA,EAAQqG,UACzDI,CAAAA,CAAAA,KAAK,CAAC,CAACxE,GAAAA,GAAAA;gBACN3C,OAAQ4C,CAAAA,KAAK,CAAC,CAAC,eAAe,EAAEgE,WAAWR,MAAM,CAAC,UAAU,EAAEzD,GAAK,CAAA,CAAA,CAAA;gBACnE,OAAO,IAAA;AACT,aAAA,CAAA;AACJ,SAAA,CAAA;AACF,QAAA,IAAI,CAAC7E,gBAAgB,CAACsJ,6BAA6B,CAAC3G,IAAM+F,EAAAA,eAAAA,CAAAA;AAC1D,QAAA,MAAMa,SAAY,GAAA,MAAMnG,OAAQC,CAAAA,GAAG,CAACuF,QAAAA,CAAAA;AACpC,QAAA,OAAOW,UAAUV,MAAM,CAAC,CAACW,QAAAA,GAA2C,CAAC,CAACA,QAAAA,CAAAA;AACxE;AACF;;;;"}
|
|
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 { createDeclarativeScriptSignature, 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, SceneNode } 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 EyeMaterial,\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 { SSSMaterial } from '../material/sss';\r\nimport { HairMaterial } from '../material/hair';\r\nimport { ScreenAdapter } from './screen';\r\nimport { PipelineCacheManager } from './pipelinecache';\r\nimport { AssetPreloader } from '../asset/asset_preload';\r\nimport { MSDFTextAtlasManager } from '../text/runtime';\r\nimport type { AssetSourceResolver } from '../asset/assetmanager';\r\nimport {\r\n ASSET_MANIFEST_FILE,\r\n createManifestSourceResolver,\r\n readAssetManifest\r\n} from '../asset/asset_manifest';\r\n\r\n/**\r\n * Interface for objects that can be rendered.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderable extends IDisposable {\r\n render(): void;\r\n}\r\n\r\n/**\r\n * Type for render functions that can be registered as renderables.\r\n *\r\n * @public\r\n */\r\nexport type RenderFunc = () => void;\r\n\r\n/**\r\n * Interface for render hooks to customize rendering behavior.\r\n *\r\n * @public\r\n */\r\nexport interface IRenderHook {\r\n // If presents, called before rendering the renderable. Return `false` to skip rendering.\r\n beforeRender?: (renderable: any) => boolean | void;\r\n // If presents, called after rendering the renderable.\r\n afterRender?: (renderable: any) => void;\r\n}\r\n\r\n/**\r\n * Core engine class managing scripting, serialization, and rendering.\r\n *\r\n * Responsibilities:\r\n * - Manages a {@link ScriptingSystem} for dynamic script attachment and lifecycle.\r\n * - Manages a {@link ResourceManager} for loading scenes and assets.\r\n * - Maintains a list of active renderable objects to be rendered each frame.\r\n * - Provides methods to attach/detach scripts, update scripts, load scenes, and read files.\r\n * - Supports enabling/disabling of runtime operations.\r\n *\r\n * @remarks\r\n * The engine can be configured with a virtual file system (VFS) and script root path.\r\n * It exposes methods to manage scripts on host objects, update scripts each frame,\r\n * load scenes from files, and render active objects.\r\n *\r\n * @public\r\n */\r\nexport class Engine {\r\n private _builtinsVFS: Nullable<MemoryFS>;\r\n private _scriptingSystem: ScriptingSystem;\r\n private _resourceManager: ResourceManager;\r\n private _msdfTextAtlasManager: MSDFTextAtlasManager;\r\n private _enabled: boolean;\r\n private _screen: ScreenAdapter;\r\n private readonly _pipelineCache: PipelineCacheManager;\r\n private readonly _assetPreloader: AssetPreloader;\r\n /** Resolver this engine installed from a build's asset manifest */\r\n private _manifestResolver: Nullable<AssetSourceResolver> = null;\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 this._pipelineCache = new PipelineCacheManager(() => this.VFS);\r\n this._assetPreloader = new AssetPreloader(\r\n () => this.VFS,\r\n () => this._resourceManager.assetManager\r\n );\r\n }\r\n /**\r\n * Exposes the instance of {@link ScriptingSystem}.\r\n */\r\n get scriptingSystem() {\r\n return this._scriptingSystem;\r\n }\r\n /**\r\n * Exposes the virtual file system used by the underlying {@link ScriptingSystem}'s registry.\r\n */\r\n get VFS() {\r\n return this._scriptingSystem.registry.VFS;\r\n }\r\n set VFS(vfs: VFS) {\r\n if (vfs !== this._resourceManager.VFS) {\r\n this._resourceManager.VFS?.close();\r\n this._resourceManager.VFS = vfs;\r\n this._scriptingSystem.registry.VFS = vfs;\r\n this.ensureBuiltinVFS();\r\n // A manifest belongs to the file system it was read from\r\n const assetManager = this._resourceManager.assetManager;\r\n if (this._manifestResolver && assetManager.assetSourceResolver === this._manifestResolver) {\r\n assetManager.assetSourceResolver = null;\r\n this._manifestResolver = null;\r\n void this.loadAssetManifest();\r\n }\r\n }\r\n }\r\n /**\r\n * Reads the asset manifest of a build (`/asset-manifest.json`, written by the\r\n * editor's build) from the engine's VFS and routes the assets it lists to the\r\n * compressed copies shipped for them, so code loading `/assets/rock.png` gets\r\n * `/assets/rock.<hash>.ktx2`. Called by {@link Engine.init}, so a project using\r\n * the editor's asset pipeline with its own code needs no setup; call it again\r\n * with another path for a manifest kept elsewhere.\r\n *\r\n * A resolver installed by someone else (the editor installs its own) is left\r\n * in place.\r\n *\r\n * @param path - VFS path of the manifest\r\n * @returns true if a manifest was found and is now in use\r\n */\r\n async loadAssetManifest(path = `/${ASSET_MANIFEST_FILE}`) {\r\n const vfs = this.VFS;\r\n const manifest = await readAssetManifest(vfs, path);\r\n const assetManager = this._resourceManager.assetManager;\r\n if (\r\n vfs !== this.VFS ||\r\n (assetManager.assetSourceResolver && assetManager.assetSourceResolver !== this._manifestResolver)\r\n ) {\r\n return false;\r\n }\r\n this._manifestResolver = manifest ? createManifestSourceResolver(vfs, manifest) : null;\r\n assetManager.assetSourceResolver = this._manifestResolver;\r\n return !!manifest;\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 /**\r\n * Reads pipeline cache files and compiles the pipelines they record ahead of time.\r\n * The engine never calls it by itself.\r\n */\r\n get pipelineCache() {\r\n return this._pipelineCache;\r\n }\r\n /**\r\n * Loads assets ahead of time from requests recorded while scenes were loaded.\r\n * The engine never calls it by itself.\r\n */\r\n get assetPreloader() {\r\n return this._assetPreloader;\r\n }\r\n /** @internal */\r\n async init() {\r\n await this.ensureBuiltinVFS();\r\n await this.loadAssetManifest();\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 * Attaches all serialized script declarations on a scene node subtree.\r\n *\r\n * The operation is explicit and idempotent. Repeated or concurrent calls reuse\r\n * instances already attached for the same declaration, while duplicate declarations\r\n * within one host remain distinct.\r\n *\r\n * @param root - Root node whose own declarations and descendants are processed.\r\n * @returns Script instances in host/declaration order. Failed declarations are omitted.\r\n */\r\n async attachScriptsInSubtree(root: SceneNode) {\r\n if (!this._enabled) {\r\n return [];\r\n }\r\n const nodes: SceneNode[] = [];\r\n root.iterate((node) => {\r\n nodes.push(node);\r\n });\r\n const results = await Promise.all(nodes.map((node) => this.attachDeclaredScripts(node)));\r\n return results.flat();\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 * Calls the `onFixedUpdate` hooks of scripts, if enabled. Driven by a physics\r\n * world before each of its fixed steps.\r\n *\r\n * @param fixedDeltaTime - Length of the step in seconds.\r\n * @param filter - Only scripts whose host passes are called.\r\n */\r\n fixedUpdate(fixedDeltaTime: number, filter?: (host: unknown) => boolean) {\r\n if (this._enabled) {\r\n this._scriptingSystem.fixedUpdate(fixedDeltaTime, filter);\r\n }\r\n }\r\n /**\r\n * Calls the `onLateUpdate` hooks of scripts, if enabled. Driven by a scene once\r\n * per frame, after its physics world has stepped.\r\n *\r\n * @param deltaTime - Time since last frame in seconds.\r\n * @param filter - Only scripts whose host passes are called.\r\n */\r\n lateUpdate(deltaTime: number, filter?: (host: unknown) => boolean) {\r\n if (this._enabled) {\r\n this._scriptingSystem.lateUpdate(deltaTime, filter);\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 running a startup script and loading the startup scene.\r\n *\r\n * @remarks\r\n * A loading screen covering the startup belongs to the page (an HTML overlay shown\r\n * before any script loads): hide it once this resolves and\r\n * {@link Application.nextFrame} reports the startup scene drawn.\r\n *\r\n * @param startupScene - Optional scene path rendered on layer `0` after startup completes.\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(startupScene?: Nullable<string>, startupScript?: Nullable<string>) {\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 }\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 '/materials/sss.zmtl': SSSMaterial,\r\n '/materials/hair.zmtl': HairMaterial,\r\n '/materials/eye.zmtl': EyeMaterial\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 await this.attachDeclaredScripts(scene);\r\n await this.attachScriptsInSubtree(scene.rootNode);\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 private async attachDeclaredScripts<\r\n T extends Host & {\r\n scripts: { script: string; config: unknown }[];\r\n script: string;\r\n scriptConfig: unknown;\r\n }\r\n >(host: T) {\r\n const attachments =\r\n host.scripts.length > 0\r\n ? host.scripts\r\n : host.script\r\n ? [{ script: host.script, config: host.scriptConfig }]\r\n : [];\r\n const occurrences = new Map<string, number>();\r\n const declarationKeys = new Set<string>();\r\n const requests = attachments\r\n .filter((attachment) => !!attachment.script)\r\n .map((attachment) => {\r\n const config = (attachment.config ?? null) as RuntimeScriptConfig | null;\r\n const signature = createDeclarativeScriptSignature(attachment.script, config);\r\n const occurrence = occurrences.get(signature) ?? 0;\r\n occurrences.set(signature, occurrence + 1);\r\n declarationKeys.add(`${signature}\\n${occurrence}`);\r\n return this._scriptingSystem\r\n .attachDeclarativeScript(host, attachment.script, config, occurrence)\r\n .catch((err) => {\r\n console.error(`Attach script '${attachment.script}' failed: ${err}`);\r\n return null;\r\n });\r\n });\r\n this._scriptingSystem.synchronizeDeclarativeScripts(host, declarationKeys);\r\n const instances = await Promise.all(requests);\r\n return instances.filter((instance): instance is RuntimeScript<T> => !!instance);\r\n }\r\n}\r\n\r\nexport { MSDFTextAtlasManager };\r\n"],"names":["Engine","_builtinsVFS","_scriptingSystem","_resourceManager","_msdfTextAtlasManager","_enabled","_screen","_pipelineCache","_assetPreloader","_manifestResolver","_activeRenderables","_loadingScenes","VFS","scriptsRoot","enabled","HttpFS","ScriptingSystem","ResourceManager","MSDFTextAtlasManager","ScreenAdapter","PipelineCacheManager","AssetPreloader","assetManager","scriptingSystem","registry","vfs","close","ensureBuiltinVFS","assetSourceResolver","loadAssetManifest","path","ASSET_MANIFEST_FILE","manifest","readAssetManifest","createManifestSourceResolver","resourceManager","msdfTextAtlasManager","releaseFontAsset","font","fontAsset","getFontAsset","atlasReleased","releaseAtlas","fontReleased","configureMSDFAtlas","pageSize","glyphSize","distanceRange","padding","console","warn","configureAtlas","screen","pipelineCache","assetPreloader","init","detachAllScripts","loadRuntimeScriptClass","module","attachScript","host","config","attachScriptsInSubtree","root","nodes","iterate","node","push","results","Promise","all","map","attachDeclaredScripts","flat","detachScript","idOrInstance","getScriptObjects","update","deltaTime","elapsedTime","fixedUpdate","fixedDeltaTime","filter","lateUpdate","loadSceneFromFile","normalizePath","_loadScene","setRenderable","renderable","layer","hook","entry","DRef","dispose","readFile","encoding","content","err","error","startup","startupScene","startupScript","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","SSSMaterial","HairMaterial","EyeMaterial","key","objectEntries","obj","writeSerializableObject","readOnly","type","data","serializeObject","JSON","stringify","writeFile","create","loadScene","rootNode","attachments","scripts","length","script","scriptConfig","occurrences","Map","declarationKeys","Set","requests","attachment","signature","createDeclarativeScriptSignature","occurrence","set","add","attachDeclarativeScript","catch","synchronizeDeclarativeScripts","instances","instance"],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buttons of the W3C "standard" gamepad layout, named after the Xbox controller.
|
|
3
|
+
* The value is the button's index in `Gamepad.buttons`.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/ const GamepadButtons = {
|
|
7
|
+
A: 0,
|
|
8
|
+
B: 1,
|
|
9
|
+
X: 2,
|
|
10
|
+
Y: 3,
|
|
11
|
+
LB: 4,
|
|
12
|
+
RB: 5,
|
|
13
|
+
LT: 6,
|
|
14
|
+
RT: 7,
|
|
15
|
+
Back: 8,
|
|
16
|
+
Start: 9,
|
|
17
|
+
LS: 10,
|
|
18
|
+
RS: 11,
|
|
19
|
+
DPadUp: 12,
|
|
20
|
+
DPadDown: 13,
|
|
21
|
+
DPadLeft: 14,
|
|
22
|
+
DPadRight: 15,
|
|
23
|
+
Home: 16
|
|
24
|
+
};
|
|
25
|
+
const BUTTON_COUNT = 17;
|
|
26
|
+
/** Analog buttons (triggers) count as pressed above this value. */ const PRESS_THRESHOLD = 0.5;
|
|
27
|
+
/**
|
|
28
|
+
* Per-frame state of one gamepad with the standard layout.
|
|
29
|
+
*
|
|
30
|
+
* Owned and polled by {@link InputManager} at the start of every frame, so all
|
|
31
|
+
* reads within a frame see the same values. Stick axes are reported with +y up,
|
|
32
|
+
* the opposite of the raw Gamepad API, and with a radial dead zone applied.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/ class GamepadState {
|
|
36
|
+
/** Radial dead zone of both sticks, as a fraction of full deflection. */ stickDeadZone = 0.15;
|
|
37
|
+
/** Analog buttons below this value read as 0. */ triggerDeadZone = 0.05;
|
|
38
|
+
_index;
|
|
39
|
+
_id;
|
|
40
|
+
_connected;
|
|
41
|
+
_values;
|
|
42
|
+
_down;
|
|
43
|
+
_prevDown;
|
|
44
|
+
_sticks;
|
|
45
|
+
_raw;
|
|
46
|
+
/** @internal */ constructor(index){
|
|
47
|
+
this._index = index;
|
|
48
|
+
this._id = '';
|
|
49
|
+
this._connected = false;
|
|
50
|
+
this._values = new Float32Array(BUTTON_COUNT);
|
|
51
|
+
this._down = new Uint8Array(BUTTON_COUNT);
|
|
52
|
+
this._prevDown = new Uint8Array(BUTTON_COUNT);
|
|
53
|
+
this._sticks = new Float32Array(4);
|
|
54
|
+
this._raw = null;
|
|
55
|
+
}
|
|
56
|
+
/** Index of the gamepad as reported by `navigator.getGamepads()`. */ get index() {
|
|
57
|
+
return this._index;
|
|
58
|
+
}
|
|
59
|
+
/** Device id string reported by the browser. */ get id() {
|
|
60
|
+
return this._id;
|
|
61
|
+
}
|
|
62
|
+
/** Whether the gamepad was connected when last polled. */ get connected() {
|
|
63
|
+
return this._connected;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Analog value of a button in [0, 1]; digital buttons read 0 or 1.
|
|
67
|
+
*
|
|
68
|
+
* @param button - Button name.
|
|
69
|
+
*/ value(button) {
|
|
70
|
+
return this._values[GamepadButtons[button]];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether a button is held this frame.
|
|
74
|
+
*
|
|
75
|
+
* @param button - Button name.
|
|
76
|
+
*/ isDown(button) {
|
|
77
|
+
return !!this._down[GamepadButtons[button]];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Whether a button went down this frame.
|
|
81
|
+
*
|
|
82
|
+
* @param button - Button name.
|
|
83
|
+
*/ pressed(button) {
|
|
84
|
+
const i = GamepadButtons[button];
|
|
85
|
+
return !!this._down[i] && !this._prevDown[i];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Whether a button went up this frame.
|
|
89
|
+
*
|
|
90
|
+
* @param button - Button name.
|
|
91
|
+
*/ released(button) {
|
|
92
|
+
const i = GamepadButtons[button];
|
|
93
|
+
return !this._down[i] && !!this._prevDown[i];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Deflection of a stick, each component in [-1, 1] and the length at most 1.
|
|
97
|
+
* +x is right and +y is up.
|
|
98
|
+
*
|
|
99
|
+
* @param stick - Stick name.
|
|
100
|
+
* @param out - Optional output object.
|
|
101
|
+
* @returns The deflection.
|
|
102
|
+
*/ stick(stick, out) {
|
|
103
|
+
const i = stick === 'LS' ? 0 : 2;
|
|
104
|
+
out = out ?? {
|
|
105
|
+
x: 0,
|
|
106
|
+
y: 0
|
|
107
|
+
};
|
|
108
|
+
out.x = this._sticks[i];
|
|
109
|
+
out.y = this._sticks[i + 1];
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Plays a rumble effect if the browser and the gamepad support it; otherwise
|
|
114
|
+
* does nothing.
|
|
115
|
+
*
|
|
116
|
+
* @param strong - Strength of the low-frequency motor in [0, 1].
|
|
117
|
+
* @param weak - Strength of the high-frequency motor in [0, 1].
|
|
118
|
+
* @param durationMs - Duration in milliseconds.
|
|
119
|
+
*/ rumble(strong, weak, durationMs) {
|
|
120
|
+
const actuator = this._raw?.vibrationActuator;
|
|
121
|
+
if (actuator?.playEffect) {
|
|
122
|
+
actuator.playEffect('dual-rumble', {
|
|
123
|
+
duration: durationMs,
|
|
124
|
+
strongMagnitude: Math.min(Math.max(strong, 0), 1),
|
|
125
|
+
weakMagnitude: Math.min(Math.max(weak, 0), 1)
|
|
126
|
+
}).catch(()=>{});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether anything was operated this frame: a button went down or a stick left
|
|
131
|
+
* its dead zone.
|
|
132
|
+
*
|
|
133
|
+
* @internal
|
|
134
|
+
*/ get active() {
|
|
135
|
+
for(let i = 0; i < BUTTON_COUNT; i++){
|
|
136
|
+
if (this._down[i] && !this._prevDown[i]) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
for(let i = 0; i < 4; i++){
|
|
141
|
+
if (this._sticks[i] !== 0) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/** @internal */ _update(pad) {
|
|
148
|
+
this._prevDown.set(this._down);
|
|
149
|
+
this._raw = pad;
|
|
150
|
+
this._connected = !!pad?.connected;
|
|
151
|
+
if (!pad || !this._connected) {
|
|
152
|
+
this._values.fill(0);
|
|
153
|
+
this._down.fill(0);
|
|
154
|
+
this._sticks.fill(0);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this._id = pad.id;
|
|
158
|
+
for(let i = 0; i < BUTTON_COUNT; i++){
|
|
159
|
+
const b = pad.buttons[i];
|
|
160
|
+
const v = b ? b.value : 0;
|
|
161
|
+
this._values[i] = v < this.triggerDeadZone ? b?.pressed ? 1 : 0 : v;
|
|
162
|
+
this._down[i] = b && (b.pressed || v > PRESS_THRESHOLD) ? 1 : 0;
|
|
163
|
+
}
|
|
164
|
+
this._readStick(pad, 0);
|
|
165
|
+
this._readStick(pad, 2);
|
|
166
|
+
}
|
|
167
|
+
/** @internal */ _reset() {
|
|
168
|
+
this._prevDown.set(this._down);
|
|
169
|
+
this._values.fill(0);
|
|
170
|
+
this._down.fill(0);
|
|
171
|
+
this._sticks.fill(0);
|
|
172
|
+
}
|
|
173
|
+
_readStick(pad, axis) {
|
|
174
|
+
const x = pad.axes[axis] ?? 0;
|
|
175
|
+
const y = -(pad.axes[axis + 1] ?? 0);
|
|
176
|
+
const len = Math.hypot(x, y);
|
|
177
|
+
const dz = this.stickDeadZone;
|
|
178
|
+
if (len <= dz) {
|
|
179
|
+
this._sticks[axis] = 0;
|
|
180
|
+
this._sticks[axis + 1] = 0;
|
|
181
|
+
} else {
|
|
182
|
+
// Rescale so that output starts at 0 just outside the dead zone
|
|
183
|
+
const scale = Math.min((len - dz) / (1 - dz), 1) / len;
|
|
184
|
+
this._sticks[axis] = x * scale;
|
|
185
|
+
this._sticks[axis + 1] = y * scale;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { GamepadButtons, GamepadState };
|
|
191
|
+
//# sourceMappingURL=gamepad.js.map
|