@woosh/meep-engine 3.59.0 → 3.60.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 (326) hide show
  1. package/package.json +1 -1
  2. package/src/shade/playground/probe_clipmap/index.html +12 -0
  3. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  4. package/src/shade/playground/probe_clipmap/main.js +5 -0
  5. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  6. package/src/shade/renderer/Renderer.js +4 -6
  7. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +63 -1
  8. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  9. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +228 -16
  10. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +27 -4
  11. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  12. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +526 -23
  13. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts +11 -0
  14. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts.map +1 -0
  15. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.js +21 -0
  16. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts +65 -0
  17. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts.map +1 -0
  18. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +376 -0
  19. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts +7 -3
  20. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts.map +1 -1
  21. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.js +70 -6
  22. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts +20 -0
  23. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts.map +1 -0
  24. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.js +80 -0
  25. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts +18 -0
  26. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts.map +1 -0
  27. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.js +113 -0
  28. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +47 -0
  29. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +1 -0
  30. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +80 -0
  31. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +91 -0
  32. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -0
  33. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +902 -0
  34. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +16 -0
  35. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +1 -0
  36. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +67 -0
  37. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +17 -0
  38. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +1 -0
  39. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +145 -0
  40. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +12 -0
  41. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +1 -0
  42. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +105 -0
  43. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.d.ts.map +1 -1
  44. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.js +2 -1
  45. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +3 -9
  46. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  47. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +13 -31
  48. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +764 -48
  49. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +410 -0
  50. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +3 -2
  51. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  52. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +4 -3
  53. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +41 -17
  54. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  55. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +57 -33
  56. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts +11 -3
  57. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts.map +1 -1
  58. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.js +13 -4
  59. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +9 -18
  60. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  61. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +8 -10
  62. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts +12 -0
  63. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts.map +1 -1
  64. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.js +28 -0
  65. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +1 -29
  66. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  67. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +1 -74
  68. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts +161 -0
  69. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts.map +1 -0
  70. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.js +219 -0
  71. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts +1 -8
  72. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts.map +1 -1
  73. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.js +1 -9
  74. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts +40 -12
  75. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts.map +1 -1
  76. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.js +373 -31
  77. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -1
  78. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts.map +1 -1
  79. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -1
  80. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts +15 -8
  81. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts.map +1 -1
  82. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js +28 -14
  83. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts +23 -0
  84. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts.map +1 -0
  85. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.js +66 -0
  86. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts +29 -0
  87. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts.map +1 -0
  88. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.js +210 -0
  89. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts +29 -0
  90. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts.map +1 -0
  91. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.js +86 -0
  92. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts +41 -0
  93. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts.map +1 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.js +439 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts +23 -0
  96. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts.map +1 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.js +135 -0
  98. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts +3 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts.map +1 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.js +12 -3
  101. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +21 -18
  102. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +254 -73
  104. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +149 -8
  105. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  106. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +181 -13
  107. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +179 -7
  108. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +412 -31
  110. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +4 -4
  111. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +4 -3
  113. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +36 -10
  114. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  115. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +218 -29
  116. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +5 -1
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +24 -14
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +15 -6
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +21 -22
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts +36 -0
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts.map +1 -0
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.js +257 -0
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +18 -7
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +157 -51
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts +23 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.js +110 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +24 -2
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +90 -10
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts +45 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts.map +1 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.js +205 -0
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts +16 -3
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +55 -10
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +19 -4
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +60 -6
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts +4 -8
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +21 -36
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +21 -14
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +100 -30
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts +6 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.js +26 -10
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +3 -2
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +12 -12
  156. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts +10 -0
  157. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts.map +1 -0
  158. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.js +21 -0
  159. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts +5 -2
  160. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts.map +1 -1
  161. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.js +31 -23
  162. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts +10 -0
  163. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts.map +1 -0
  164. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.js +22 -0
  165. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts +9 -0
  166. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts.map +1 -0
  167. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.js +18 -0
  168. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts +8 -3
  169. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts.map +1 -1
  170. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.js +41 -32
  171. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts +31 -0
  172. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts.map +1 -0
  173. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.js +71 -0
  174. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts +47 -0
  175. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts.map +1 -0
  176. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.js +210 -0
  177. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +5 -4
  178. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts.map +1 -1
  179. package/src/shade/renderer/gpu_primitive/sort/defs.js +5 -4
  180. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +56 -15
  181. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  182. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +410 -61
  183. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts +4 -1
  184. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  185. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +16 -42
  186. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts +15 -0
  187. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts.map +1 -0
  188. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.js +60 -0
  189. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts +25 -0
  190. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts.map +1 -0
  191. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.js +89 -0
  192. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts +3 -8
  193. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  194. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +28 -160
  195. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts +12 -0
  196. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts.map +1 -0
  197. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.js +74 -0
  198. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts +3 -1
  199. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts.map +1 -1
  200. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.js +387 -188
  201. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +1 -1
  202. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +1 -1
  203. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  204. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +90 -72
  205. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts +5 -0
  206. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts.map +1 -1
  207. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.js +9 -0
  208. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts +13 -0
  209. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts.map +1 -0
  210. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.js +14 -0
  211. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts +10 -0
  212. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts.map +1 -0
  213. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.js +15 -0
  214. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts +4 -3
  215. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts.map +1 -1
  216. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.js +6 -5
  217. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts +17 -2
  218. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts.map +1 -1
  219. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.js +25 -57
  220. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts +13 -0
  221. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts.map +1 -0
  222. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.js +70 -0
  223. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts +10 -0
  224. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts.map +1 -0
  225. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.js +59 -0
  226. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts +12 -0
  227. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts.map +1 -0
  228. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.js +49 -0
  229. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.d.ts.map +1 -1
  230. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.js +1 -0
  231. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.d.ts.map +1 -1
  232. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.js +1 -0
  233. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.d.ts.map +1 -1
  234. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.js +2 -1
  235. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts +7 -0
  236. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  237. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +15 -6
  238. package/src/shade/renderer/scene/GPUSceneContext.d.ts +7 -1
  239. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  240. package/src/shade/renderer/scene/GPUSceneContext.js +26 -1
  241. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts +7 -7
  242. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts.map +1 -1
  243. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.js +262 -294
  244. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts +9 -0
  245. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts.map +1 -0
  246. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.js +21 -0
  247. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +43 -0
  248. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -0
  249. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +87 -0
  250. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts +7 -1
  251. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts.map +1 -1
  252. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.js +1 -1
  253. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts +21 -0
  254. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts.map +1 -0
  255. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.js +42 -0
  256. package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
  257. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +19 -0
  258. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
  259. package/src/shade/wgsl/emulator/CPUBitmapData.js +27 -0
  260. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  261. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +39 -18
  262. package/src/view/elements/progress/segmented/GhostTrail.d.ts +56 -0
  263. package/src/view/elements/progress/segmented/GhostTrail.d.ts.map +1 -0
  264. package/src/view/elements/progress/segmented/GhostTrail.js +98 -0
  265. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts +3 -1
  266. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts.map +1 -1
  267. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.js +3 -1
  268. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts +11 -0
  269. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts.map +1 -0
  270. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.js +15 -0
  271. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts +3 -0
  272. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts.map +1 -1
  273. package/src/view/elements/progress/segmented/SegmentDefinition.js +3 -0
  274. package/src/view/elements/progress/segmented/SegmentTier.d.ts +38 -0
  275. package/src/view/elements/progress/segmented/SegmentTier.d.ts.map +1 -0
  276. package/src/view/elements/progress/segmented/SegmentTier.js +50 -0
  277. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +155 -10
  278. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
  279. package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +427 -101
  280. package/src/view/elements/progress/segmented/playground/index.html +78 -0
  281. package/src/view/elements/progress/segmented/playground/main.d.ts +2 -0
  282. package/src/view/elements/progress/segmented/playground/main.d.ts.map +1 -0
  283. package/src/view/elements/progress/segmented/playground/main.js +173 -0
  284. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts +48 -0
  285. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts.map +1 -0
  286. package/src/view/elements/progress/segmented/segment_cell_layout.js +75 -0
  287. package/src/view/elements/progress/segmented/segment_notch_place.d.ts +18 -0
  288. package/src/view/elements/progress/segmented/segment_notch_place.d.ts.map +1 -0
  289. package/src/view/elements/progress/segmented/segment_notch_place.js +28 -0
  290. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts +32 -0
  291. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts.map +1 -0
  292. package/src/view/elements/progress/segmented/segment_tick_positions.js +103 -0
  293. package/src/view/elements/progress/segmented/segmented-resource-bar.css +142 -0
  294. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts +0 -35
  295. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts.map +0 -1
  296. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.js +0 -238
  297. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts +0 -99
  298. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts.map +0 -1
  299. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.js +0 -139
  300. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts +0 -65
  301. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts.map +0 -1
  302. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.js +0 -393
  303. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts +0 -17
  304. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts.map +0 -1
  305. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.js +0 -36
  306. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts +0 -29
  307. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts.map +0 -1
  308. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.js +0 -108
  309. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts +0 -31
  310. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts.map +0 -1
  311. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.js +0 -113
  312. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts +0 -36
  313. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts.map +0 -1
  314. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.js +0 -85
  315. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts +0 -23
  316. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts.map +0 -1
  317. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.js +0 -273
  318. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts +0 -13
  319. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts.map +0 -1
  320. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.js +0 -151
  321. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts +0 -13
  322. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts.map +0 -1
  323. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.js +0 -133
  324. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts +0 -22
  325. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts.map +0 -1
  326. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.js +0 -135
