@woosh/meep-engine 3.11.3 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/README.md +14 -18
  2. package/editor/SelectionVisualizer.js +127 -127
  3. package/editor/entity_world_bounds.js +27 -27
  4. package/editor/particles/rebuildParticleEmitter.js +31 -31
  5. package/editor/process/SymbolicDisplayProcess.js +1 -1
  6. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  7. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  8. package/editor/prototypeEditorShell.js +156 -156
  9. package/editor/selection/editor_pick.js +130 -130
  10. package/editor/selection/screen_rect_frustum.js +119 -119
  11. package/editor/tools/v2/TransformControls.js +971 -971
  12. package/package.json +1 -1
  13. package/src/engine/Engine.d.ts +3 -3
  14. package/src/engine/Engine.d.ts.map +1 -1
  15. package/src/engine/Engine.js +726 -726
  16. package/src/engine/EngineHarness.d.ts +1 -1
  17. package/src/engine/EngineHarness.js +590 -590
  18. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  19. package/src/engine/ecs/terrain/ecs/BuildLightTexture.d.ts +1 -1
  20. package/src/engine/ecs/terrain/ecs/BuildLightTexture.js +27 -27
  21. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +1 -5
  22. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  23. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  24. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  25. package/src/engine/graphics/ecs/camera/camera_find_active.d.ts +1 -1
  26. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  27. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +1 -1
  28. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  29. package/src/engine/graphics/ecs/water/Water.d.ts +1 -1
  30. package/src/engine/graphics/ecs/water/Water.js +104 -104
  31. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +1 -1
  32. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1 -1
  33. package/src/engine/graphics3/AnimationGraphSystem.d.ts +65 -0
  34. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -0
  35. package/src/engine/graphics3/AnimationGraphSystem.js +329 -0
  36. package/src/engine/graphics3/AnimationGraphSystem3.d.ts +6 -61
  37. package/src/engine/graphics3/AnimationGraphSystem3.d.ts.map +1 -1
  38. package/src/engine/graphics3/AnimationGraphSystem3.js +6 -325
  39. package/src/engine/graphics3/AnimationSystem.d.ts +76 -0
  40. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -0
  41. package/src/engine/graphics3/AnimationSystem.js +352 -0
  42. package/src/engine/graphics3/AnimationSystem3.d.ts +6 -72
  43. package/src/engine/graphics3/AnimationSystem3.d.ts.map +1 -1
  44. package/src/engine/graphics3/AnimationSystem3.js +6 -348
  45. package/src/engine/graphics3/CameraSystem.d.ts +49 -0
  46. package/src/engine/graphics3/CameraSystem.d.ts.map +1 -0
  47. package/src/engine/graphics3/CameraSystem.js +170 -0
  48. package/src/engine/graphics3/CameraSystem3.d.ts +6 -45
  49. package/src/engine/graphics3/CameraSystem3.d.ts.map +1 -1
  50. package/src/engine/graphics3/CameraSystem3.js +6 -166
  51. package/src/engine/graphics3/DebugDrawSystem.d.ts +72 -0
  52. package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -0
  53. package/src/engine/graphics3/DebugDrawSystem.js +205 -0
  54. package/src/engine/graphics3/DebugDrawSystem3.d.ts +6 -68
  55. package/src/engine/graphics3/DebugDrawSystem3.d.ts.map +1 -1
  56. package/src/engine/graphics3/DebugDrawSystem3.js +6 -201
  57. package/src/engine/graphics3/DecalSystem.d.ts +81 -0
  58. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -0
  59. package/src/engine/graphics3/DecalSystem.js +441 -0
  60. package/src/engine/graphics3/DecalSystem3.d.ts +6 -77
  61. package/src/engine/graphics3/DecalSystem3.d.ts.map +1 -1
  62. package/src/engine/graphics3/DecalSystem3.js +6 -437
  63. package/src/engine/graphics3/FogOfWarSystem.d.ts +74 -0
  64. package/src/engine/graphics3/FogOfWarSystem.d.ts.map +1 -0
  65. package/src/engine/graphics3/FogOfWarSystem.js +265 -0
  66. package/src/engine/graphics3/FogOfWarSystem3.d.ts +6 -70
  67. package/src/engine/graphics3/FogOfWarSystem3.d.ts.map +1 -1
  68. package/src/engine/graphics3/FogOfWarSystem3.js +6 -261
  69. package/src/engine/graphics3/GraphicsEngine.d.ts +340 -0
  70. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -0
  71. package/src/engine/graphics3/GraphicsEngine.js +790 -0
  72. package/src/engine/graphics3/GraphicsEngine3.d.ts +6 -336
  73. package/src/engine/graphics3/GraphicsEngine3.d.ts.map +1 -1
  74. package/src/engine/graphics3/GraphicsEngine3.js +6 -786
  75. package/src/engine/graphics3/HighlightSystem.d.ts +82 -0
  76. package/src/engine/graphics3/HighlightSystem.d.ts.map +1 -0
  77. package/src/engine/graphics3/HighlightSystem.js +241 -0
  78. package/src/engine/graphics3/HighlightSystem3.d.ts +6 -78
  79. package/src/engine/graphics3/HighlightSystem3.d.ts.map +1 -1
  80. package/src/engine/graphics3/HighlightSystem3.js +6 -237
  81. package/src/engine/graphics3/LightSystem.d.ts +40 -0
  82. package/src/engine/graphics3/LightSystem.d.ts.map +1 -0
  83. package/src/engine/graphics3/LightSystem.js +211 -0
  84. package/src/engine/graphics3/LightSystem3.d.ts +6 -36
  85. package/src/engine/graphics3/LightSystem3.d.ts.map +1 -1
  86. package/src/engine/graphics3/LightSystem3.js +6 -207
  87. package/src/engine/graphics3/MeshSystem.d.ts +106 -0
  88. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -0
  89. package/src/engine/graphics3/MeshSystem.js +647 -0
  90. package/src/engine/graphics3/MeshSystem3.d.ts +6 -102
  91. package/src/engine/graphics3/MeshSystem3.d.ts.map +1 -1
  92. package/src/engine/graphics3/MeshSystem3.js +6 -642
  93. package/src/engine/graphics3/ParticipatingMedia.d.ts +2 -2
  94. package/src/engine/graphics3/ParticipatingMedia.js +203 -203
  95. package/src/engine/graphics3/ParticipatingMediaSystem.d.ts +87 -0
  96. package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -0
  97. package/src/engine/graphics3/ParticipatingMediaSystem.js +184 -0
  98. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +6 -83
  99. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -1
  100. package/src/engine/graphics3/ParticipatingMediaSystem3.js +6 -180
  101. package/src/engine/graphics3/ParticleEmitterSystem.d.ts +76 -0
  102. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -0
  103. package/src/engine/graphics3/ParticleEmitterSystem.js +289 -0
  104. package/src/engine/graphics3/ParticleEmitterSystem3.d.ts +6 -72
  105. package/src/engine/graphics3/ParticleEmitterSystem3.d.ts.map +1 -1
  106. package/src/engine/graphics3/ParticleEmitterSystem3.js +6 -285
  107. package/src/engine/graphics3/PathDisplaySystem.d.ts +70 -0
  108. package/src/engine/graphics3/PathDisplaySystem.d.ts.map +1 -0
  109. package/src/engine/graphics3/PathDisplaySystem.js +309 -0
  110. package/src/engine/graphics3/PathDisplaySystem3.d.ts +6 -66
  111. package/src/engine/graphics3/PathDisplaySystem3.d.ts.map +1 -1
  112. package/src/engine/graphics3/PathDisplaySystem3.js +6 -305
  113. package/src/engine/graphics3/Pickable.d.ts +1 -1
  114. package/src/engine/graphics3/Pickable.js +65 -65
  115. package/src/engine/graphics3/PickingQuery.d.ts +1 -1
  116. package/src/engine/graphics3/PickingQuery.js +48 -48
  117. package/src/engine/graphics3/PickingSystem.d.ts +67 -0
  118. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -0
  119. package/src/engine/graphics3/PickingSystem.js +273 -0
  120. package/src/engine/graphics3/PickingSystem3.d.ts +6 -63
  121. package/src/engine/graphics3/PickingSystem3.d.ts.map +1 -1
  122. package/src/engine/graphics3/PickingSystem3.js +6 -269
  123. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +47 -0
  124. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -0
  125. package/src/engine/graphics3/ShadedGeometrySystem.js +169 -0
  126. package/src/engine/graphics3/ShadedGeometrySystem3.d.ts +6 -43
  127. package/src/engine/graphics3/ShadedGeometrySystem3.d.ts.map +1 -1
  128. package/src/engine/graphics3/ShadedGeometrySystem3.js +6 -165
  129. package/src/engine/graphics3/TerrainSystem.d.ts +80 -0
  130. package/src/engine/graphics3/TerrainSystem.d.ts.map +1 -0
  131. package/src/engine/graphics3/TerrainSystem.js +566 -0
  132. package/src/engine/graphics3/TerrainSystem3.d.ts +6 -76
  133. package/src/engine/graphics3/TerrainSystem3.d.ts.map +1 -1
  134. package/src/engine/graphics3/TerrainSystem3.js +6 -562
  135. package/src/engine/graphics3/TooltipComponentSystem.d.ts +65 -0
  136. package/src/engine/graphics3/TooltipComponentSystem.d.ts.map +1 -0
  137. package/src/engine/graphics3/TooltipComponentSystem.js +328 -0
  138. package/src/engine/graphics3/TooltipComponentSystem3.d.ts +6 -61
  139. package/src/engine/graphics3/TooltipComponentSystem3.d.ts.map +1 -1
  140. package/src/engine/graphics3/TooltipComponentSystem3.js +6 -324
  141. package/src/engine/graphics3/Trail3DSystem.d.ts +73 -0
  142. package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -0
  143. package/src/engine/graphics3/Trail3DSystem.js +221 -0
  144. package/src/engine/graphics3/Trail3DSystem3.d.ts +6 -69
  145. package/src/engine/graphics3/Trail3DSystem3.d.ts.map +1 -1
  146. package/src/engine/graphics3/Trail3DSystem3.js +6 -217
  147. package/src/engine/graphics3/VolumetricLightMap.d.ts +2 -2
  148. package/src/engine/graphics3/VolumetricLightMap.js +2 -2
  149. package/src/engine/graphics3/VolumetricLightMapSystem.d.ts +98 -0
  150. package/src/engine/graphics3/VolumetricLightMapSystem.d.ts.map +1 -0
  151. package/src/engine/graphics3/VolumetricLightMapSystem.js +261 -0
  152. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +6 -94
  153. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -1
  154. package/src/engine/graphics3/VolumetricLightMapSystem3.js +10 -261
  155. package/src/engine/graphics3/WaterSystem.d.ts +59 -0
  156. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -0
  157. package/src/engine/graphics3/WaterSystem.js +293 -0
  158. package/src/engine/graphics3/WaterSystem3.d.ts +6 -55
  159. package/src/engine/graphics3/WaterSystem3.d.ts.map +1 -1
  160. package/src/engine/graphics3/WaterSystem3.js +6 -289
  161. package/src/engine/graphics3/animation/AnimationGraphController.d.ts +1 -1
  162. package/src/engine/graphics3/animation/AnimationGraphController.js +518 -518
  163. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +1 -1
  164. package/src/engine/graphics3/animation/ClipListPlayer.js +263 -263
  165. package/src/engine/graphics3/animation/ClipPlayback.d.ts +2 -2
  166. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  167. package/src/engine/graphics3/decal/graph_build_decal_clusters.d.ts.map +1 -1
  168. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +6 -8
  169. package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts +0 -7
  170. package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts.map +1 -1
  171. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
  172. package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts +0 -4
  173. package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts.map +1 -1
  174. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
  175. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts +2 -2
  176. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts.map +1 -1
  177. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  178. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +1 -1
  179. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +101 -101
  180. package/src/engine/graphics3/preview/make_model_thumbnail.d.ts +3 -3
  181. package/src/engine/graphics3/preview/make_model_thumbnail.d.ts.map +1 -1
  182. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  183. package/src/engine/graphics3/shade_camera_projection_ray.d.ts +1 -1
  184. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  185. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +1 -1
  186. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  187. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
  188. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +0 -1
  189. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
  190. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +0 -1
  191. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
  192. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +133 -134
  193. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +202 -202
  194. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +249 -249
  195. package/src/shade/renderer/STATIC_GRAPHICS_ENGINE_ASSETS.js +1 -1
  196. package/src/shade/renderer/animation/pose/PosePlayback.d.ts +2 -1
  197. package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
  198. package/src/shade/renderer/animation/pose/PosePlayback.js +2 -1
  199. package/src/shade/renderer/animation/shader_animation_apply.d.ts.map +1 -1
  200. package/src/shade/renderer/animation/shader_animation_apply.js +128 -129
  201. package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
  202. package/src/shade/renderer/animation/shader_animation_pose_resolve.js +176 -177
  203. package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
  204. package/src/shade/renderer/animation/shader_animation_tick.js +125 -126
  205. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
  206. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +98 -99
  207. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
  208. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +212 -213
  209. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
  210. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +120 -121
  211. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
  212. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +75 -76
  213. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  214. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +371 -372
  215. package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.d.ts.map +1 -1
  216. package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.js +104 -105
  217. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
  218. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +0 -1
  219. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +136 -136
  220. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  221. package/src/shade/renderer/buffer/table/GPUDatabase.js +2 -3
  222. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +319 -319
  223. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  224. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +41 -42
  225. package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.d.ts.map +1 -1
  226. package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.js +83 -84
  227. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts.map +1 -1
  228. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +177 -170
  229. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  230. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +4 -4
  231. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
  232. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +121 -122
  233. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +774 -774
  234. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts +1 -1
  235. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  236. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +69 -70
  237. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.js +367 -367
  238. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +184 -184
  239. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1115 -1115
  240. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
  241. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  242. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +142 -143
  243. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  244. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +0 -1
  245. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
  246. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +140 -141
  247. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  248. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +0 -1
  249. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  250. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +0 -1
  251. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
  252. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +191 -198
  253. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts +0 -6
  254. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts.map +1 -1
  255. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.js +120 -120
  256. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts +0 -4
  257. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts.map +1 -1
  258. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.js +112 -112
  259. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
  260. package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +4 -7
  261. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts +0 -6
  262. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts.map +1 -1
  263. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.js +1 -1
  264. package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +222 -222
  265. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_tile_composit.js +81 -81
  266. package/src/shade/renderer/material/GPUMaterialContext.js +380 -380
  267. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  268. package/src/shade/renderer/object_property/shader_object_property_process.d.ts.map +1 -1
  269. package/src/shade/renderer/object_property/shader_object_property_process.js +83 -84
  270. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.d.ts.map +1 -1
  271. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.js +57 -58
  272. package/src/shade/renderer/particles/prototypeParticleSystem.js +2 -3
  273. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  274. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +117 -118
  275. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  276. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +77 -79
  277. package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
  278. package/src/shade/renderer/particles/shaders/shader_particle_render.js +190 -183
  279. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  280. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +99 -100
  281. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
  282. package/src/shade/renderer/particles/sort/shader_particle_sort.js +158 -161
  283. package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +184 -184
  284. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +119 -119
  285. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +3 -4
  286. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  287. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +266 -267
  288. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  289. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +270 -271
  290. package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
  291. package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +68 -69
  292. package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.d.ts.map +1 -1
  293. package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.js +225 -226
  294. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.d.ts.map +1 -1
  295. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.js +49 -50
  296. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
  297. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +291 -292
  298. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.d.ts.map +1 -1
  299. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +230 -231
  300. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +16 -2
  301. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +1 -1
  302. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +12 -12
  303. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +2 -2
  304. package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.d.ts.map +1 -1
  305. package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.js +68 -69
  306. package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.d.ts.map +1 -1
  307. package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.js +59 -60
  308. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  309. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +0 -1
  310. package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.d.ts.map +1 -1
  311. package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.js +64 -65
  312. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
  313. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +168 -169
  314. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.d.ts.map +1 -1
  315. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.js +160 -161
  316. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  317. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +109 -110
  318. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  319. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +115 -116
  320. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.d.ts.map +1 -1
  321. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.js +139 -140
  322. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.d.ts.map +1 -1
  323. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.js +91 -92
  324. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.d.ts.map +1 -1
  325. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.js +88 -89
  326. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.d.ts.map +1 -1
  327. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.js +90 -91
  328. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  329. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +65 -66
  330. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
  331. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +89 -90
  332. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
  333. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +169 -170
  334. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.d.ts.map +1 -1
  335. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.js +89 -90
  336. package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.d.ts.map +1 -1
  337. package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.js +61 -62
  338. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.d.ts.map +1 -1
  339. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.js +153 -154
  340. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +144 -144
  341. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +88 -88
  342. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +217 -217
  343. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +179 -179
  344. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  345. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +194 -194
  346. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_opaque_pass_descriptor.js +76 -76
  347. package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
  348. package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +136 -137
  349. package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
  350. package/src/shade/renderer/restir/di/shader_restir_di_resample.js +129 -130
  351. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  352. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +99 -100
  353. package/src/shade/renderer/restir/di/shader_restir_di_spatial.d.ts.map +1 -1
  354. package/src/shade/renderer/restir/di/shader_restir_di_spatial.js +116 -117
  355. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +383 -383
  356. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy_naive.js +123 -123
  357. package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.d.ts.map +1 -1
  358. package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.js +64 -65
  359. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.d.ts.map +1 -1
  360. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.js +372 -373
  361. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.d.ts.map +1 -1
  362. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.js +111 -112
  363. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
  364. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +0 -1
  365. package/src/shade/renderer/shader/ComputeShader.d.ts +24 -3
  366. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  367. package/src/shade/renderer/shader/ComputeShader.js +350 -296
  368. package/src/shade/renderer/shader/ImageShader.js +217 -217
  369. package/src/shade/renderer/shader/ShaderDescriptor.d.ts +5 -0
  370. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  371. package/src/shade/renderer/shader/ShaderDescriptor.js +20 -0
  372. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts +47 -0
  373. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts.map +1 -0
  374. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.js +448 -0
  375. package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.js +3 -3
  376. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +3 -3
  377. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +2 -2
  378. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +4 -4
  379. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
  380. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +231 -232
  381. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +1 -1
  382. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  383. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +12 -15
  384. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +3 -2
  385. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  386. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +3 -2
  387. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts +0 -2
  388. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts.map +1 -1
  389. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +17 -6
  390. package/src/shade/renderer/water/shader_water.js +246 -246
  391. package/src/shade/vitest.setup.mjs +1 -1
  392. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +291 -291
  393. package/src/view/minimap/Minimap.d.ts +2 -2
  394. package/src/view/minimap/Minimap.d.ts.map +1 -1
  395. package/src/view/minimap/Minimap.js +225 -225
  396. package/src/view/minimap/dom/MinimapCameraView.d.ts +3 -3
  397. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  398. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  399. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts +0 -3
  400. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts.map +0 -1
  401. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.js +0 -20
@@ -1,726 +1,726 @@
1
- /**
2
- *
3
- */
4
-
5
- import { assert } from "../core/assert.js";
6
- import Vector1 from "../core/geom/Vector1.js";
7
- import { Localization } from "../core/localization/Localization.js";
8
- import { ModuleRegistry } from "../core/model/ModuleRegistry.js";
9
- import ObservedBoolean from "../core/model/ObservedBoolean.js";
10
- import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
11
- import EmptyView from "../view/elements/EmptyView.js";
12
- import { ViewStack } from "../view/elements/navigation/ViewStack.js";
13
- import { GraphicsContextFailureView } from "../view/graphics/GraphicsContextFailureView.js";
14
-
15
- import { AssetManager } from './asset/AssetManager.js';
16
- import { AssetPreloader } from "./asset/preloader/AssetPreloader.js";
17
- import { MetricCollection } from "./development/performance/MetricCollection.js";
18
- import { MetricStatistics } from "./development/performance/MetricStatistics.js";
19
- import { PeriodicConsolePrinter } from "./development/performance/monitor/PeriodicConsolePrinter.js";
20
- import { EntityManager } from "./ecs/EntityManager.js";
21
- import { BinarySerializationRegistry } from "./ecs/storage/binary/BinarySerializationRegistry.js";
22
- import { GraphicsEngine3 } from './graphics3/GraphicsEngine3.js';
23
- import { GamepadDevice } from "./input/devices/GamepadDevice.js";
24
- import KeyboardDevice from "./input/devices/KeyboardDevice.js";
25
- import { PointerDevice } from "./input/devices/PointerDevice.js";
26
- import { StaticKnowledgeDatabase, StaticKnowledgeState } from "./knowledge/database/StaticKnowledgeDatabase.js";
27
- import { logger } from "./logging/GlobalLogger.js";
28
- import { OptionGroup } from "./options/OptionGroup.js";
29
- import { EnginePluginManager } from "./plugin/EnginePluginManager.js";
30
- import SceneManager from "./scene/SceneManager.js";
31
- import Ticker from "./simulation/Ticker.js";
32
- import SoundEngine from './sound/SoundEngine.js';
33
-
34
- import GUIEngine from './ui/GUIEngine.js';
35
-
36
-
37
- class EngineSettings {
38
- graphics_control_viewport_size = new ObservedBoolean(true);
39
- simulation_speed = new Vector1(1);
40
- input_mouse_sensitivity = new Vector1(5);
41
- }
42
-
43
- const METRIC_ID_FRAME = 'frame_delay';
44
- const METRIC_ID_RENDER = 'render_time';
45
- const METRIC_ID_SIMULATION = 'simulation_time';
46
-
47
- /**
48
- * How long a context loss is tolerated before the simulation is paused as well, in seconds. Most losses
49
- * are resolved in well under a second, and stopping the world for those would be more disruptive than
50
- * letting it run; a longer outage is worth pausing for, as the player cannot see what is happening.
51
- * @type {number}
52
- */
53
- const CONTEXT_LOSS_SIMULATION_PAUSE_DELAY = 2;
54
-
55
- class Engine {
56
- #last_frame_timestamp = 0;
57
-
58
- /**
59
- * Handle of the pending render-loop frame, `-1` when the loop is not running
60
- * @type {number}
61
- */
62
- #animation_frame_handle = -1;
63
-
64
- /**
65
- * Handle of the pending "pause the simulation, this outage is taking a while" timer, `-1` when none
66
- * @type {number}
67
- */
68
- #context_loss_pause_timer = -1;
69
-
70
- /**
71
- * Whether the simulation was paused because of a context loss, and therefore should be resumed once
72
- * the context comes back
73
- * @type {boolean}
74
- */
75
- #paused_by_context_loss = false;
76
-
77
- /**
78
- * Absent when the engine is constructed with `enableGraphics: false`.
79
- * @type {GraphicsEngine3|null}
80
- */
81
- graphics = null;
82
-
83
- /**
84
- * Absent when the engine is constructed with `enableAudio: false`.
85
- * @type {SoundEngine|null}
86
- */
87
- sound = null;
88
-
89
- viewStack = new ViewStack();
90
-
91
- /**
92
- *
93
- * Static database
94
- * Can contain tables of structured data that the application often works with.
95
- * Engine startup will load all tables ensuring that data is ready once startup finishes
96
- * Use sparingly, this is not suitable for very large amounts of data as all the data will be in memory and deserialization will stall engine startup
97
- * Example: inventory item table, monster table
98
- * @readonly
99
- * @type {StaticKnowledgeDatabase}
100
- */
101
- staticKnowledge = new StaticKnowledgeDatabase();
102
-
103
- /**
104
- * @readonly
105
- * @type {EnginePluginManager}
106
- */
107
- plugins = new EnginePluginManager();
108
-
109
- /**
110
- * Main simulation ticker
111
- * @readonly
112
- * @type {Ticker}
113
- */
114
- ticker = new Ticker();
115
-
116
- /**
117
- * Default executor, enables time-sharing concurrency
118
- * @readonly
119
- * @type {ConcurrentExecutor}
120
- */
121
- executor = new ConcurrentExecutor(1, 10);
122
-
123
- /**
124
- *
125
- * @param {EnginePlatform} platform
126
- * @param {EntityManager} [entityManager]
127
- * @param {boolean} [enableGraphics]
128
- * @param {boolean} [enableAudio]
129
- * @param {boolean} [debug]
130
- * @constructor
131
- */
132
- constructor(platform, {
133
- entityManager,
134
- enableGraphics = true,
135
- enableAudio = true,
136
- debug = true
137
- } = {}) {
138
- assert.defined(platform, 'platform');
139
-
140
- /**
141
- *
142
- * @type {EnginePlatform}
143
- */
144
- this.platform = platform;
145
-
146
- this.staticKnowledge.validation_enabled = debug;
147
-
148
-
149
- /**
150
- *
151
- * @type {MetricCollection}
152
- */
153
- this.performance = new MetricCollection();
154
-
155
-
156
- this.__using_external_entity_manager = entityManager !== undefined;
157
-
158
- //setup entity component system
159
- if (this.__using_external_entity_manager) {
160
- // external entity manager provided
161
- this.entityManager = entityManager;
162
- } else {
163
- this.entityManager = new EntityManager();
164
- }
165
-
166
-
167
- /**
168
- *
169
- * @type {AssetManager<Engine>}
170
- */
171
- this.assetManager = new AssetManager({
172
- context: this,
173
- executor: this.executor
174
- });
175
-
176
- this.__performacne_monitor = new PeriodicConsolePrinter(15, () => {
177
- const metrics = this.performance;
178
- const stats = new MetricStatistics();
179
-
180
- // RENDER
181
- const m_render = metrics.get(METRIC_ID_RENDER);
182
-
183
- m_render.computeStats(stats);
184
-
185
- const v_render = (stats.mean * 1000).toFixed(2);
186
-
187
- // SIMULATION
188
- const m_sim = metrics.get(METRIC_ID_SIMULATION);
189
-
190
- m_sim.computeStats(stats);
191
-
192
- const v_sim = (stats.mean * 1000).toFixed(2);
193
-
194
- // FPS
195
-
196
- const m_frame = metrics.get(METRIC_ID_FRAME);
197
-
198
- m_frame.computeStats(stats);
199
-
200
- const v_fps = (1 / stats.mean).toFixed(2);
201
-
202
-
203
- // clear stats
204
- m_render.clear();
205
- m_sim.clear();
206
- m_frame.clear();
207
-
208
- return `FPS: ${v_fps}, RENDER: ${v_render}ms, SIMULATION: ${v_sim}ms`;
209
- });
210
-
211
-
212
- if (!this.__using_external_entity_manager) {
213
- // subscribe simulator to common ticker
214
- this.ticker.onTick.add(timeDelta => {
215
- const t0 = performance.now();
216
- this.entityManager.update(timeDelta);
217
-
218
- const t1 = performance.now();
219
- const duration = (t1 - t0) / 1000;
220
-
221
- // record frame time
222
- this.performance.get(METRIC_ID_SIMULATION).record(duration);
223
- });
224
- }
225
-
226
- // initialize performance metrics
227
- this.performance.create({
228
- name: METRIC_ID_RENDER
229
- });
230
- this.performance.create({
231
- name: METRIC_ID_SIMULATION
232
- });
233
- this.performance.create({
234
- name: METRIC_ID_FRAME
235
- });
236
-
237
- /**
238
- *
239
- * @type {OptionGroup}
240
- */
241
- this.options = new OptionGroup("options");
242
-
243
- /**
244
- *
245
- * @type {ModuleRegistry}
246
- */
247
- this.moduleRegistry = new ModuleRegistry();
248
-
249
- /**
250
- * @readonly
251
- * @type {BinarySerializationRegistry}
252
- */
253
- this.binarySerializationRegistry = new BinarySerializationRegistry();
254
-
255
- this.settings = new EngineSettings();
256
-
257
-
258
- /**
259
- * @deprecated use plugins instead
260
- */
261
- this.services = {};
262
-
263
- /**
264
- *
265
- * @type {Storage}
266
- */
267
- this.storage = this.platform.getStorage();
268
-
269
-
270
- this.localization = new Localization();
271
- this.localization.setAssetManager(this.assetManager);
272
-
273
-
274
- if (enableGraphics !== false) {
275
-
276
- /**
277
- * @type {GraphicsEngine3}
278
- */
279
- const graphicsEngine = new GraphicsEngine3();
280
-
281
- this.graphics = graphicsEngine;
282
-
283
- // The renderer is not started here. Acquiring a WebGPU device is asynchronous and a
284
- // constructor is the wrong place to fail from, so `start()` does it — which is also
285
- // what makes the device restartable (E1).
286
-
287
- graphicsEngine.on.contextLost.add(this.#handle_context_lost, this);
288
- graphicsEngine.on.contextRestored.add(this.#handle_context_restored, this);
289
- graphicsEngine.on.contextFailed.add(this.#handle_context_failed, this);
290
-
291
- } else {
292
- logger.info('enableGraphics option is not set, no graphics engine will be created');
293
- }
294
-
295
- if (enableAudio !== false) {
296
- //sound engine
297
- const soundEngine = new SoundEngine();
298
- soundEngine.volume = 1;
299
-
300
- /**
301
- *
302
- * @type {SoundEngine}
303
- */
304
- this.sound = soundEngine;
305
- } else {
306
- logger.info('enableAudio option is not set, no audio engine will be created');
307
- }
308
-
309
- /**
310
- * Graphical User Interface engine
311
- * @type {GUIEngine}
312
- */
313
- this.gui = new GUIEngine();
314
-
315
- /**
316
- * @readonly
317
- * @type {SceneManager}
318
- */
319
- this.sceneManager = new SceneManager(this.entityManager, this.ticker.clock);
320
-
321
- this.initializeViews();
322
-
323
- this.devices = {
324
- pointer: new PointerDevice(this.viewStack.el),
325
- keyboard: new KeyboardDevice(this.viewStack.el),
326
- gamepad: new GamepadDevice()
327
- };
328
-
329
- this.devices.pointer.start();
330
- this.devices.keyboard.start();
331
- this.devices.gamepad.start();
332
-
333
- //process settings
334
- this.initializeSettings();
335
-
336
- logger.info("engine initialized");
337
-
338
- /**
339
- * Toggles GraphicsEngine rendering on and off
340
- * @type {boolean}
341
- */
342
- this.renderingEnabled = true;
343
-
344
-
345
- this.plugins.initialize(this);
346
- }
347
-
348
- #clear_context_loss_pause_timer() {
349
- if (this.#context_loss_pause_timer !== -1) {
350
- clearTimeout(this.#context_loss_pause_timer);
351
- this.#context_loss_pause_timer = -1;
352
- }
353
- }
354
-
355
- /**
356
- * Pauses the simulation, if it is running. {@link Ticker#pause} freezes the clock, so no simulation
357
- * time accrues while we wait and the first step after resuming is a normal-sized one.
358
- *
359
- * A ticker that is already paused is left alone - somebody else owns that pause and it is not ours to
360
- * undo when the context comes back.
361
- */
362
- #pause_simulation_for_context_loss() {
363
- this.#context_loss_pause_timer = -1;
364
-
365
- if (this.#paused_by_context_loss) {
366
- return;
367
- }
368
-
369
- const ticker = this.ticker;
370
-
371
- if (!ticker.is_active || ticker.is_paused) {
372
- return;
373
- }
374
-
375
- this.#paused_by_context_loss = true;
376
-
377
- logger.warn('Graphics context outage is taking a while, pausing simulation');
378
-
379
- ticker.pause();
380
- }
381
-
382
- #handle_context_lost() {
383
- logger.warn('Graphics context lost, waiting for recovery');
384
-
385
- this.#clear_context_loss_pause_timer();
386
-
387
- this.#context_loss_pause_timer = setTimeout(
388
- () => this.#pause_simulation_for_context_loss(),
389
- CONTEXT_LOSS_SIMULATION_PAUSE_DELAY * 1000
390
- );
391
- }
392
-
393
- #handle_context_restored() {
394
- this.#clear_context_loss_pause_timer();
395
-
396
- if (this.#paused_by_context_loss) {
397
- this.#paused_by_context_loss = false;
398
-
399
- if (this.ticker.is_active) {
400
- this.ticker.resume();
401
- }
402
- }
403
-
404
- logger.info('Graphics context restored, rendering resumed');
405
- }
406
-
407
- /**
408
- * @param {ShadeDeviceFailure} reason carries a message written to be shown to a person
409
- */
410
- #handle_context_failed(reason) {
411
- logger.error(`Graphics context recovery abandoned (${reason}), no further rendering is possible`);
412
-
413
- this.#clear_context_loss_pause_timer();
414
-
415
- // nothing can be drawn any more, so let the simulation stop rather than burn cycles invisibly.
416
- // Application state is left intact, which keeps a save-on-failure handler viable.
417
- this.#pause_simulation_for_context_loss();
418
-
419
- this.viewStack.addChild(new GraphicsContextFailureView());
420
- }
421
-
422
- #initialize_audio() {
423
- const sound = this.sound;
424
- if (sound === null) {
425
- // no sound engine
426
- return;
427
- }
428
-
429
- // hook up context resumption to input
430
- if (this.devices.pointer !== undefined) {
431
-
432
- this.devices.pointer.on.down.addOne(sound.resumeContext, sound);
433
- this.devices.keyboard.on.down.addOne(sound.resumeContext, sound);
434
-
435
- }
436
- }
437
-
438
- initializeViews() {
439
-
440
- const gameView = new EmptyView();
441
-
442
- gameView.addClass('game-view');
443
-
444
- gameView.css({
445
- left: 0,
446
- top: 0,
447
- position: "absolute",
448
- pointerEvents: "none"
449
- });
450
- this.gameView = gameView;
451
-
452
- this.viewStack.push(gameView, 'game-view');
453
-
454
- if (this.graphics !== null) {
455
-
456
- const viewport = this.graphics.viewport;
457
-
458
- viewport.css({
459
- pointerEvents: "auto"
460
- });
461
-
462
- gameView.addChild(viewport);
463
- //bind size of renderer viewport to game view
464
- viewport.bindSignal(gameView.size.onChanged, viewport.size.set.bind(viewport.size));
465
- gameView.on.linked.add(function () {
466
- viewport.size.copy(gameView.size);
467
- });
468
-
469
- }
470
- }
471
-
472
- initializeSettings() {
473
- logger.info('Initializing engine settings...');
474
-
475
- const engine = this;
476
-
477
- function setViewportToWindowSize() {
478
- // get parent element
479
- let parentElement = engine.viewStack.el.parentElement;
480
-
481
- while (parentElement !== null && parentElement.innerWidth === undefined) {
482
- // traverse up until we find an element with defined dimensions
483
- parentElement = parentElement.parentElement;
484
- }
485
-
486
- if (parentElement === null || parentElement === undefined) {
487
- // no parent element, default to window
488
- parentElement = window;
489
- }
490
-
491
- engine.viewStack.size.set(parentElement.innerWidth, parentElement.innerHeight);
492
- }
493
-
494
- this.settings.graphics_control_viewport_size.process(function (value) {
495
- if (value) {
496
- setViewportToWindowSize();
497
- window.addEventListener("resize", setViewportToWindowSize, false);
498
- } else {
499
- window.removeEventListener("resize", setViewportToWindowSize);
500
- }
501
- });
502
-
503
- logger.info('Engine settings initilized.');
504
- }
505
-
506
- benchmark() {
507
- const duration = 2000;
508
- let count = 0;
509
- const t0 = Date.now();
510
- let t1;
511
- while (true) {
512
- this.entityManager.update(0.0000000001);
513
- t1 = Date.now();
514
- if (t1 - t0 > duration) {
515
- break;
516
- }
517
- count++;
518
- }
519
- //normalize
520
- const elapsed = (t1 - t0) / 1000;
521
- const rate = (count / elapsed);
522
- return rate;
523
- }
524
-
525
- /**
526
- * Returns preloader object
527
- * @param {String} listURL
528
- */
529
- loadAssetList(listURL) {
530
- const preloader = new AssetPreloader();
531
- const assetManager = this.assetManager;
532
- assetManager.get({
533
- path: listURL, type: "json", callback: function (asset) {
534
- preloader.addAll(asset.create());
535
- preloader.load(assetManager);
536
- }
537
- });
538
- return preloader;
539
- }
540
-
541
- render() {
542
- assert.isInstanceOf(this, Engine, 'this', 'Engine');
543
-
544
- const graphics = this.graphics;
545
-
546
- if (graphics === null) {
547
- // headless
548
- return;
549
- }
550
-
551
- if (graphics.autoDraw) {
552
- // request redraw
553
- graphics.needDraw = true;
554
- }
555
-
556
- if (this.renderingEnabled && graphics.needDraw) {
557
-
558
- const metrics = this.performance;
559
-
560
- const t0 = performance.now();
561
-
562
- graphics.render();
563
-
564
- const t1 = performance.now();
565
- const frame_time = (t1 - t0) / 1000;
566
-
567
- // record frame time
568
- metrics.get(METRIC_ID_RENDER).record(frame_time);
569
- }
570
- }
571
-
572
- /**
573
- * Startup
574
- * @returns {Promise}
575
- */
576
- async start() {
577
- // First, and awaited: systems read `graphics.viewport` and size themselves off it during
578
- // their own startup, so the device has to exist before the entity manager runs.
579
- if (this.graphics !== null) {
580
- await this.graphics.start();
581
- }
582
-
583
- this.assetManager.startup();
584
-
585
- this.#initialize_audio();
586
-
587
- const promiseEntityManager = () => {
588
- return new Promise((resolve, reject) => {
589
- //initialize entity manager
590
- this.entityManager.startup(resolve, reject);
591
- });
592
- }
593
-
594
- this.__performacne_monitor.start();
595
-
596
- const sound = this.sound;
597
-
598
- const soundStarted = sound === null
599
- ? Promise.resolve()
600
- : sound.start();
601
-
602
- const knowledge = this.staticKnowledge;
603
-
604
- // static knowledge is engine-lifetime content and a stop does not drop it, so a restart keeps
605
- // what the first start loaded. `load` accepts the Initial state only; callers that want the
606
- // tables re-read call `reset` first.
607
- const knowledgeLoaded = knowledge.state === StaticKnowledgeState.Initial
608
- ? knowledge.load(this.assetManager, this.executor)
609
- : Promise.resolve();
610
-
611
- return Promise.all([
612
- soundStarted.then(promiseEntityManager),
613
- knowledgeLoaded,
614
- this.gui.startup(this),
615
- this.plugins.startup()
616
- ]).then(async () => {
617
-
618
- this.#last_frame_timestamp = performance.now();
619
-
620
- /**
621
- * Starting the engine
622
- */
623
- this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
624
-
625
- //start simulation
626
- this.ticker.start({ maxTimeout: 200 });
627
- //self.uiController.init(self);
628
-
629
- //load options
630
- await this.options.attachToStorage('lazykitty.komrade.options', this.storage);
631
-
632
- logger.info('engine started');
633
- }, function (e) {
634
- logger.error(`Engine Failed to start: ${e}`);
635
-
636
- // the caller awaits start() to know whether the engine came up;
637
- // swallowing this reported success after a failed startup
638
- throw e;
639
- });
640
-
641
-
642
- }
643
-
644
- /**
645
- * Fired every animation frame via {@link requestAnimationFrame}
646
- */
647
- #animation_frame = () => {
648
-
649
- const t0 = this.#last_frame_timestamp;
650
- const t1 = performance.now();
651
- this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
652
- this.render();
653
-
654
- const frame_delay = (t1 - t0) / 1000;
655
-
656
- // swap variables
657
- this.#last_frame_timestamp = t1;
658
-
659
- // record metric
660
- this.performance.get(METRIC_ID_FRAME).record(frame_delay);
661
- }
662
-
663
- /**
664
- * Shutdown the engine, disposing all relevant resources
665
- */
666
- async stop() {
667
- this.__performacne_monitor.stop();
668
-
669
- // stop the ticker. pause() throws when the loop is not currently
670
- // running, which would abort the whole teardown below
671
- this.ticker.stop();
672
-
673
- // and the render loop, which re-requests itself every frame and would
674
- // otherwise keep calling render() on a torn-down engine forever
675
- cancelAnimationFrame(this.#animation_frame_handle);
676
- this.#animation_frame_handle = -1;
677
-
678
- // shutdown entity manager
679
- if (!this.__using_external_entity_manager) {
680
- await new Promise((resolve, reject) => this.entityManager.shutdown(resolve, reject));
681
- }
682
-
683
- // shutdown plugins
684
- await this.plugins.shutdown();
685
-
686
- // stop gui
687
- await this.gui.shutdown();
688
-
689
-
690
- // TODO shutdown executor
691
-
692
- await this.assetManager.shutdown();
693
-
694
- // last, so that everything above still has a live context to release its GPU resources through
695
- const graphics = this.graphics;
696
-
697
- if (graphics !== null) {
698
- graphics.stop();
699
- }
700
- }
701
-
702
- exit() {
703
- window.close();
704
- }
705
-
706
- /**
707
- * @returns {Promise}
708
- */
709
- requestExit() {
710
- return this.gui.confirmTextDialog({
711
- title: this.localization.getString('system_confirm_exit_to_system.title'),
712
- text: this.localization.getString('system_confirm_exit_to_system.text')
713
- }).then(() => {
714
- this.exit();
715
- });
716
- }
717
- }
718
-
719
-
720
- /**
721
- * @readonly
722
- * @type {boolean}
723
- */
724
- Engine.prototype.isEngine = true;
725
-
726
- export default Engine;
1
+ /**
2
+ *
3
+ */
4
+
5
+ import { assert } from "../core/assert.js";
6
+ import Vector1 from "../core/geom/Vector1.js";
7
+ import { Localization } from "../core/localization/Localization.js";
8
+ import { ModuleRegistry } from "../core/model/ModuleRegistry.js";
9
+ import ObservedBoolean from "../core/model/ObservedBoolean.js";
10
+ import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
11
+ import EmptyView from "../view/elements/EmptyView.js";
12
+ import { ViewStack } from "../view/elements/navigation/ViewStack.js";
13
+ import { GraphicsContextFailureView } from "../view/graphics/GraphicsContextFailureView.js";
14
+
15
+ import { AssetManager } from './asset/AssetManager.js';
16
+ import { AssetPreloader } from "./asset/preloader/AssetPreloader.js";
17
+ import { MetricCollection } from "./development/performance/MetricCollection.js";
18
+ import { MetricStatistics } from "./development/performance/MetricStatistics.js";
19
+ import { PeriodicConsolePrinter } from "./development/performance/monitor/PeriodicConsolePrinter.js";
20
+ import { EntityManager } from "./ecs/EntityManager.js";
21
+ import { BinarySerializationRegistry } from "./ecs/storage/binary/BinarySerializationRegistry.js";
22
+ import { GraphicsEngine } from './graphics3/GraphicsEngine.js';
23
+ import { GamepadDevice } from "./input/devices/GamepadDevice.js";
24
+ import KeyboardDevice from "./input/devices/KeyboardDevice.js";
25
+ import { PointerDevice } from "./input/devices/PointerDevice.js";
26
+ import { StaticKnowledgeDatabase, StaticKnowledgeState } from "./knowledge/database/StaticKnowledgeDatabase.js";
27
+ import { logger } from "./logging/GlobalLogger.js";
28
+ import { OptionGroup } from "./options/OptionGroup.js";
29
+ import { EnginePluginManager } from "./plugin/EnginePluginManager.js";
30
+ import SceneManager from "./scene/SceneManager.js";
31
+ import Ticker from "./simulation/Ticker.js";
32
+ import SoundEngine from './sound/SoundEngine.js';
33
+
34
+ import GUIEngine from './ui/GUIEngine.js';
35
+
36
+
37
+ class EngineSettings {
38
+ graphics_control_viewport_size = new ObservedBoolean(true);
39
+ simulation_speed = new Vector1(1);
40
+ input_mouse_sensitivity = new Vector1(5);
41
+ }
42
+
43
+ const METRIC_ID_FRAME = 'frame_delay';
44
+ const METRIC_ID_RENDER = 'render_time';
45
+ const METRIC_ID_SIMULATION = 'simulation_time';
46
+
47
+ /**
48
+ * How long a context loss is tolerated before the simulation is paused as well, in seconds. Most losses
49
+ * are resolved in well under a second, and stopping the world for those would be more disruptive than
50
+ * letting it run; a longer outage is worth pausing for, as the player cannot see what is happening.
51
+ * @type {number}
52
+ */
53
+ const CONTEXT_LOSS_SIMULATION_PAUSE_DELAY = 2;
54
+
55
+ class Engine {
56
+ #last_frame_timestamp = 0;
57
+
58
+ /**
59
+ * Handle of the pending render-loop frame, `-1` when the loop is not running
60
+ * @type {number}
61
+ */
62
+ #animation_frame_handle = -1;
63
+
64
+ /**
65
+ * Handle of the pending "pause the simulation, this outage is taking a while" timer, `-1` when none
66
+ * @type {number}
67
+ */
68
+ #context_loss_pause_timer = -1;
69
+
70
+ /**
71
+ * Whether the simulation was paused because of a context loss, and therefore should be resumed once
72
+ * the context comes back
73
+ * @type {boolean}
74
+ */
75
+ #paused_by_context_loss = false;
76
+
77
+ /**
78
+ * Absent when the engine is constructed with `enableGraphics: false`.
79
+ * @type {GraphicsEngine|null}
80
+ */
81
+ graphics = null;
82
+
83
+ /**
84
+ * Absent when the engine is constructed with `enableAudio: false`.
85
+ * @type {SoundEngine|null}
86
+ */
87
+ sound = null;
88
+
89
+ viewStack = new ViewStack();
90
+
91
+ /**
92
+ *
93
+ * Static database
94
+ * Can contain tables of structured data that the application often works with.
95
+ * Engine startup will load all tables ensuring that data is ready once startup finishes
96
+ * Use sparingly, this is not suitable for very large amounts of data as all the data will be in memory and deserialization will stall engine startup
97
+ * Example: inventory item table, monster table
98
+ * @readonly
99
+ * @type {StaticKnowledgeDatabase}
100
+ */
101
+ staticKnowledge = new StaticKnowledgeDatabase();
102
+
103
+ /**
104
+ * @readonly
105
+ * @type {EnginePluginManager}
106
+ */
107
+ plugins = new EnginePluginManager();
108
+
109
+ /**
110
+ * Main simulation ticker
111
+ * @readonly
112
+ * @type {Ticker}
113
+ */
114
+ ticker = new Ticker();
115
+
116
+ /**
117
+ * Default executor, enables time-sharing concurrency
118
+ * @readonly
119
+ * @type {ConcurrentExecutor}
120
+ */
121
+ executor = new ConcurrentExecutor(1, 10);
122
+
123
+ /**
124
+ *
125
+ * @param {EnginePlatform} platform
126
+ * @param {EntityManager} [entityManager]
127
+ * @param {boolean} [enableGraphics]
128
+ * @param {boolean} [enableAudio]
129
+ * @param {boolean} [debug]
130
+ * @constructor
131
+ */
132
+ constructor(platform, {
133
+ entityManager,
134
+ enableGraphics = true,
135
+ enableAudio = true,
136
+ debug = true
137
+ } = {}) {
138
+ assert.defined(platform, 'platform');
139
+
140
+ /**
141
+ *
142
+ * @type {EnginePlatform}
143
+ */
144
+ this.platform = platform;
145
+
146
+ this.staticKnowledge.validation_enabled = debug;
147
+
148
+
149
+ /**
150
+ *
151
+ * @type {MetricCollection}
152
+ */
153
+ this.performance = new MetricCollection();
154
+
155
+
156
+ this.__using_external_entity_manager = entityManager !== undefined;
157
+
158
+ //setup entity component system
159
+ if (this.__using_external_entity_manager) {
160
+ // external entity manager provided
161
+ this.entityManager = entityManager;
162
+ } else {
163
+ this.entityManager = new EntityManager();
164
+ }
165
+
166
+
167
+ /**
168
+ *
169
+ * @type {AssetManager<Engine>}
170
+ */
171
+ this.assetManager = new AssetManager({
172
+ context: this,
173
+ executor: this.executor
174
+ });
175
+
176
+ this.__performacne_monitor = new PeriodicConsolePrinter(15, () => {
177
+ const metrics = this.performance;
178
+ const stats = new MetricStatistics();
179
+
180
+ // RENDER
181
+ const m_render = metrics.get(METRIC_ID_RENDER);
182
+
183
+ m_render.computeStats(stats);
184
+
185
+ const v_render = (stats.mean * 1000).toFixed(2);
186
+
187
+ // SIMULATION
188
+ const m_sim = metrics.get(METRIC_ID_SIMULATION);
189
+
190
+ m_sim.computeStats(stats);
191
+
192
+ const v_sim = (stats.mean * 1000).toFixed(2);
193
+
194
+ // FPS
195
+
196
+ const m_frame = metrics.get(METRIC_ID_FRAME);
197
+
198
+ m_frame.computeStats(stats);
199
+
200
+ const v_fps = (1 / stats.mean).toFixed(2);
201
+
202
+
203
+ // clear stats
204
+ m_render.clear();
205
+ m_sim.clear();
206
+ m_frame.clear();
207
+
208
+ return `FPS: ${v_fps}, RENDER: ${v_render}ms, SIMULATION: ${v_sim}ms`;
209
+ });
210
+
211
+
212
+ if (!this.__using_external_entity_manager) {
213
+ // subscribe simulator to common ticker
214
+ this.ticker.onTick.add(timeDelta => {
215
+ const t0 = performance.now();
216
+ this.entityManager.update(timeDelta);
217
+
218
+ const t1 = performance.now();
219
+ const duration = (t1 - t0) / 1000;
220
+
221
+ // record frame time
222
+ this.performance.get(METRIC_ID_SIMULATION).record(duration);
223
+ });
224
+ }
225
+
226
+ // initialize performance metrics
227
+ this.performance.create({
228
+ name: METRIC_ID_RENDER
229
+ });
230
+ this.performance.create({
231
+ name: METRIC_ID_SIMULATION
232
+ });
233
+ this.performance.create({
234
+ name: METRIC_ID_FRAME
235
+ });
236
+
237
+ /**
238
+ *
239
+ * @type {OptionGroup}
240
+ */
241
+ this.options = new OptionGroup("options");
242
+
243
+ /**
244
+ *
245
+ * @type {ModuleRegistry}
246
+ */
247
+ this.moduleRegistry = new ModuleRegistry();
248
+
249
+ /**
250
+ * @readonly
251
+ * @type {BinarySerializationRegistry}
252
+ */
253
+ this.binarySerializationRegistry = new BinarySerializationRegistry();
254
+
255
+ this.settings = new EngineSettings();
256
+
257
+
258
+ /**
259
+ * @deprecated use plugins instead
260
+ */
261
+ this.services = {};
262
+
263
+ /**
264
+ *
265
+ * @type {Storage}
266
+ */
267
+ this.storage = this.platform.getStorage();
268
+
269
+
270
+ this.localization = new Localization();
271
+ this.localization.setAssetManager(this.assetManager);
272
+
273
+
274
+ if (enableGraphics !== false) {
275
+
276
+ /**
277
+ * @type {GraphicsEngine}
278
+ */
279
+ const graphicsEngine = new GraphicsEngine();
280
+
281
+ this.graphics = graphicsEngine;
282
+
283
+ // The renderer is not started here. Acquiring a WebGPU device is asynchronous and a
284
+ // constructor is the wrong place to fail from, so `start()` does it — which is also
285
+ // what makes the device restartable (E1).
286
+
287
+ graphicsEngine.on.contextLost.add(this.#handle_context_lost, this);
288
+ graphicsEngine.on.contextRestored.add(this.#handle_context_restored, this);
289
+ graphicsEngine.on.contextFailed.add(this.#handle_context_failed, this);
290
+
291
+ } else {
292
+ logger.info('enableGraphics option is not set, no graphics engine will be created');
293
+ }
294
+
295
+ if (enableAudio !== false) {
296
+ //sound engine
297
+ const soundEngine = new SoundEngine();
298
+ soundEngine.volume = 1;
299
+
300
+ /**
301
+ *
302
+ * @type {SoundEngine}
303
+ */
304
+ this.sound = soundEngine;
305
+ } else {
306
+ logger.info('enableAudio option is not set, no audio engine will be created');
307
+ }
308
+
309
+ /**
310
+ * Graphical User Interface engine
311
+ * @type {GUIEngine}
312
+ */
313
+ this.gui = new GUIEngine();
314
+
315
+ /**
316
+ * @readonly
317
+ * @type {SceneManager}
318
+ */
319
+ this.sceneManager = new SceneManager(this.entityManager, this.ticker.clock);
320
+
321
+ this.initializeViews();
322
+
323
+ this.devices = {
324
+ pointer: new PointerDevice(this.viewStack.el),
325
+ keyboard: new KeyboardDevice(this.viewStack.el),
326
+ gamepad: new GamepadDevice()
327
+ };
328
+
329
+ this.devices.pointer.start();
330
+ this.devices.keyboard.start();
331
+ this.devices.gamepad.start();
332
+
333
+ //process settings
334
+ this.initializeSettings();
335
+
336
+ logger.info("engine initialized");
337
+
338
+ /**
339
+ * Toggles GraphicsEngine rendering on and off
340
+ * @type {boolean}
341
+ */
342
+ this.renderingEnabled = true;
343
+
344
+
345
+ this.plugins.initialize(this);
346
+ }
347
+
348
+ #clear_context_loss_pause_timer() {
349
+ if (this.#context_loss_pause_timer !== -1) {
350
+ clearTimeout(this.#context_loss_pause_timer);
351
+ this.#context_loss_pause_timer = -1;
352
+ }
353
+ }
354
+
355
+ /**
356
+ * Pauses the simulation, if it is running. {@link Ticker#pause} freezes the clock, so no simulation
357
+ * time accrues while we wait and the first step after resuming is a normal-sized one.
358
+ *
359
+ * A ticker that is already paused is left alone - somebody else owns that pause and it is not ours to
360
+ * undo when the context comes back.
361
+ */
362
+ #pause_simulation_for_context_loss() {
363
+ this.#context_loss_pause_timer = -1;
364
+
365
+ if (this.#paused_by_context_loss) {
366
+ return;
367
+ }
368
+
369
+ const ticker = this.ticker;
370
+
371
+ if (!ticker.is_active || ticker.is_paused) {
372
+ return;
373
+ }
374
+
375
+ this.#paused_by_context_loss = true;
376
+
377
+ logger.warn('Graphics context outage is taking a while, pausing simulation');
378
+
379
+ ticker.pause();
380
+ }
381
+
382
+ #handle_context_lost() {
383
+ logger.warn('Graphics context lost, waiting for recovery');
384
+
385
+ this.#clear_context_loss_pause_timer();
386
+
387
+ this.#context_loss_pause_timer = setTimeout(
388
+ () => this.#pause_simulation_for_context_loss(),
389
+ CONTEXT_LOSS_SIMULATION_PAUSE_DELAY * 1000
390
+ );
391
+ }
392
+
393
+ #handle_context_restored() {
394
+ this.#clear_context_loss_pause_timer();
395
+
396
+ if (this.#paused_by_context_loss) {
397
+ this.#paused_by_context_loss = false;
398
+
399
+ if (this.ticker.is_active) {
400
+ this.ticker.resume();
401
+ }
402
+ }
403
+
404
+ logger.info('Graphics context restored, rendering resumed');
405
+ }
406
+
407
+ /**
408
+ * @param {ShadeDeviceFailure} reason carries a message written to be shown to a person
409
+ */
410
+ #handle_context_failed(reason) {
411
+ logger.error(`Graphics context recovery abandoned (${reason}), no further rendering is possible`);
412
+
413
+ this.#clear_context_loss_pause_timer();
414
+
415
+ // nothing can be drawn any more, so let the simulation stop rather than burn cycles invisibly.
416
+ // Application state is left intact, which keeps a save-on-failure handler viable.
417
+ this.#pause_simulation_for_context_loss();
418
+
419
+ this.viewStack.addChild(new GraphicsContextFailureView());
420
+ }
421
+
422
+ #initialize_audio() {
423
+ const sound = this.sound;
424
+ if (sound === null) {
425
+ // no sound engine
426
+ return;
427
+ }
428
+
429
+ // hook up context resumption to input
430
+ if (this.devices.pointer !== undefined) {
431
+
432
+ this.devices.pointer.on.down.addOne(sound.resumeContext, sound);
433
+ this.devices.keyboard.on.down.addOne(sound.resumeContext, sound);
434
+
435
+ }
436
+ }
437
+
438
+ initializeViews() {
439
+
440
+ const gameView = new EmptyView();
441
+
442
+ gameView.addClass('game-view');
443
+
444
+ gameView.css({
445
+ left: 0,
446
+ top: 0,
447
+ position: "absolute",
448
+ pointerEvents: "none"
449
+ });
450
+ this.gameView = gameView;
451
+
452
+ this.viewStack.push(gameView, 'game-view');
453
+
454
+ if (this.graphics !== null) {
455
+
456
+ const viewport = this.graphics.viewport;
457
+
458
+ viewport.css({
459
+ pointerEvents: "auto"
460
+ });
461
+
462
+ gameView.addChild(viewport);
463
+ //bind size of renderer viewport to game view
464
+ viewport.bindSignal(gameView.size.onChanged, viewport.size.set.bind(viewport.size));
465
+ gameView.on.linked.add(function () {
466
+ viewport.size.copy(gameView.size);
467
+ });
468
+
469
+ }
470
+ }
471
+
472
+ initializeSettings() {
473
+ logger.info('Initializing engine settings...');
474
+
475
+ const engine = this;
476
+
477
+ function setViewportToWindowSize() {
478
+ // get parent element
479
+ let parentElement = engine.viewStack.el.parentElement;
480
+
481
+ while (parentElement !== null && parentElement.innerWidth === undefined) {
482
+ // traverse up until we find an element with defined dimensions
483
+ parentElement = parentElement.parentElement;
484
+ }
485
+
486
+ if (parentElement === null || parentElement === undefined) {
487
+ // no parent element, default to window
488
+ parentElement = window;
489
+ }
490
+
491
+ engine.viewStack.size.set(parentElement.innerWidth, parentElement.innerHeight);
492
+ }
493
+
494
+ this.settings.graphics_control_viewport_size.process(function (value) {
495
+ if (value) {
496
+ setViewportToWindowSize();
497
+ window.addEventListener("resize", setViewportToWindowSize, false);
498
+ } else {
499
+ window.removeEventListener("resize", setViewportToWindowSize);
500
+ }
501
+ });
502
+
503
+ logger.info('Engine settings initilized.');
504
+ }
505
+
506
+ benchmark() {
507
+ const duration = 2000;
508
+ let count = 0;
509
+ const t0 = Date.now();
510
+ let t1;
511
+ while (true) {
512
+ this.entityManager.update(0.0000000001);
513
+ t1 = Date.now();
514
+ if (t1 - t0 > duration) {
515
+ break;
516
+ }
517
+ count++;
518
+ }
519
+ //normalize
520
+ const elapsed = (t1 - t0) / 1000;
521
+ const rate = (count / elapsed);
522
+ return rate;
523
+ }
524
+
525
+ /**
526
+ * Returns preloader object
527
+ * @param {String} listURL
528
+ */
529
+ loadAssetList(listURL) {
530
+ const preloader = new AssetPreloader();
531
+ const assetManager = this.assetManager;
532
+ assetManager.get({
533
+ path: listURL, type: "json", callback: function (asset) {
534
+ preloader.addAll(asset.create());
535
+ preloader.load(assetManager);
536
+ }
537
+ });
538
+ return preloader;
539
+ }
540
+
541
+ render() {
542
+ assert.isInstanceOf(this, Engine, 'this', 'Engine');
543
+
544
+ const graphics = this.graphics;
545
+
546
+ if (graphics === null) {
547
+ // headless
548
+ return;
549
+ }
550
+
551
+ if (graphics.autoDraw) {
552
+ // request redraw
553
+ graphics.needDraw = true;
554
+ }
555
+
556
+ if (this.renderingEnabled && graphics.needDraw) {
557
+
558
+ const metrics = this.performance;
559
+
560
+ const t0 = performance.now();
561
+
562
+ graphics.render();
563
+
564
+ const t1 = performance.now();
565
+ const frame_time = (t1 - t0) / 1000;
566
+
567
+ // record frame time
568
+ metrics.get(METRIC_ID_RENDER).record(frame_time);
569
+ }
570
+ }
571
+
572
+ /**
573
+ * Startup
574
+ * @returns {Promise}
575
+ */
576
+ async start() {
577
+ // First, and awaited: systems read `graphics.viewport` and size themselves off it during
578
+ // their own startup, so the device has to exist before the entity manager runs.
579
+ if (this.graphics !== null) {
580
+ await this.graphics.start();
581
+ }
582
+
583
+ this.assetManager.startup();
584
+
585
+ this.#initialize_audio();
586
+
587
+ const promiseEntityManager = () => {
588
+ return new Promise((resolve, reject) => {
589
+ //initialize entity manager
590
+ this.entityManager.startup(resolve, reject);
591
+ });
592
+ }
593
+
594
+ this.__performacne_monitor.start();
595
+
596
+ const sound = this.sound;
597
+
598
+ const soundStarted = sound === null
599
+ ? Promise.resolve()
600
+ : sound.start();
601
+
602
+ const knowledge = this.staticKnowledge;
603
+
604
+ // static knowledge is engine-lifetime content and a stop does not drop it, so a restart keeps
605
+ // what the first start loaded. `load` accepts the Initial state only; callers that want the
606
+ // tables re-read call `reset` first.
607
+ const knowledgeLoaded = knowledge.state === StaticKnowledgeState.Initial
608
+ ? knowledge.load(this.assetManager, this.executor)
609
+ : Promise.resolve();
610
+
611
+ return Promise.all([
612
+ soundStarted.then(promiseEntityManager),
613
+ knowledgeLoaded,
614
+ this.gui.startup(this),
615
+ this.plugins.startup()
616
+ ]).then(async () => {
617
+
618
+ this.#last_frame_timestamp = performance.now();
619
+
620
+ /**
621
+ * Starting the engine
622
+ */
623
+ this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
624
+
625
+ //start simulation
626
+ this.ticker.start({ maxTimeout: 200 });
627
+ //self.uiController.init(self);
628
+
629
+ //load options
630
+ await this.options.attachToStorage('lazykitty.komrade.options', this.storage);
631
+
632
+ logger.info('engine started');
633
+ }, function (e) {
634
+ logger.error(`Engine Failed to start: ${e}`);
635
+
636
+ // the caller awaits start() to know whether the engine came up;
637
+ // swallowing this reported success after a failed startup
638
+ throw e;
639
+ });
640
+
641
+
642
+ }
643
+
644
+ /**
645
+ * Fired every animation frame via {@link requestAnimationFrame}
646
+ */
647
+ #animation_frame = () => {
648
+
649
+ const t0 = this.#last_frame_timestamp;
650
+ const t1 = performance.now();
651
+ this.#animation_frame_handle = requestAnimationFrame(this.#animation_frame);
652
+ this.render();
653
+
654
+ const frame_delay = (t1 - t0) / 1000;
655
+
656
+ // swap variables
657
+ this.#last_frame_timestamp = t1;
658
+
659
+ // record metric
660
+ this.performance.get(METRIC_ID_FRAME).record(frame_delay);
661
+ }
662
+
663
+ /**
664
+ * Shutdown the engine, disposing all relevant resources
665
+ */
666
+ async stop() {
667
+ this.__performacne_monitor.stop();
668
+
669
+ // stop the ticker. pause() throws when the loop is not currently
670
+ // running, which would abort the whole teardown below
671
+ this.ticker.stop();
672
+
673
+ // and the render loop, which re-requests itself every frame and would
674
+ // otherwise keep calling render() on a torn-down engine forever
675
+ cancelAnimationFrame(this.#animation_frame_handle);
676
+ this.#animation_frame_handle = -1;
677
+
678
+ // shutdown entity manager
679
+ if (!this.__using_external_entity_manager) {
680
+ await new Promise((resolve, reject) => this.entityManager.shutdown(resolve, reject));
681
+ }
682
+
683
+ // shutdown plugins
684
+ await this.plugins.shutdown();
685
+
686
+ // stop gui
687
+ await this.gui.shutdown();
688
+
689
+
690
+ // TODO shutdown executor
691
+
692
+ await this.assetManager.shutdown();
693
+
694
+ // last, so that everything above still has a live context to release its GPU resources through
695
+ const graphics = this.graphics;
696
+
697
+ if (graphics !== null) {
698
+ graphics.stop();
699
+ }
700
+ }
701
+
702
+ exit() {
703
+ window.close();
704
+ }
705
+
706
+ /**
707
+ * @returns {Promise}
708
+ */
709
+ requestExit() {
710
+ return this.gui.confirmTextDialog({
711
+ title: this.localization.getString('system_confirm_exit_to_system.title'),
712
+ text: this.localization.getString('system_confirm_exit_to_system.text')
713
+ }).then(() => {
714
+ this.exit();
715
+ });
716
+ }
717
+ }
718
+
719
+
720
+ /**
721
+ * @readonly
722
+ * @type {boolean}
723
+ */
724
+ Engine.prototype.isEngine = true;
725
+
726
+ export default Engine;