@@ -5,27 +5,85 @@ import { clamp01 } from "../../../../core/math/clamp01.js";
5
5
  import ListView from "../../../common/ListView.js";
6
6
  import { DomSizeObserver } from "../../../util/DomSizeObserver.js";
7
7
  import View from "../../../View.js";
8
- import { CanvasView } from "../../CanvasView.js";
9
8
  import EmptyView from "../../EmptyView.js";
10
- import { RESOURCE_BAR_SEGMENTS } from "./RESOURCE_BAR_SEGMENTS.js";
9
+ import { GhostTrail } from "./GhostTrail.js";
10
+ import { SEGMENT_TIERS_DEFAULT } from "./SEGMENT_TIERS_DEFAULT.js";
11
+ import { segment_cell_layout } from "./segment_cell_layout.js";
12
+ import { segment_notch_place } from "./segment_notch_place.js";
13
+ import { segment_tick_positions } from "./segment_tick_positions.js";
14
+
15
+ /**
16
+ * A width change smaller than this, in CSS pixels, does not rebuild the notches
17
+ * @type {number}
18
+ */
19
+ const REBUILD_WIDTH_THRESHOLD_PX = 0.5;
20
+
21
+ /**
22
+ * Cell fills within this of a whole cell count as whole, so 7 of 30 rounds is 7 full cells and not 7 and a sliver
23
+ * @type {number}
24
+ */
25
+ const CELL_FILL_TOLERANCE = 1e-9;
26
+
27
+ const CELL_STATE_EMPTY = 0;
28
+ const CELL_STATE_PARTIAL = 1;
29
+ const CELL_STATE_FILLED = 2;
30
+
31
+ const CELL_STATE_CLASS = ['cell empty', 'cell partial', 'cell filled'];
32
+
33
+ /**
34
+ * @param {number} x
35
+ * @returns {number}
36
+ */
37
+ function snap_whole(x) {
38
+ const r = Math.round(x);
39
+
40
+ return Math.abs(x - r) <= CELL_FILL_TOLERANCE ? r : x;
41
+ }
11
42
 
43
+ /**
44
+ * Resource bar in the style of a MOBA health bar: the values fill it end to end, notches mark fixed amounts, and
45
+ * a ghost behind the fill trails a drop so the loss stays readable for a moment.
46
+ *
47
+ * Two modes:
48
+ * - notches (default): a continuous fill, with a notch at every multiple of each {@link SegmentTier}'s unit;
49
+ * - cells (`cells` given): `count` separate cells with exact, identical gaps, for counting rounds and the like.
50
+ *
51
+ * Notches and cells sit on whole device pixels at any pixel ratio and under a CSS scale. Colours, notch heights
52
+ * and the ghost are styled by `segmented-resource-bar.css` through `--segmented-bar-*` custom properties.
53
+ */
12
54
  export class SegmentedResourceBarView extends View {
13
55
  /**
14
56
  *
15
57
  * @param {Object} options
16
- * @param {(Vector1|ObservedInteger)[]} options.values
58
+ * @param {(Vector1|ObservedInteger)[]} options.values stacked end to end, value 0 first; their total is clamped to max
17
59
  * @param {Vector1|ObservedInteger|ReactiveExpression} [options.max=1]
18
60
  * @param {string[]} [options.classList]
61
+ * @param {{unit:number, class_name:string, width_px:number, min_spacing_px:number}[]} [options.tiers] notch tiers, finest first; see {@link SegmentTier}
62
+ * @param {{count:number, group:number}|null} [options.cells] draw `count` cells instead of notches, in groups of `group` (0 for none)
63
+ * @param {number} [options.ghost_delay_ms=450] how long the ghost holds after a drop
64
+ * @param {number} [options.ghost_duration_ms=350] how long the ghost then takes to catch up; 0 under prefers-reduced-motion
19
65
  */
20
66
  constructor({
21
67
  values,
22
68
  max = Vector1.one,
23
- classList = []
69
+ classList = [],
70
+ tiers = SEGMENT_TIERS_DEFAULT,
71
+ cells = null,
72
+ ghost_delay_ms = 450,
73
+ ghost_duration_ms = 350
24
74
  }) {
25
75
  super();
26
76
 
27
77
  assert.isArray(values, 'values');
28
78
  assert.defined(max, 'max');
79
+ assert.isArray(tiers, 'tiers');
80
+ assert.isNumber(ghost_delay_ms, 'ghost_delay_ms');
81
+ assert.isNumber(ghost_duration_ms, 'ghost_duration_ms');
82
+
83
+ if (cells !== null) {
84
+ assert.isNonNegativeInteger(cells.count, 'cells.count');
85
+ assert.isNonNegativeInteger(cells.group, 'cells.group');
86
+ }
29
87
 
30
88
  /**
31
89
  *
@@ -41,6 +99,69 @@ export class SegmentedResourceBarView extends View {
41
99
  */
42
100
  this.__value_max = max;
43
101
 
102
+ /**
103
+ * @type {{unit:number, class_name:string, width_px:number, min_spacing_px:number}[]}
104
+ * @private
105
+ */
106
+ this.__tiers = tiers;
107
+
108
+ /**
109
+ * @type {{count:number, group:number}|null}
110
+ * @private
111
+ */
112
+ this.__cells = cells;
113
+
114
+ /**
115
+ * @type {GhostTrail}
116
+ * @private
117
+ */
118
+ this.__ghost = new GhostTrail();
119
+ this.__ghost.delay_ms = ghost_delay_ms;
120
+
121
+ /**
122
+ * @type {number}
123
+ * @private
124
+ */
125
+ this.__ghost_duration_ms = ghost_duration_ms;
126
+
127
+ /**
128
+ * Total fill as a fraction of max, as last drawn
129
+ * @type {number}
130
+ * @private
131
+ */
132
+ this.__total_fraction = 0;
133
+
134
+ /**
135
+ * @type {MediaQueryList|null}
136
+ * @private
137
+ */
138
+ this.__reduced_motion = typeof matchMedia === 'function' ? matchMedia('(prefers-reduced-motion: reduce)') : null;
139
+
140
+ /**
141
+ * Watches for the device pixel ratio moving off the one the layout was built for
142
+ * @type {MediaQueryList|null}
143
+ * @private
144
+ */
145
+ this.__dpr_query = null;
146
+
147
+ this.__handle_dpr_change = this.__handle_dpr_change.bind(this);
148
+
149
+ this.__frame_pending = false;
150
+ this.__frame_id = 0;
151
+ this.__animate_ghost = this.__animate_ghost.bind(this);
152
+
153
+ // what the layout was last built for, so it is rebuilt only when one of them moves
154
+ this.__built_max = NaN;
155
+ this.__built_width = NaN;
156
+ this.__built_ratio = NaN;
157
+ this.__built_origin_phase = NaN;
158
+
159
+ /**
160
+ * scratch for {@link segment_notch_place}
161
+ * @type {Float64Array}
162
+ * @private
163
+ */
164
+ this.__place = new Float64Array(2);
44
165
 
45
166
  /**
46
167
  *
@@ -52,31 +173,93 @@ export class SegmentedResourceBarView extends View {
52
173
  this.el = document.createElement('div');
53
174
 
54
175
  this.addClass('ui-segmented-resource-bar-view');
176
+ this.addClass(cells === null ? 'mode-notches' : 'mode-cells');
55
177
 
56
178
  this.addClasses(classList);
57
179
 
180
+ // build structure; the ghost goes first so the fills paint over it
58
181
 
59
- // build structure
60
- this.__v__fill = new EmptyView({ classList: ['fill-container'] });
61
- this.addChild(this.__v__fill);
182
+ /**
183
+ * @type {HTMLElement}
184
+ * @private
185
+ */
186
+ this.__el_ghost = document.createElement('div');
187
+ this.__el_ghost.className = 'ghost';
62
188
 
189
+ /**
190
+ * @type {HTMLElement[]}
191
+ * @private
192
+ */
63
193
  this.__value_fills = [];
64
194
 
65
- for (let i = 0; i < this.__values_current.length; i++) {
66
- const v_value = new EmptyView({ classList: ['fill', `value-${i}`] });
195
+ /**
196
+ * @type {HTMLElement[]}
197
+ * @private
198
+ */
199
+ this.__notch_elements = [];
67
200
 
68
- this.__v__fill.addChild(v_value);
69
- this.__value_fills[i] = v_value;
70
- }
201
+ /**
202
+ * @type {HTMLElement[]}
203
+ * @private
204
+ */
205
+ this.__cell_elements = [];
206
+ this.__cell_fill_elements = [];
207
+ this.__cell_ghost_elements = [];
208
+ this.__cell_states = new Uint8Array(cells === null ? 0 : cells.count);
209
+
210
+ // what each cell's fill and ghost were last drawn at, so an animation frame writes only the cells that moved
211
+ this.__cell_fill_drawn = new Float64Array(cells === null ? 0 : cells.count);
212
+ this.__cell_ghost_drawn = new Float64Array(cells === null ? 0 : cells.count);
213
+
214
+ if (cells === null) {
215
+ this.el.appendChild(this.__el_ghost);
216
+
217
+ const el_fill_container = document.createElement('div');
218
+ el_fill_container.className = 'fill-container';
219
+
220
+ for (let i = 0; i < values.length; i++) {
221
+ const el_fill = document.createElement('div');
222
+ el_fill.className = `fill value-${i}`;
223
+
224
+ el_fill_container.appendChild(el_fill);
225
+ this.__value_fills[i] = el_fill;
226
+ }
227
+
228
+ this.el.appendChild(el_fill_container);
229
+
230
+ /**
231
+ * The notches' own box; what they are positioned in and what is measured to place them
232
+ * @type {HTMLElement}
233
+ * @private
234
+ */
235
+ this.__el_layout = document.createElement('div');
236
+ this.__el_layout.className = 'notches';
237
+ } else {
238
+ this.__el_layout = document.createElement('div');
239
+ this.__el_layout.className = 'cells';
71
240
 
72
- this.__v__ghost = new EmptyView({ classList: ['ghost'] });
73
- this.addChild(this.__v__ghost);
241
+ for (let i = 0; i < cells.count; i++) {
242
+ const el_cell = document.createElement('div');
243
+ el_cell.className = CELL_STATE_CLASS[CELL_STATE_EMPTY];
74
244
 
245
+ const el_cell_ghost = document.createElement('div');
246
+ el_cell_ghost.className = 'cell-ghost';
75
247
 
76
- this.__v_segments = new CanvasView();
77
- this.__v_segments.addClass('notch-overlay');
248
+ const el_cell_fill = document.createElement('div');
249
+ el_cell_fill.className = 'cell-fill';
78
250
 
79
- this.addChild(this.__v_segments);
251
+ el_cell.appendChild(el_cell_ghost);
252
+ el_cell.appendChild(el_cell_fill);
253
+
254
+ this.__el_layout.appendChild(el_cell);
255
+
256
+ this.__cell_elements[i] = el_cell;
257
+ this.__cell_ghost_elements[i] = el_cell_ghost;
258
+ this.__cell_fill_elements[i] = el_cell_fill;
259
+ }
260
+ }
261
+
262
+ this.el.appendChild(this.__el_layout);
80
263
 
81
264
 
82
265
  /**
@@ -131,15 +314,15 @@ export class SegmentedResourceBarView extends View {
131
314
  this.bindSignal(this.__value_max.onChanged, this.handleMaxChange, this);
132
315
 
133
316
  /**
134
- * We need an observer in order to know when we need to resize the canvas element that holds marks
317
+ * Tells us when the bar's width moves, so the notches or cells can be placed again
135
318
  * @type {DomSizeObserver}
136
319
  * @private
137
320
  */
138
321
  this.__sizeObserver = new DomSizeObserver();
139
322
 
140
- this.__sizeObserver.attach(this.el);
323
+ this.__sizeObserver.attach(this.__el_layout);
141
324
 
142
- this.__sizeObserver.dimensions.size.onChanged.add(this.__updateSize, this);
325
+ this.__sizeObserver.dimensions.size.onChanged.add(this.updateSegments, this);
143
326
  }
144
327
 
145
328
  link() {
@@ -147,10 +330,10 @@ export class SegmentedResourceBarView extends View {
147
330
  return;
148
331
  }
149
332
 
150
-
151
333
  super.link();
152
334
 
153
335
  this.__sizeObserver.start();
336
+ this.__watch_device_pixel_ratio();
154
337
  this.update();
155
338
  }
156
339
 
@@ -161,22 +344,22 @@ export class SegmentedResourceBarView extends View {
161
344
 
162
345
  this.__sizeObserver.stop();
163
346
 
347
+ if (this.__dpr_query !== null) {
348
+ this.__dpr_query.removeEventListener('change', this.__handle_dpr_change);
349
+ this.__dpr_query = null;
350
+ }
351
+
352
+ if (this.__frame_pending) {
353
+ cancelAnimationFrame(this.__frame_id);
354
+ this.__frame_pending = false;
355
+ }
356
+
164
357
  super.unlink();
165
358
  }
166
359
 
167
360
  update() {
168
- this.updateFill();
169
- this.updateSegments();
170
- }
171
-
172
- __updateSize() {
173
-
174
- if (this.__sizeObserver.dimensions.size.distanceSqrTo(this.__v_segments.size) < 0.5) {
175
- // change too small, ignore
176
- return;
177
- }
178
-
179
361
  this.updateSegments();
362
+ this.updateFill();
180
363
  }
181
364
 
182
365
  handleMaxChange() {
@@ -184,130 +367,273 @@ export class SegmentedResourceBarView extends View {
184
367
  this.updateFill();
185
368
  }
186
369
 
370
+ /**
371
+ * Place the notches or cells again, if the max, the bar's width (by {@link REBUILD_WIDTH_THRESHOLD_PX} or more),
372
+ * its pixel ratio or the device-pixel phase of its left edge has moved since they were last placed.
373
+ */
187
374
  updateSegments() {
375
+ const el = this.__el_layout;
376
+
188
377
  /**
189
- *
190
- * @type {Vector2}
378
+ * width as laid out, before any transform on an ancestor
379
+ * @type {number}
191
380
  */
192
- const size = this.__sizeObserver.dimensions.size;
381
+ const layout_width = el.offsetWidth;
193
382
 
383
+ if (!(layout_width > 0)) {
384
+ // not laid out (detached, display:none); nothing to place against
385
+ return;
386
+ }
194
387
 
195
- this.__v_segments.size.copy(size);
388
+ const rect = el.getBoundingClientRect();
196
389
 
197
- const vSegments = this.__v_segments;
390
+ const dpr = typeof devicePixelRatio === 'number' && devicePixelRatio > 0 ? devicePixelRatio : 1;
198
391
 
199
- vSegments.clear();
392
+ // a CSS scale on an ancestor shows each CSS pixel of the bar as `scale` page pixels
393
+ const scale = rect.width / layout_width;
200
394
 
201
- /**
202
- *
203
- * @type {CanvasRenderingContext2D}
204
- */
205
- const ctx = vSegments.context2d;
395
+ // device pixels per CSS pixel of the bar
396
+ const ratio = dpr * scale;
206
397
 
207
- const maxValue = this.__value_max.getValue();
398
+ const origin_device = rect.left * dpr;
399
+ const origin_phase = origin_device - Math.round(origin_device);
208
400
 
209
- // figure out what segments to use
210
- let major_segment_index = 0;
401
+ const max = this.__value_max.getValue();
211
402
 
212
- const max_segment_index = RESOURCE_BAR_SEGMENTS.length - 1;
213
- for (let i = max_segment_index; i >= 0; i--) {
214
- const segmentDefinition = RESOURCE_BAR_SEGMENTS[i];
403
+ if (
404
+ max === this.__built_max
405
+ && Math.abs(layout_width - this.__built_width) < REBUILD_WIDTH_THRESHOLD_PX
406
+ && ratio === this.__built_ratio
407
+ && origin_phase === this.__built_origin_phase
408
+ ) {
409
+ return;
410
+ }
215
411
 
216
- if (segmentDefinition.value <= maxValue && (i >= max_segment_index || RESOURCE_BAR_SEGMENTS[i + 1].value > maxValue)) {
217
- //we found major segment
218
- major_segment_index = i;
219
- }
412
+ this.__built_max = max;
413
+ this.__built_width = layout_width;
414
+ this.__built_ratio = ratio;
415
+ this.__built_origin_phase = origin_phase;
220
416
 
417
+ // the bar's left edge in its own CSS pixels, such that left * ratio lands where the page puts it
418
+ const local_left = origin_device / ratio;
419
+
420
+ if (this.__cells === null) {
421
+ this.__place_notches(max, layout_width, local_left, ratio);
422
+ } else {
423
+ this.__place_cells(layout_width, local_left, ratio);
221
424
  }
425
+ }
222
426
 
223
- const major_spec = RESOURCE_BAR_SEGMENTS[major_segment_index];
224
- const minor_spec = RESOURCE_BAR_SEGMENTS[major_segment_index - 1];
427
+ /**
428
+ * @param {number} max
429
+ * @param {number} width
430
+ * @param {number} left
431
+ * @param {number} ratio
432
+ * @private
433
+ */
434
+ __place_notches(max, width, left, ratio) {
435
+ const tiers = this.__tiers;
436
+ const ticks = segment_tick_positions(max, width, tiers);
225
437
 
438
+ const tick_count = ticks.length;
439
+ const elements = this.__notch_elements;
440
+ const container = this.__el_layout;
226
441
 
227
- const majorSegmentValue = major_spec.value;
442
+ while (elements.length < tick_count) {
443
+ const el = document.createElement('div');
228
444
 
229
- if (minor_spec === undefined) {
230
- //no minor spec, only paint major
445
+ container.appendChild(el);
446
+ elements.push(el);
447
+ }
231
448
 
232
- /**
233
- *
234
- * @type {number}
235
- */
236
- const stepCount = maxValue / majorSegmentValue;
449
+ while (elements.length > tick_count) {
450
+ container.removeChild(elements.pop());
451
+ }
237
452
 
238
- const segmentWidth = size.x / stepCount;
453
+ const place = this.__place;
239
454
 
455
+ for (let i = 0; i < tick_count; i++) {
456
+ const tick = ticks[i];
457
+ const tier = tiers[tick.tier];
240
458
 
241
- for (let i = 1; i < stepCount; i++) {
459
+ segment_notch_place(place, 0, tick.value / max, tier.width_px, left, width, ratio);
242
460
 
243
- const x = i * segmentWidth;
461
+ const el = elements[i];
244
462
 
245
- // major notch
463
+ el.className = `notch ${tier.class_name}`;
246
464
 
247
- major_spec.draw(ctx, x, size.y);
465
+ const style = el.style;
248
466
 
249
- }
467
+ style.left = `${place[0]}px`;
468
+ style.width = `${place[1]}px`;
469
+ }
470
+ }
250
471
 
251
- } else {
472
+ /**
473
+ * @param {number} width
474
+ * @param {number} left
475
+ * @param {number} ratio
476
+ * @private
477
+ */
478
+ __place_cells(width, left, ratio) {
479
+ const cells = this.__cells;
252
480
 
253
- const minorSegmentValue = minor_spec.value;
481
+ const layout = segment_cell_layout(width, cells.count, cells.group, ratio);
254
482
 
255
- const majorMultiplier = majorSegmentValue / minorSegmentValue;
483
+ const origin_device = left * ratio;
484
+ const origin_shift_device = Math.round(origin_device) - origin_device;
256
485
 
257
- /**
258
- *
259
- * @type {number}
260
- */
261
- const stepCount = maxValue / minorSegmentValue;
486
+ const cell_x = layout.cell_x_device;
487
+ const cell_width = layout.cell_width_device;
488
+ const elements = this.__cell_elements;
489
+
490
+ for (let i = 0; i < cells.count; i++) {
491
+ const style = elements[i].style;
492
+
493
+ style.left = `${(cell_x[i] + origin_shift_device) / ratio}px`;
494
+ style.width = `${cell_width[i] / ratio}px`;
495
+ }
496
+ }
262
497
 
263
- const minorSegmentWidth = size.x / stepCount;
498
+ updateFill() {
499
+ const m = this.__value_max.getValue();
264
500
 
265
- const displayMinor = minorSegmentWidth >= 2;
501
+ const values = this.__values_current;
502
+ const value_count = values.length;
266
503
 
267
- for (let i = 1; i < stepCount; i++) {
504
+ const fills = this.__value_fills;
505
+ const draw_fills = fills.length > 0;
268
506
 
269
- const x = i * minorSegmentWidth;
507
+ let total = 0;
270
508
 
271
- if (i % majorMultiplier === 0) {
272
- // major notch
509
+ for (let i = 0; i < value_count; i++) {
510
+ const value = Math.max(0, values[i].getValue());
273
511
 
274
- major_spec.draw(ctx, x, size.y);
512
+ const f0 = m > 0 ? clamp01(total / m) : 0;
275
513
 
276
- } else if (displayMinor) {
277
- // minor notch
514
+ total += value;
278
515
 
279
- minor_spec.draw(ctx, x, size.y);
516
+ const f1 = m > 0 ? clamp01(total / m) : 0;
280
517
 
281
- }
518
+ if (draw_fills) {
519
+ const style = fills[i].style;
282
520
 
521
+ style.left = `${f0 * 100}%`;
522
+ style.width = `${(f1 - f0) * 100}%`;
283
523
  }
284
524
  }
525
+
526
+ const total_fraction = m > 0 ? clamp01(total / m) : 0;
527
+
528
+ this.__total_fraction = total_fraction;
529
+
530
+ const now = performance.now();
531
+
532
+ const ghost = this.__ghost;
533
+
534
+ ghost.duration_ms = this.__reduced_motion !== null && this.__reduced_motion.matches ? 0 : this.__ghost_duration_ms;
535
+ ghost.set(total_fraction, now);
536
+
537
+ this.__draw(now);
538
+ }
539
+
540
+ /**
541
+ * Draw the cells (in cell mode) and the ghost as they stand at `time_ms`, and keep animating until the ghost settles
542
+ * @param {number} time_ms
543
+ * @private
544
+ */
545
+ __draw(time_ms) {
546
+ const ghost_fraction = this.__ghost.sample(time_ms);
547
+
548
+ if (this.__cells === null) {
549
+ this.__el_ghost.style.width = `${ghost_fraction * 100}%`;
550
+ } else {
551
+ this.__draw_cells(this.__total_fraction, ghost_fraction);
552
+ }
553
+
554
+ if (!this.__ghost.is_settled(time_ms) && this.isLinked && !this.__frame_pending) {
555
+ this.__frame_pending = true;
556
+ this.__frame_id = requestAnimationFrame(this.__animate_ghost);
557
+ }
285
558
  }
286
559
 
287
- updateFill() {
288
- const m = this.__value_max.getValue();
560
+ /**
561
+ * @param {number} total_fraction
562
+ * @param {number} ghost_fraction
563
+ * @private
564
+ */
565
+ __draw_cells(total_fraction, ghost_fraction) {
566
+ const count = this.__cells.count;
289
567
 
290
- let total_current = 0;
568
+ const fill_cells = snap_whole(total_fraction * count);
569
+ const ghost_cells = snap_whole(ghost_fraction * count);
291
570
 
292
- for (let i = 0; i < this.__values_current.length; i++) {
293
- const v = this.__values_current[i];
571
+ const states = this.__cell_states;
294
572
 
295
- const value = v.getValue();
573
+ for (let i = 0; i < count; i++) {
574
+ const fill = clamp01(fill_cells - i);
575
+ const ghost = clamp01(ghost_cells - i);
296
576
 
297
- total_current += value;
577
+ const state = fill >= 1 ? CELL_STATE_FILLED : (fill > 0 ? CELL_STATE_PARTIAL : CELL_STATE_EMPTY);
298
578
 
299
- const v_fraction = clamp01(v / m);
579
+ if (states[i] !== state) {
580
+ states[i] = state;
581
+ this.__cell_elements[i].className = CELL_STATE_CLASS[state];
582
+ }
300
583
 
301
- const fill_view = this.__value_fills[i];
584
+ if (this.__cell_fill_drawn[i] !== fill) {
585
+ this.__cell_fill_drawn[i] = fill;
586
+ this.__cell_fill_elements[i].style.width = `${fill * 100}%`;
587
+ }
302
588
 
303
- fill_view.el.style.width = `${v_fraction * 100}%`;
589
+ if (this.__cell_ghost_drawn[i] !== ghost) {
590
+ this.__cell_ghost_drawn[i] = ghost;
591
+ this.__cell_ghost_elements[i].style.width = `${ghost * 100}%`;
592
+ }
304
593
  }
594
+ }
305
595
 
596
+ /**
597
+ * @private
598
+ */
599
+ __animate_ghost() {
600
+ this.__frame_pending = false;
306
601
 
307
- const f = clamp01(total_current / m);
602
+ if (!this.isLinked) {
603
+ return;
604
+ }
605
+
606
+ this.__draw(performance.now());
607
+ }
608
+
609
+ /**
610
+ * Arm a one-shot watch on the current device pixel ratio; it fires when the window moves to another screen or the
611
+ * page is zoomed, neither of which resizes the bar in CSS pixels
612
+ * @private
613
+ */
614
+ __watch_device_pixel_ratio() {
615
+ if (typeof matchMedia !== 'function' || typeof devicePixelRatio !== 'number') {
616
+ return;
617
+ }
618
+
619
+ const query = matchMedia(`(resolution: ${devicePixelRatio}dppx)`);
308
620
 
309
- const width = `${f * 100}%`;
621
+ query.addEventListener('change', this.__handle_dpr_change, { once: true });
310
622
 
311
- this.__v__ghost.el.style.width = width;
623
+ this.__dpr_query = query;
624
+ }
625
+
626
+ /**
627
+ * @private
628
+ */
629
+ __handle_dpr_change() {
630
+ this.__dpr_query = null;
631
+
632
+ if (!this.isLinked) {
633
+ return;
634
+ }
635
+
636
+ this.updateSegments();
637
+ this.__watch_device_pixel_ratio();
312
638
  }
313
639
  }