nodehammer 0.2.0rc1__tar.gz → 0.2.0rc5__tar.gz

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 (462) hide show
  1. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.gitignore +2 -1
  2. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/CMakeLists.txt +149 -30
  3. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/Justfile +71 -2
  4. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/PKG-INFO +29 -19
  5. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/README.md +26 -18
  6. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/build.sh +1 -0
  7. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/shared_consumer/main.cpp +3 -2
  8. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/Dependencies.cmake +27 -3
  9. nodehammer-0.2.0rc5/cmake/Version.cmake +88 -0
  10. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/conanfile.py +14 -2
  11. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/kitchen_sink.lua +1 -1
  12. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd.lua +2 -2
  13. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/cli.hpp +47 -0
  14. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/config.hpp +1 -1
  15. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/semantic_scene.hpp +5 -4
  16. nodehammer-0.2.0rc5/packaging/plugins/nh_web_pin.py +92 -0
  17. nodehammer-0.2.0rc5/packaging/web/.gitignore +7 -0
  18. nodehammer-0.2.0rc5/packaging/web/LICENSE +21 -0
  19. nodehammer-0.2.0rc5/packaging/web/README.md +32 -0
  20. nodehammer-0.2.0rc5/packaging/web/pyproject.toml +63 -0
  21. nodehammer-0.2.0rc5/packaging/web/src/nodehammer_web/__init__.py +79 -0
  22. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/pyproject.toml +49 -1
  23. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/python/nodehammer/__main__.py +7 -1
  24. nodehammer-0.2.0rc5/python/nodehammer/cli.py +134 -0
  25. nodehammer-0.2.0rc5/recipes/cli11/conandata.yml +6 -0
  26. nodehammer-0.2.0rc5/recipes/cli11/conanfile.py +71 -0
  27. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/build_pages_site.sh +7 -4
  28. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/check_em_js_closure.py +1 -1
  29. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/check_pages_site.py +20 -2
  30. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/check_wasm_module_linkage.py +3 -3
  31. nodehammer-0.2.0rc5/scripts/check_web_serve.py +155 -0
  32. nodehammer-0.2.0rc5/scripts/check_wheel_pair.py +110 -0
  33. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/make_nhproj.py +6 -0
  34. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/stage_wasm_viewer.sh +48 -10
  35. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/render_scene.cpp +5 -37
  36. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/cli_common.hpp +53 -0
  37. nodehammer-0.2.0rc5/src/cli/cmd_config.cpp +204 -0
  38. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/cmd_convert.cpp +160 -55
  39. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/cmd_inspect.cpp +215 -41
  40. nodehammer-0.2.0rc5/src/cli/cmd_project.cpp +238 -0
  41. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/cmd_viewer_native.cpp +221 -134
  42. nodehammer-0.2.0rc5/src/cli/cmd_viewer_web.cpp +338 -0
  43. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/main.cpp +6 -0
  44. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/run.cpp +37 -8
  45. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/run_internal.hpp +56 -9
  46. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_loader.hpp +1 -1
  47. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/diagnostic_codes.hpp +20 -0
  48. nodehammer-0.2.0rc5/src/ir/fb/render/exporter.cpp +43 -0
  49. nodehammer-0.2.0rc5/src/ir/fb/render/exporter.hpp +25 -0
  50. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/importer.cpp +1 -1
  51. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/importer.hpp +1 -1
  52. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/render/exporter_registry.cpp +14 -0
  53. nodehammer-0.2.0rc5/src/ir/render/json_exporter.cpp +25 -0
  54. nodehammer-0.2.0rc5/src/ir/render/json_exporter.hpp +25 -0
  55. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/lua/lua_config.cpp +1 -1
  56. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/lua/lua_config.hpp +1 -1
  57. nodehammer-0.2.0rc5/src/project/pack.cpp +216 -0
  58. nodehammer-0.2.0rc5/src/project/pack.hpp +63 -0
  59. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/python/bindings.cpp +22 -2
  60. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/app.cpp +4 -4
  61. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform.hpp +1 -1
  62. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform_web.cpp +1 -1
  63. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/project_manifest.hpp +7 -0
  64. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/menu_bar.cpp +1 -1
  65. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/zip_working_set.cpp +67 -5
  66. nodehammer-0.2.0rc5/src/web/executable_path.cpp +76 -0
  67. nodehammer-0.2.0rc5/src/web/open_browser.cpp +68 -0
  68. nodehammer-0.2.0rc5/src/web/open_browser.hpp +23 -0
  69. nodehammer-0.2.0rc5/src/web/runtime_locator.cpp +267 -0
  70. nodehammer-0.2.0rc5/src/web/runtime_locator.hpp +122 -0
  71. nodehammer-0.2.0rc5/src/web/stage.cpp +129 -0
  72. nodehammer-0.2.0rc5/src/web/stage.hpp +62 -0
  73. nodehammer-0.2.0rc5/src/web/static_server.cpp +140 -0
  74. nodehammer-0.2.0rc5/src/web/static_server.hpp +73 -0
  75. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/CMakeLists.txt +54 -23
  76. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/api/test_api_surface.cpp +1 -1
  77. nodehammer-0.2.0rc5/tests/cli/cli_test_support.hpp +122 -0
  78. nodehammer-0.2.0rc5/tests/cli/test_cli_config.cpp +181 -0
  79. nodehammer-0.2.0rc5/tests/cli/test_cli_convert_stages.cpp +148 -0
  80. nodehammer-0.2.0rc5/tests/cli/test_cli_inspect_json.cpp +234 -0
  81. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/cli/test_cli_run.cpp +101 -91
  82. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_config_writer.cpp +1 -1
  83. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/ir/test_flatbuffer_roundtrip.cpp +1 -1
  84. nodehammer-0.2.0rc5/tests/ir/test_render_nhr_exporter.cpp +140 -0
  85. nodehammer-0.2.0rc5/tests/project/test_pack.cpp +249 -0
  86. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_semantic_scene.cpp +4 -3
  87. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/python/test_cli.py +154 -6
  88. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/python/test_semantic_scene.py +1 -1
  89. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_zip_working_set.cpp +41 -0
  90. nodehammer-0.2.0rc5/tests/web/test_runtime_locator.cpp +382 -0
  91. nodehammer-0.2.0rc5/tests/web/test_stage.cpp +171 -0
  92. nodehammer-0.2.0rc5/tests/web/test_static_server.cpp +220 -0
  93. nodehammer-0.2.0rc1/cmake/Version.cmake +0 -51
  94. nodehammer-0.2.0rc1/python/nodehammer/cli.py +0 -63
  95. nodehammer-0.2.0rc1/src/cli/cmd_config_flatten.cpp +0 -63
  96. nodehammer-0.2.0rc1/src/cli/cmd_config_lua.cpp +0 -80
  97. nodehammer-0.2.0rc1/src/cli/cmd_dump_render.cpp +0 -80
  98. nodehammer-0.2.0rc1/src/cli/cmd_dump_semantic.cpp +0 -327
  99. nodehammer-0.2.0rc1/src/cli/cmd_validate_config.cpp +0 -45
  100. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.clang-format +0 -0
  101. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.clang-tidy +0 -0
  102. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.gitattributes +0 -0
  103. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.pre-commit-config.yaml +0 -0
  104. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.vscode/launch.json +0 -0
  105. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.vscode/settings.json +0 -0
  106. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/.vscode/tasks.json +0 -0
  107. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/LICENSE +0 -0
  108. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/LICENSES/MIT.txt +0 -0
  109. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/LICENSES/OFL-1.1.txt +0 -0
  110. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/LICENSES/Zlib.txt +0 -0
  111. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/REUSE.toml +0 -0
  112. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/STYLE.md +0 -0
  113. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/bench-summary.py +0 -0
  114. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/bench.sh +0 -0
  115. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/check_shared_exports.py +0 -0
  116. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/shared-build.sh +0 -0
  117. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/shared_consumer/CMakeLists.txt +0 -0
  118. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/ci/verify-shared-install.sh +0 -0
  119. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/CompilerOptions.cmake +0 -0
  120. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/PicProbe.cmake +0 -0
  121. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/Sokol.cmake +0 -0
  122. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/ThirdPartyLicenses.cmake +0 -0
  123. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/nodehammer-config.cmake.in +0 -0
  124. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/patch_sokol_wgpu.cmake +0 -0
  125. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/pic_probe.cpp +0 -0
  126. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/validate_shader_hlsl.cmake +0 -0
  127. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/cmake/validate_shader_wgsl.cmake +0 -0
  128. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/full_example.toml +0 -0
  129. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/include_bad_path.toml +0 -0
  130. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/include_basic.toml +0 -0
  131. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/include_cycle.toml +0 -0
  132. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/include_diamond.toml +0 -0
  133. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/include_nested.toml +0 -0
  134. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/cycle_a.toml +0 -0
  135. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/cycle_b.toml +0 -0
  136. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_base.toml +0 -0
  137. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_left.toml +0 -0
  138. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/diamond_right.toml +0 -0
  139. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/materials.toml +0 -0
  140. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/nested_inner.toml +0 -0
  141. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/nested_outer.toml +0 -0
  142. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/includes/rules.toml +0 -0
  143. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/invalid_bad_tolerance.toml +0 -0
  144. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/invalid_missing_material_ref.toml +0 -0
  145. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/calorimeters.lua +0 -0
  146. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/lib/constants.lua +0 -0
  147. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/materials.lua +0 -0
  148. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/muon.lua +0 -0
  149. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/base.lua +0 -0
  150. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/calorimeters.lua +0 -0
  151. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/materials.lua +0 -0
  152. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/muon.lua +0 -0
  153. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/odd/tracker.lua +0 -0
  154. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/parity.lua +0 -0
  155. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/parity.toml +0 -0
  156. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/lua/tracker.lua +0 -0
  157. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/minimal.toml +0 -0
  158. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/base.toml +0 -0
  159. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/calorimeters.toml +0 -0
  160. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/calorimeters_simple.toml +0 -0
  161. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/materials.toml +0 -0
  162. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/muon.toml +0 -0
  163. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/muon_simple.toml +0 -0
  164. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/simple_materials.toml +0 -0
  165. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd/tracker.toml +0 -0
  166. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd.toml +0 -0
  167. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_drop_coincident_faces.toml +0 -0
  168. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_merged.toml +0 -0
  169. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_simple.toml +0 -0
  170. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_ecal_barrel_stave.toml +0 -0
  171. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_hcal_barrel_stave.toml +0 -0
  172. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_long_strip_barrel_module.toml +0 -0
  173. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_long_strip_barrel_stave.toml +0 -0
  174. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_muon_barrel_chamber.toml +0 -0
  175. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_pixel_barrel_module.toml +0 -0
  176. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_pixel_barrel_stave.toml +0 -0
  177. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_short_strip_barrel_module.toml +0 -0
  178. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_single_short_strip_barrel_stave.toml +0 -0
  179. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/configs/odd_tracker.toml +0 -0
  180. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/dd4hep/sensitive_detector.xml +0 -0
  181. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/fixtures/dd4hep/simple_box.xml +0 -0
  182. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/build.hpp +0 -0
  183. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/diagnostics.hpp +0 -0
  184. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/render_scene.hpp +0 -0
  185. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/version.hpp.in +0 -0
  186. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/include/nodehammer/visibility.hpp +0 -0
  187. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/profiles/emscripten +0 -0
  188. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/python/nodehammer/__init__.py +0 -0
  189. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/python/nodehammer/py.typed +0 -0
  190. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/imgui/CMakeLists.txt +0 -0
  191. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/imgui/conandata.yml +0 -0
  192. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/imgui/conanfile.py +0 -0
  193. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/implot/CMakeLists.txt +0 -0
  194. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/implot/conandata.yml +0 -0
  195. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/implot/conanfile.py +0 -0
  196. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/nfd/conandata.yml +0 -0
  197. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/nfd/conanfile.py +0 -0
  198. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/sokol/conandata.yml +0 -0
  199. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/sokol/conanfile.py +0 -0
  200. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/sokol-shdc/conandata.yml +0 -0
  201. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/recipes/sokol-shdc/conanfile.py +0 -0
  202. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/schemas/render.fbs +0 -0
  203. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/schemas/semantic.fbs +0 -0
  204. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/check_cli_no_exit.py +0 -0
  205. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/serve_nocache.py +0 -0
  206. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/wasm_compute_smoke.js +0 -0
  207. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/scripts/windows-msvc-cmake.ps1 +0 -0
  208. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/CMakeLists.txt +0 -0
  209. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/ao.glsl +0 -0
  210. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/ao_denoise.glsl +0 -0
  211. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/blit.glsl +0 -0
  212. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/composite.glsl +0 -0
  213. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/depth_helpers.glsl.h +0 -0
  214. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/ibl_bake.glsl +0 -0
  215. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/shaders/scene.glsl +0 -0
  216. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/build.cpp +0 -0
  217. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/config.cpp +0 -0
  218. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/diagnostics.cpp +0 -0
  219. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/handles.hpp +0 -0
  220. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/api/semantic_scene.cpp +0 -0
  221. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/pager.cpp +0 -0
  222. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/cli/pager.hpp +0 -0
  223. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/color_parse.cpp +0 -0
  224. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/color_parse.hpp +0 -0
  225. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_ast.hpp +0 -0
  226. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_enums.hpp +0 -0
  227. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_keys.hpp +0 -0
  228. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_loader.cpp +0 -0
  229. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_validator.cpp +0 -0
  230. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_validator.hpp +0 -0
  231. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_writer.cpp +0 -0
  232. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/config_writer.hpp +0 -0
  233. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/predicate_parser.cpp +0 -0
  234. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/config/predicate_parser.hpp +0 -0
  235. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/file_io.hpp +0 -0
  236. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/glm_json.hpp +0 -0
  237. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/markup.cpp +0 -0
  238. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/markup.hpp +0 -0
  239. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/overloaded.hpp +0 -0
  240. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/timing.hpp +0 -0
  241. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/detail/zstd_io.hpp +0 -0
  242. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/diagnostics.hpp +0 -0
  243. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/export_resolve.cpp +0 -0
  244. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/export_resolve.hpp +0 -0
  245. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/dd4hep/semantic/importer.cpp +0 -0
  246. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/dd4hep/semantic/importer.hpp +0 -0
  247. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/render/flatbuffer.cpp +0 -0
  248. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/render/flatbuffer.hpp +0 -0
  249. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/exporter.cpp +0 -0
  250. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/exporter.hpp +0 -0
  251. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/flatbuffer.cpp +0 -0
  252. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/fb/semantic/flatbuffer.hpp +0 -0
  253. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/gltf/render/exporter.cpp +0 -0
  254. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/gltf/render/exporter.hpp +0 -0
  255. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/json/semantic/exporter.cpp +0 -0
  256. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/json/semantic/exporter.hpp +0 -0
  257. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/json/semantic/importer.cpp +0 -0
  258. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/json/semantic/importer.hpp +0 -0
  259. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/obj/render/exporter.cpp +0 -0
  260. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/obj/render/exporter.hpp +0 -0
  261. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/provenance.hpp +0 -0
  262. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/render/exporter.hpp +0 -0
  263. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/render.hpp +0 -0
  264. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/render_json.cpp +0 -0
  265. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/render_json.hpp +0 -0
  266. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic/exporter.hpp +0 -0
  267. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic/exporter_registry.cpp +0 -0
  268. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic/importer.hpp +0 -0
  269. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic/importer_registry.cpp +0 -0
  270. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic.cpp +0 -0
  271. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic.hpp +0 -0
  272. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic_json.cpp +0 -0
  273. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/semantic_json.hpp +0 -0
  274. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/synthetic/semantic/importer.cpp +0 -0
  275. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/synthetic/semantic/importer.hpp +0 -0
  276. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/importer.cpp +0 -0
  277. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/importer.hpp +0 -0
  278. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/shape_dispatch.cpp +0 -0
  279. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/ir/tgeo/semantic/shape_dispatch.hpp +0 -0
  280. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/python/CMakeLists.txt +0 -0
  281. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/scene_build.cpp +0 -0
  282. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/scene_build.hpp +0 -0
  283. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/selection/predicate.cpp +0 -0
  284. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/selection/predicate.hpp +0 -0
  285. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/selection/selector.cpp +0 -0
  286. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/selection/selector.hpp +0 -0
  287. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/sokol/sokol_imgui_impl.cc +0 -0
  288. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/sokol/sokol_imgui_impl.mm +0 -0
  289. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/sokol/sokol_impl.c +0 -0
  290. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/sokol/sokol_impl.mm +0 -0
  291. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/boolean_tessellator.cpp +0 -0
  292. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/boolean_tessellator.hpp +0 -0
  293. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/build_pipeline.cpp +0 -0
  294. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/build_pipeline.hpp +0 -0
  295. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/primitive_tessellator.cpp +0 -0
  296. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/primitive_tessellator.hpp +0 -0
  297. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_job.hpp +0 -0
  298. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_pass.cpp +0 -0
  299. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/tessellation_pass.hpp +0 -0
  300. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/tessellator.hpp +0 -0
  301. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/wedge_cut.cpp +0 -0
  302. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tessellation/wedge_cut.hpp +0 -0
  303. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/tools/imgui_kitchen_sink_main.cpp +0 -0
  304. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/version.cpp +0 -0
  305. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/CMakeLists.txt +0 -0
  306. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_denoise_pass.cpp +0 -0
  307. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_denoise_pass.hpp +0 -0
  308. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_pass.cpp +0 -0
  309. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_pass.hpp +0 -0
  310. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_render_target.cpp +0 -0
  311. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ao_render_target.hpp +0 -0
  312. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/app.hpp +0 -0
  313. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/app_state.cpp +0 -0
  314. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/app_state.hpp +0 -0
  315. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/archive_export.cpp +0 -0
  316. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/archive_export.hpp +0 -0
  317. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/archive_project_fs.cpp +0 -0
  318. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/archive_project_fs.hpp +0 -0
  319. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/backend_caps.hpp +0 -0
  320. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/bag_project_fs.cpp +0 -0
  321. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/bag_project_fs.hpp +0 -0
  322. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/bench_runner.cpp +0 -0
  323. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/bench_runner.hpp +0 -0
  324. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/blit_pass.cpp +0 -0
  325. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/blit_pass.hpp +0 -0
  326. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/build_controller.cpp +0 -0
  327. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/build_controller.hpp +0 -0
  328. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/build_session.cpp +0 -0
  329. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/build_session.hpp +0 -0
  330. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/byte_buffer.hpp +0 -0
  331. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/camera.cpp +0 -0
  332. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/camera.hpp +0 -0
  333. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/composite_pass.cpp +0 -0
  334. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/composite_pass.hpp +0 -0
  335. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/config.hpp +0 -0
  336. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/dynamic_render_scale.cpp +0 -0
  337. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/dynamic_render_scale.hpp +0 -0
  338. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/filesystem_project_fs.cpp +0 -0
  339. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/filesystem_project_fs.hpp +0 -0
  340. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer.hpp +0 -0
  341. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer_d3d11.cpp +0 -0
  342. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/gpu_pass_timer_noop.cpp +0 -0
  343. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ibl.cpp +0 -0
  344. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ibl.hpp +0 -0
  345. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ibl_baker.cpp +0 -0
  346. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ibl_baker.hpp +0 -0
  347. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/imgui_backend.cpp +0 -0
  348. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/imgui_backend.hpp +0 -0
  349. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/log_sink.hpp +0 -0
  350. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/native_bag_project_fs.cpp +0 -0
  351. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/native_bag_project_fs.hpp +0 -0
  352. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform_macos.mm +0 -0
  353. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform_native_common.cpp +0 -0
  354. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform_native_common.hpp +0 -0
  355. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/platform_native_default.cpp +0 -0
  356. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export.cpp +0 -0
  357. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export.hpp +0 -0
  358. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback.hpp +0 -0
  359. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_d3d11.cpp +0 -0
  360. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_gl.cpp +0 -0
  361. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_metal.mm +0 -0
  362. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_export_readback_wgpu.cpp +0 -0
  363. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_exporter.cpp +0 -0
  364. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/png_exporter.hpp +0 -0
  365. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/project_fs.hpp +0 -0
  366. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/project_manifest.cpp +0 -0
  367. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/render_quality.hpp +0 -0
  368. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job.hpp +0 -0
  369. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_common.cpp +0 -0
  370. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_internal.hpp +0 -0
  371. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_native.cpp +0 -0
  372. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web.cpp +0 -0
  373. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web_backend.hpp +0 -0
  374. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_build_job_web_worker.cpp +0 -0
  375. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_render_target.cpp +0 -0
  376. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_render_target.hpp +0 -0
  377. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_renderer.cpp +0 -0
  378. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/scene_renderer.hpp +0 -0
  379. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/shared_image.hpp +0 -0
  380. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/stb_image_write_impl.cpp +0 -0
  381. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/debug_panel.cpp +0 -0
  382. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/debug_panel.hpp +0 -0
  383. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/icon_font.cpp +0 -0
  384. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/icon_font.hpp +0 -0
  385. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/menu_bar.hpp +0 -0
  386. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/notifications.cpp +0 -0
  387. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/notifications.hpp +0 -0
  388. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/perf_history.hpp +0 -0
  389. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/project_panel.cpp +0 -0
  390. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/project_panel.hpp +0 -0
  391. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/status_ui.cpp +0 -0
  392. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/status_ui.hpp +0 -0
  393. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/ui_context.hpp +0 -0
  394. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/view_panel.cpp +0 -0
  395. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/view_panel.hpp +0 -0
  396. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/viewer_ui.cpp +0 -0
  397. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/ui/viewer_ui.hpp +0 -0
  398. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/watched_filesystem_project_fs.cpp +0 -0
  399. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/watched_filesystem_project_fs.hpp +0 -0
  400. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/viewer/zip_working_set.hpp +0 -0
  401. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/web/compute_worker.js +0 -0
  402. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/web/compute_worker_main.cpp +0 -0
  403. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/src/web/viewer_main.cpp +0 -0
  404. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/api/test_api_equivalence.cpp +0 -0
  405. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/api/test_config_wrapper.cpp +0 -0
  406. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/bench_main.cpp +0 -0
  407. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_config_fixtures.cpp +0 -0
  408. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_config_loader.cpp +0 -0
  409. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_config_validator.cpp +0 -0
  410. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_lua_config.cpp +0 -0
  411. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/config/test_predicate_parser.cpp +0 -0
  412. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/export/test_export_resolve.cpp +0 -0
  413. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/export/test_gltf_exporter.cpp +0 -0
  414. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/export/test_render_exporter_registry.cpp +0 -0
  415. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/export/test_semantic_exporter_registry.cpp +0 -0
  416. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/import/test_dd4hep_importer.cpp +0 -0
  417. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/import/test_synthetic_importer.cpp +0 -0
  418. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/import/test_tgeo_importer.cpp +0 -0
  419. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/ir/test_json_roundtrip.cpp +0 -0
  420. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/ir/test_render_flatbuffer_roundtrip.cpp +0 -0
  421. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/ir/test_semantic_ir.cpp +0 -0
  422. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/ir/test_shape_variant.cpp +0 -0
  423. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/public_fixture.hpp +0 -0
  424. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_build.cpp +0 -0
  425. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_cli.cpp +0 -0
  426. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_config.cpp +0 -0
  427. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_dd4hep.cpp +0 -0
  428. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_diagnostics.cpp +0 -0
  429. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_render_scene.cpp +0 -0
  430. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/public/test_public_tgeo.cpp +0 -0
  431. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/python/test_build.py +0 -0
  432. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/python/test_config_and_diagnostics.py +0 -0
  433. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/selection/test_predicate.cpp +0 -0
  434. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/selection/test_selector.cpp +0 -0
  435. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_boolean_tessellator.cpp +0 -0
  436. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_build_pipeline.cpp +0 -0
  437. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_obj_writer.hpp +0 -0
  438. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_primitive_tessellator.cpp +0 -0
  439. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_tessellation_pass.cpp +0 -0
  440. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_tgeo_tessellation.cpp +0 -0
  441. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/tessellation/test_wedge_cut.cpp +0 -0
  442. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/test_compute_pipeline.cpp +0 -0
  443. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/test_main.cpp +0 -0
  444. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/test_markup.cpp +0 -0
  445. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/test_scene_build.cpp +0 -0
  446. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/test_timing.cpp +0 -0
  447. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_app_state.cpp +0 -0
  448. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_archive_export.cpp +0 -0
  449. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_archive_project_fs.cpp +0 -0
  450. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_bag_project_fs.cpp +0 -0
  451. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_build_session.cpp +0 -0
  452. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_byte_buffer.cpp +0 -0
  453. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_dynamic_render_scale.cpp +0 -0
  454. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_filesystem_project_fs.cpp +0 -0
  455. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_native_bag_project_fs.cpp +0 -0
  456. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_project_manifest.cpp +0 -0
  457. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/viewer/test_watched_filesystem_project_fs.cpp +0 -0
  458. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/tests/wasm_lua_smoke.cpp +0 -0
  459. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/third_party/fontawesome7/IconsFontAwesome7.h +0 -0
  460. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/third_party/fontawesome7/README.md +0 -0
  461. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/third_party/fontawesome7/fa-solid-900.h +0 -0
  462. {nodehammer-0.2.0rc1 → nodehammer-0.2.0rc5}/third_party/stb/stb_image_write.h +0 -0
@@ -14,13 +14,14 @@
14
14
  # Project archives packed by the viewer / make_nhproj.py — always generated.
15
15
  *.nhproj
16
16
 
17
- # config-flatten output written to the repo root (generated from fixtures/).
17
+ # `config flatten` output written to the repo root (generated from fixtures/).
18
18
  /*_flat.toml
19
19
  CMakeUserPresets.json
20
20
 
21
21
  # Python: the venv the wheel workflow builds against, and wheel output.
22
22
  /.venv/
23
23
  /dist/
24
+ /dist-web/
24
25
  *.egg-info/
25
26
  .idea
26
27
 
@@ -134,6 +134,32 @@ include(cmake/CompilerOptions.cmake)
134
134
  # into the shared target's INSTALL_INTERFACE include path.
135
135
  include(GNUInstallDirs)
136
136
 
137
+ # ── The web runtime's contract ───────────────────────────────────────────────
138
+ # The wasm viewer is delivered as a directory, not a program: a shell, a worker
139
+ # script, three bundles and the stamp below. `nodehammer viewer serve` locates
140
+ # one through a ladder of candidate directories (a flag, an environment
141
+ # variable, this install path, later a download cache), which means it can be
142
+ # handed a directory that nobody validated — an old checkout's build tree is
143
+ # exactly the mistake a person makes while debugging, and no wheel metadata or
144
+ # version pin can see it. So the runtime says what it is and the library checks
145
+ # before it serves anything.
146
+ #
147
+ # What is compared is the schema id, not the version. What actually has to
148
+ # agree between the two halves is the .nhproj + nh_manifest.json shape and the
149
+ # compute worker's postMessage protocol — the last of which has already broken
150
+ # once, silently, under Closure (dcc4a06, and scripts/check_wasm_module_
151
+ # linkage.py exists because of it). An integer is at once stricter than a
152
+ # version, because it catches same-version skew from a hand-pointed directory,
153
+ # and looser, because it does not cry wolf on a patch release where nothing
154
+ # about the contract moved. The version rides along in the stamp only so the
155
+ # refusal can name it.
156
+ #
157
+ # BUMP THIS when the manifest/archive shape or the worker protocol changes.
158
+ # Monotonic; never reused.
159
+ set(NH_WEB_RUNTIME_SCHEMA 1)
160
+ set(NH_WEB_RUNTIME_STAMP "nh_runtime.json")
161
+ set(NH_WEB_RUNTIME_DIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/web")
162
+
137
163
  # ── FlatBuffers code generation ──────────────────────────────────────────────
138
164
  set(NH_FBS_SCHEMAS
139
165
  ${CMAKE_CURRENT_SOURCE_DIR}/schemas/semantic.fbs
@@ -227,10 +253,17 @@ set(NH_CORE_SOURCES
227
253
  src/ir/gltf/render/exporter.cpp
228
254
  src/ir/obj/render/exporter.cpp
229
255
  src/ir/render/exporter_registry.cpp
256
+ src/ir/fb/render/exporter.cpp
257
+ src/ir/render/json_exporter.cpp
230
258
  src/ir/json/semantic/exporter.cpp
231
259
  src/ir/fb/semantic/exporter.cpp
232
260
  src/ir/semantic/exporter_registry.cpp
233
261
  src/detail/markup.cpp
262
+ # Host-side, despite the directory: locating and vetting the wasm runtime is
263
+ # something the *serving* process does. src/web/'s other two TUs are the
264
+ # Emscripten entry points and are not core.
265
+ src/web/runtime_locator.cpp
266
+ src/web/executable_path.cpp
234
267
  src/scene_build.cpp
235
268
  src/export_resolve.cpp
236
269
  src/version.cpp
@@ -267,11 +300,7 @@ set(NH_CORE_SOURCES
267
300
  src/cli/pager.cpp
268
301
  src/cli/cmd_convert.cpp
269
302
  src/cli/cmd_inspect.cpp
270
- src/cli/cmd_validate_config.cpp
271
- src/cli/cmd_config_flatten.cpp
272
- src/cli/cmd_dump_semantic.cpp
273
- src/cli/cmd_dump_render.cpp
274
- src/cli/cmd_config_lua.cpp
303
+ src/cli/cmd_config.cpp
275
304
  )
276
305
 
277
306
  # ── Application sources ───────────────────────────────────────────────────────
@@ -348,6 +377,11 @@ set(NH_CORE_PRIVATE_DEPS
348
377
 
349
378
  set(NH_CORE_DEFINES "")
350
379
 
380
+ # The web runtime's schema id, compiled in so `web::compiledSchema()` and the
381
+ # `nh_runtime.json` the install rules stamp come from one `set()` and cannot
382
+ # drift. See the contract block above GNUInstallDirs.
383
+ list(APPEND NH_CORE_DEFINES NH_WEB_RUNTIME_SCHEMA=${NH_WEB_RUNTIME_SCHEMA})
384
+
351
385
  # Extra include directories for dependencies that ship variables instead of
352
386
  # imported targets — Geant4 is the only one today. Everything else propagates
353
387
  # its includes through the link.
@@ -429,11 +463,34 @@ list(APPEND NH_CORE_DEPS manifold::manifold)
429
463
  # the web *runtime* no longer references BagProjectFs (static-lib dead-strip
430
464
  # keeps it out of the wasm viewer), but the native CLI (cmd_viewer) and the
431
465
  # unit tests on both platforms still use it.
466
+ #
467
+ # The web viewer's server and staging are native-only for a plainer reason:
468
+ # they exist to *serve* the wasm runtime to a browser, and a wasm module is the
469
+ # thing being served. Sockets are the giveaway -- there are none in the sandbox.
470
+ # The locator above is not gated, because "where would the runtime be" is a
471
+ # question the wasm build can be asked and answer "nowhere" to.
432
472
  if(NOT EMSCRIPTEN)
433
473
  list(APPEND NH_CORE_SOURCES
434
474
  src/viewer/filesystem_project_fs.cpp
435
475
  src/viewer/native_bag_project_fs.cpp
476
+ src/web/static_server.cpp
477
+ src/web/stage.cpp
478
+ src/web/open_browser.cpp
479
+ # Packing mounts a FilesystemProjectFs, so it is gated here rather than
480
+ # beside the ZipWorkingSet it builds -- that half *is* cross-platform.
481
+ src/project/pack.cpp
482
+ src/cli/cmd_project.cpp
483
+ # `viewer serve` itself. Excluded here rather than #ifdef'd inside:
484
+ # every line of it calls something in the three files above, so a wasm
485
+ # build of this TU would be a shell around a refusal. `run.cpp` skips
486
+ # the registration to match, and a wasm module simply has no `viewer`
487
+ # subcommand — which is right, since it *is* the viewer.
488
+ src/cli/cmd_viewer_web.cpp
436
489
  )
490
+ # Private: httplib.h is included by static_server.cpp and by nothing else,
491
+ # least of all a header. Header-only, so the shared library gains no link
492
+ # dependency and its package config gains no requirement.
493
+ list(APPEND NH_CORE_PRIVATE_DEPS httplib::httplib)
437
494
  endif()
438
495
 
439
496
  # WatchedFilesystemProjectFs (strategy doc step 4) decorates FilesystemProjectFs
@@ -712,7 +769,7 @@ endif()
712
769
  # executable per backend. Native picks the right backend for the host
713
770
  # (Metal on Apple, GLCORE on Linux/Windows). Emscripten builds BOTH GLES3
714
771
  # and WGPU executables from a single configure so the wasm shell can pick
715
- # at runtime via navigator.gpu — see web/viewer.html.
772
+ # at runtime via navigator.gpu — see web/index.html.
716
773
  if(NODEHAMMER_WITH_VIEWER)
717
774
  # Defines nodehammer_shaders custom target + NH_SHADER_INCLUDE_DIR.
718
775
  add_subdirectory(shaders)
@@ -723,7 +780,7 @@ if(NODEHAMMER_WITH_VIEWER)
723
780
  # dispatcher (`nodehammer viewer …` alongside the other subcommands);
724
781
  # the wasm build skips CLI11 entirely and uses src/web/viewer_main.cpp,
725
782
  # which exposes a single `nh_viewer_start(opts_json)` C export driven
726
- # by web/viewer.html.
783
+ # by web/index.html.
727
784
  function(nh_add_viewer_exe name viewer_lib)
728
785
  if(EMSCRIPTEN)
729
786
  add_executable(${name} src/web/viewer_main.cpp)
@@ -813,7 +870,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
813
870
  src/scene_build.cpp
814
871
  src/selection/selector.cpp
815
872
  src/cli/cmd_convert.cpp
816
- src/cli/cmd_dump_semantic.cpp
817
873
  PROPERTIES COMPILE_OPTIONS "-Wno-maybe-uninitialized"
818
874
  )
819
875
  endif()
@@ -837,37 +893,100 @@ include(cmake/PicProbe.cmake)
837
893
  # (GNUInstallDirs is included near the top — the core-library helper needs
838
894
  # CMAKE_INSTALL_INCLUDEDIR for the shared target's INSTALL_INTERFACE.)
839
895
 
840
- # Native: single nodehammer executable. Emscripten + viewer: per-backend
841
- # wasm bundles named nodehammer-{gles3,wgpu}.{js,wasm}. Emscripten + no
842
- # viewer: headless nodehammer (just the .js + .wasm).
843
- if(EMSCRIPTEN AND NODEHAMMER_WITH_VIEWER)
844
- set(NH_INSTALL_TARGETS nodehammer-gles3 nodehammer-wgpu nodehammer-compute)
845
- else()
846
- set(NH_INSTALL_TARGETS nodehammer)
847
- endif()
848
-
849
896
  # Every install rule names a COMPONENT: Runtime to run nodehammer, Development
850
- # to build against it. A plain `cmake --install` still installs everything, so
851
- # existing callers are unaffected; what this adds is `--component Runtime` for a
852
- # release artifact that wants the CLI and its licences but not the headers.
897
+ # to build against it, WebRuntime for the servable wasm payload. A plain
898
+ # `cmake --install` still installs everything, so existing callers are
899
+ # unaffected; what this adds is `--component Runtime` for a release artifact
900
+ # that wants the CLI and its licences but not the headers.
853
901
  #
854
902
  # Tag every rule, not just the new ones — an untagged rule lands in a default
855
903
  # component named Unspecified and would be silently missing from *both* halves.
856
- install(TARGETS ${NH_INSTALL_TARGETS}
857
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
858
- COMPONENT Runtime
859
- )
904
+ if(EMSCRIPTEN AND NODEHAMMER_WITH_VIEWER)
905
+ # This configuration does not install a *program*. What it installs is a
906
+ # directory a web server can point at: the shell, the worker script, the
907
+ # per-backend bundles and a stamp saying what they are. Six blobs under
908
+ # bin/ were never that — `scripts/build_pages_site.sh` only worked because
909
+ # it read the shell out of the source tree it happened to be running in, so
910
+ # the artifact alone could not be served by anything that did not also have
911
+ # a checkout.
912
+ #
913
+ # share/nodehammer/web is also the rung the asset ladder looks for relative
914
+ # to the executable (docs/cli-and-web-viewer-plan.md Part 1), which is why
915
+ # it is a datadir path and not an opaque one: a native install tree and a
916
+ # wasm install tree merge into one directory that `nodehammer viewer serve`
917
+ # can resolve without being told where anything is.
918
+ install(TARGETS nodehammer-gles3 nodehammer-wgpu nodehammer-compute
919
+ RUNTIME DESTINATION "${NH_WEB_RUNTIME_DIR}"
920
+ COMPONENT WebRuntime
921
+ )
860
922
 
861
- # Emscripten produces a sidecar .wasm next to each .js loader; CMake's
862
- # install(TARGETS RUNTIME) only picks up the primary output, so install
863
- # the blobs explicitly.
864
- if(EMSCRIPTEN)
865
- foreach(_t ${NH_INSTALL_TARGETS})
923
+ # Emscripten produces a sidecar .wasm next to each .js loader; CMake's
924
+ # install(TARGETS RUNTIME) only picks up the primary output, so install
925
+ # the blobs explicitly.
926
+ foreach(_t nodehammer-gles3 nodehammer-wgpu nodehammer-compute)
866
927
  install(FILES "$<TARGET_FILE_DIR:${_t}>/${_t}.wasm"
928
+ DESTINATION "${NH_WEB_RUNTIME_DIR}"
929
+ COMPONENT WebRuntime
930
+ )
931
+ endforeach()
932
+
933
+ # The two files the browser loads that no compiler produced. They are as
934
+ # much a part of the runtime as the bundles — index.html is what picks a
935
+ # backend at all, and a bundle without its worker script tessellates on the
936
+ # main thread or not at all.
937
+ install(FILES
938
+ "${CMAKE_CURRENT_SOURCE_DIR}/web/index.html"
939
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/web/compute_worker.js"
940
+ DESTINATION "${NH_WEB_RUNTIME_DIR}"
941
+ COMPONENT WebRuntime
942
+ )
943
+
944
+ # The stamp, written beside the bundles in the build tree so that a build
945
+ # directory and an install tree are the same shape — `just wasm-serve` and
946
+ # `just pages-site` stage straight out of the former, and `viewer serve
947
+ # --web-assets build/emscripten/Release` is the first thing any developer
948
+ # reaches for.
949
+ file(GENERATE
950
+ OUTPUT "$<TARGET_FILE_DIR:nodehammer-gles3>/${NH_WEB_RUNTIME_STAMP}"
951
+ CONTENT "{\n \"schema\": ${NH_WEB_RUNTIME_SCHEMA},\n \"version\": \"${NODEHAMMER_VERSION}\"\n}\n"
952
+ )
953
+ install(FILES "$<TARGET_FILE_DIR:nodehammer-gles3>/${NH_WEB_RUNTIME_STAMP}"
954
+ DESTINATION "${NH_WEB_RUNTIME_DIR}"
955
+ COMPONENT WebRuntime
956
+ )
957
+
958
+ # "The same shape" has to include the two files no compiler produces, or the
959
+ # claim above is false in exactly the way that bites: a build tree carrying a
960
+ # stamp and bundles but no shell passes every check a stamp can make and then
961
+ # serves 404 on `/`.
962
+ #
963
+ # Symlinks, not copies, and that is the whole point: an edit to web/index.html
964
+ # is live in a served build tree with no rebuild, which is what `just
965
+ # wasm-serve`'s link mode has always given. COPY_ON_ERROR covers Windows,
966
+ # where an unprivileged symlink fails and a stale copy is better than an
967
+ # incomplete directory.
968
+ foreach(_nh_shell_file
969
+ "${CMAKE_CURRENT_SOURCE_DIR}/web/index.html"
970
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/web/compute_worker.js")
971
+ get_filename_component(_nh_shell_name "${_nh_shell_file}" NAME)
972
+ file(CREATE_LINK "${_nh_shell_file}"
973
+ "${CMAKE_CURRENT_BINARY_DIR}/${_nh_shell_name}"
974
+ COPY_ON_ERROR SYMBOLIC)
975
+ endforeach()
976
+ else()
977
+ # Native: the single nodehammer executable. Emscripten with no viewer: the
978
+ # headless nodehammer bundle (just the .js + .wasm).
979
+ install(TARGETS nodehammer
980
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
981
+ COMPONENT Runtime
982
+ )
983
+
984
+ if(EMSCRIPTEN)
985
+ install(FILES "$<TARGET_FILE_DIR:nodehammer>/nodehammer.wasm"
867
986
  DESTINATION ${CMAKE_INSTALL_BINDIR}
868
987
  COMPONENT Runtime
869
988
  )
870
- endforeach()
989
+ endif()
871
990
  endif()
872
991
 
873
992
  install(FILES "${CMAKE_SOURCE_DIR}/LICENSE"
@@ -12,6 +12,7 @@ build_nodehammer_cmd := if os_family() == "windows" { "powershell -NoProfile -Ex
12
12
 
13
13
  # Cheap to re-export every time; conan dedupes by recipe revision.
14
14
  recipes:
15
+ conan export recipes/cli11 --version=2.7.2
15
16
  conan export recipes/sokol --version=2026.07.02
16
17
  conan export recipes/imgui --version=1.92.8
17
18
  conan export recipes/implot --version=1.0.0
@@ -328,7 +329,9 @@ wheel *args:
328
329
  # the only visible difference is the filename. Catch that here rather than
329
330
  # discovering it as a CI matrix that grew from one wheel per platform to one
330
331
  # per interpreter.
331
- for whl in "$root"/dist/*.whl; do
332
+ # dist/ also holds nodehammer_web-*.whl, which is py3-none-any by design, so
333
+ # the glob names this distribution rather than every wheel in the directory.
334
+ for whl in "$root"/dist/nodehammer-*.whl; do
332
335
  case "$whl" in
333
336
  *-abi3-*) ;;
334
337
  *) echo "not an abi3 wheel: $(basename "$whl") -- STABLE_ABI did not engage" >&2
@@ -336,6 +339,65 @@ wheel *args:
336
339
  esac
337
340
  done
338
341
 
342
+ # ── the web runtime wheel ─────────────────────────────────────────────────────
343
+ # `nodehammer-web` is the other half of the Python story: a py3-none-any wheel
344
+ # holding the Emscripten build, because no native toolchain can produce one and
345
+ # a headless install has no use for 7 MB of it. See packaging/web/pyproject.toml.
346
+ #
347
+ # `src` is anything the runtime locator would accept -- a wasm build directory or
348
+ # an install tree's share/nodehammer/web -- and it is staged by the same script
349
+ # the Pages site uses, in application mode, so the payload is the one CI deploys.
350
+
351
+ # Build the nodehammer-web wheel from a wasm build (run `just wasm-release` first)
352
+ wheel-web src="build/emscripten/Release":
353
+ #!/usr/bin/env bash
354
+ set -euo pipefail
355
+ root="{{justfile_directory()}}"
356
+ src="{{src}}"
357
+ case "$src" in /*) ;; *) src="$root/$src" ;; esac
358
+ runtime="$root/packaging/web/src/nodehammer_web/runtime"
359
+ # Both sides emptied rather than overlaid. The staging directory is the
360
+ # obvious one; setuptools' build/lib is the one that bites, because
361
+ # `build_py` copies into it and never prunes -- a file dropped from the
362
+ # payload survives there and is added to the wheel from a previous run.
363
+ # Caught doing exactly that with a stale nodehammer-wgpu.wasm.zst.
364
+ rm -rf "$runtime" "$root/packaging/web/build"
365
+ "$root/scripts/stage_wasm_viewer.sh" copy none "$runtime" "$src"
366
+ uv build --wheel --out-dir "$root/dist" "$root/packaging/web"
367
+ # The mirror of the abi3 check above, and the same kind of silent failure:
368
+ # a wheel that picked up a platform tag would install nowhere it is needed.
369
+ for whl in "$root"/dist/nodehammer_web-*.whl; do
370
+ case "$whl" in
371
+ *-py3-none-any.whl) ;;
372
+ *) echo "not a pure wheel: $(basename "$whl")" >&2
373
+ exit 1 ;;
374
+ esac
375
+ done
376
+
377
+ # The only check that reaches the rung a wheel fills. `--web-assets` and
378
+ # NODEHAMMER_WEB_ASSETS are cleared out of the way on purpose: both outrank the
379
+ # package, so leaving either set would test the wrong rung and pass anyway.
380
+ #
381
+ # The pair check reads dist/, so it fails on a directory holding two versions of
382
+ # either distribution -- which is the stale-artifact case it exists to catch, and
383
+ # locally usually just means `rm -rf dist` first.
384
+
385
+ # Install both wheels from local files and serve the viewer out of them
386
+ wheel-web-test: wheel wheel-web
387
+ #!/usr/bin/env bash
388
+ set -euo pipefail
389
+ root="{{justfile_directory()}}"
390
+ uv run --no-project --with packaging "$root/scripts/check_wheel_pair.py" "$root/dist"
391
+ venv=$(mktemp -d)/venv
392
+ uv venv --python 3.12 "$venv"
393
+ # --no-index: the pair under test is the one just built, never whatever an
394
+ # index happens to resolve. Only `nodehammer` is named -- pulling the runtime
395
+ # in is the dependency's job, and naming it here would pass even if the
396
+ # generated pin had gone missing.
397
+ VIRTUAL_ENV="$venv" uv pip install --quiet --no-index \
398
+ --find-links "$root/dist" nodehammer
399
+ env -u NODEHAMMER_WEB_ASSETS "$root/scripts/check_web_serve.py" "$venv/bin/nodehammer"
400
+
339
401
  # The Python counterpart of ci/shared_consumer: the build tree resolves
340
402
  # libnodehammer through CMake's own rpath, so only an installed wheel proves the
341
403
  # relative rpath and the bundled library are right.
@@ -347,7 +409,14 @@ wheel-test: wheel
347
409
  root="{{justfile_directory()}}"
348
410
  venv=$(mktemp -d)/venv
349
411
  uv venv --python 3.12 "$venv"
350
- VIRTUAL_ENV="$venv" uv pip install --quiet pytest tomli-w "$root"/dist/nodehammer-*.whl
412
+ VIRTUAL_ENV="$venv" uv pip install --quiet pytest tomli-w
413
+ # --no-deps, in its own command so the test tools above still resolve.
414
+ # `nodehammer` requires `nodehammer-web`, which is built by a separate
415
+ # Emscripten toolchain -- resolving it here would either reach an index for
416
+ # something this recipe is not testing, or fail on a machine with no emsdk.
417
+ # What this recipe is for is the platform wheel's own payload and its
418
+ # relative rpath; `just wheel-web-test` is the one that exercises the pair.
419
+ VIRTUAL_ENV="$venv" uv pip install --quiet --no-deps "$root"/dist/nodehammer-*.whl
351
420
  cd "$root" && "$venv/bin/python" -m pytest tests/python -q
352
421
 
353
422
  # Build the Linux wheels the way CI does, in a manylinux container. Needs Docker.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nodehammer
3
- Version: 0.2.0rc1
3
+ Version: 0.2.0rc5
4
4
  Summary: Detector geometry tessellation and export
5
5
  Author: Paul Gessinger
6
6
  License-Expression: MIT
@@ -11,8 +11,10 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
11
11
  Classifier: Topic :: Scientific/Engineering :: Physics
12
12
  Project-URL: Homepage, https://github.com/paulgessinger/nodehammer
13
13
  Requires-Python: >=3.12
14
+ Requires-Dist: nodehammer-web==0.2.*
14
15
  Provides-Extra: dict
15
16
  Requires-Dist: tomli-w>=1.0; extra == "dict"
17
+ Provides-Extra: web
16
18
  Description-Content-Type: text/markdown
17
19
 
18
20
  <p align="center">
@@ -75,8 +77,7 @@ versus what's on the roadmap.
75
77
  - **Analytical geometry surgery**: semantic-level azimuthal wedge cuts and
76
78
  boolean operations via [manifold](https://github.com/elalish/manifold),
77
79
  correct on non-manifold swept primitives, cooperative with UI progress.
78
- - **CLI**: `convert`, `inspect`, `validate-config`, `config-flatten`,
79
- `dump-semantic`, `dump-render`, `viewer`.
80
+ - **CLI**: `convert`, `inspect`, `config`, `project`, `viewer`.
80
81
  - **Viewer rendering pipeline**, live today:
81
82
  - Full offscreen HDR pipeline with ACES / Reinhard / AgX tonemapping and
82
83
  exposure control
@@ -88,7 +89,7 @@ versus what's on the roadmap.
88
89
  profile — renders on demand and caps the idle frame rate
89
90
  - Live ImPlot performance graphs in the debug panel
90
91
  - High-resolution, supersampled PNG screenshot export
91
- (`nodehammer viewer --screenshot out.png ...`) — **verified on Metal**;
92
+ (`nodehammer viewer shot -o out.png ...`) — **verified on Metal**;
92
93
  the WebGL2/GLES3 and WebGPU readback paths compile and link but are not
93
94
  yet verified in-browser
94
95
  - **Builds on macOS, Linux, and Windows** natively (Metal, GLCORE, and D3D11
@@ -137,7 +138,7 @@ natively, in the browser, and behind a published link.
137
138
  | **Working set** | the live, editable in-memory project (`ZipWorkingSet`) — what the viewer edits |
138
139
  | **Archive** | a serialized `.nhproj` of a working set — the portable, publishable unit |
139
140
  | **Project manifest** | root `nodehammer.toml` *inside* the archive: `[project]` entry keys + `[view]` initial steer |
140
- | **Sidecar** | `nh_manifest.json` next to `viewer.html` — points at archive(s), carries deployment presentation (lock, steer overrides) |
141
+ | **Sidecar** | `nh_manifest.json` next to `index.html` — points at archive(s), carries deployment presentation (lock, steer overrides) |
141
142
  | **Steer** | view-state (camera, angle cut, rotation, toggles) — the ephemeral per-link layer, committed to the URL query |
142
143
  | **Provenance** | `Empty \| Local(name) \| Remote(url)` — where the working set came from; drives persistence and posture |
143
144
  | **Package** | the self-contained static folder emitted by **Publish** — drop it on any static host, zero server code |
@@ -160,18 +161,27 @@ Full design of record, including backend mapping and mode transitions:
160
161
  ## CLI
161
162
 
162
163
  ```
163
- nodehammer convert # geometry → glTF / OBJ / render IR
164
- nodehammer inspect # explore a semantic scene
165
- nodehammer validate-config # lint a TOML config before running it
166
- nodehammer config-flatten # resolve config includes/overrides
167
- nodehammer dump-semantic # dump the semantic scene as JSON
168
- nodehammer dump-render # dump the render IR as JSON
169
- nodehammer viewer # launch the interactive viewer
164
+ nodehammer convert # geometry in, anything out — the pipeline
165
+ nodehammer inspect # summary | tree | tags — ask about a scene
166
+ nodehammer config # validate | flatten — TOML and Lua configs
167
+ nodehammer project # pack | publish | info — .nhproj archives
168
+ nodehammer viewer # open | serve | shot | bench — the app
170
169
  ```
171
170
 
172
- Running the executable with no arguments at all (e.g. double-clicking
173
- `nodehammer.exe` in a file manager) also launches the viewer, in builds with
174
- `NODEHAMMER_WITH_VIEWER` enabled.
171
+ Four nouns and one verb. The design of record, including the vocabulary and why
172
+ each old name went, is [docs/cli-design.md](docs/cli-design.md).
173
+
174
+ `convert` spans the whole pipeline, and **the output format decides how far it
175
+ runs**: `-o scene.nhb` stops at the semantic scene, `-o scene.glb` tessellates
176
+ first, and asking for both in one command is one pass rather than two.
177
+ Tessellation is lossy by construction — solids become triangles — so `.nhb` is
178
+ the faithful stop and `.glb` is a one-way door.
179
+
180
+ ```bash
181
+ nodehammer project pack -c scene.toml -i odd.xml -o odd.nhproj
182
+ nodehammer viewer odd.nhproj serve # open it in a browser
183
+ nodehammer project publish odd.nhproj -o site/
184
+ ```
175
185
 
176
186
  ## Building
177
187
 
@@ -233,7 +243,7 @@ The repo ships a real detector fixture — the Open Data Detector — ready to c
233
243
 
234
244
  ```bash
235
245
  just odd # full ODD → glb (see the Justfile for single-stave recipes too)
236
- build/RelWithDebInfo/nodehammer viewer
246
+ build/RelWithDebInfo/nodehammer viewer open
237
247
  ```
238
248
 
239
249
  ### …in a browser
@@ -244,9 +254,9 @@ web build supports:
244
254
 
245
255
  | | |
246
256
  |---|---|
247
- | [`/app/`](https://paulgessinger.github.io/nodehammer/app/viewer.html) | the open application — empty start; drop a `.nhproj` or loose config/geometry files onto it |
248
- | [`/odd/`](https://paulgessinger.github.io/nodehammer/odd/viewer.html) | the full Open Data Detector, preconfigured and content-locked |
249
- | [`/odd-simple/`](https://paulgessinger.github.io/nodehammer/odd-simple/viewer.html) | the simplified ODD — same, lighter to build |
257
+ | [`/app/`](https://paulgessinger.github.io/nodehammer/app/) | the open application — empty start; drop a `.nhproj` or loose config/geometry files onto it |
258
+ | [`/odd/`](https://paulgessinger.github.io/nodehammer/odd/) | the full Open Data Detector, preconfigured and content-locked |
259
+ | [`/odd-simple/`](https://paulgessinger.github.io/nodehammer/odd-simple/) | the simplified ODD — same, lighter to build |
250
260
 
251
261
  Each directory is a self-contained static package of the kind the viewer's
252
262
  **Publish** command emits. Reproduce the whole site locally with
@@ -58,8 +58,7 @@ versus what's on the roadmap.
58
58
  - **Analytical geometry surgery**: semantic-level azimuthal wedge cuts and
59
59
  boolean operations via [manifold](https://github.com/elalish/manifold),
60
60
  correct on non-manifold swept primitives, cooperative with UI progress.
61
- - **CLI**: `convert`, `inspect`, `validate-config`, `config-flatten`,
62
- `dump-semantic`, `dump-render`, `viewer`.
61
+ - **CLI**: `convert`, `inspect`, `config`, `project`, `viewer`.
63
62
  - **Viewer rendering pipeline**, live today:
64
63
  - Full offscreen HDR pipeline with ACES / Reinhard / AgX tonemapping and
65
64
  exposure control
@@ -71,7 +70,7 @@ versus what's on the roadmap.
71
70
  profile — renders on demand and caps the idle frame rate
72
71
  - Live ImPlot performance graphs in the debug panel
73
72
  - High-resolution, supersampled PNG screenshot export
74
- (`nodehammer viewer --screenshot out.png ...`) — **verified on Metal**;
73
+ (`nodehammer viewer shot -o out.png ...`) — **verified on Metal**;
75
74
  the WebGL2/GLES3 and WebGPU readback paths compile and link but are not
76
75
  yet verified in-browser
77
76
  - **Builds on macOS, Linux, and Windows** natively (Metal, GLCORE, and D3D11
@@ -120,7 +119,7 @@ natively, in the browser, and behind a published link.
120
119
  | **Working set** | the live, editable in-memory project (`ZipWorkingSet`) — what the viewer edits |
121
120
  | **Archive** | a serialized `.nhproj` of a working set — the portable, publishable unit |
122
121
  | **Project manifest** | root `nodehammer.toml` *inside* the archive: `[project]` entry keys + `[view]` initial steer |
123
- | **Sidecar** | `nh_manifest.json` next to `viewer.html` — points at archive(s), carries deployment presentation (lock, steer overrides) |
122
+ | **Sidecar** | `nh_manifest.json` next to `index.html` — points at archive(s), carries deployment presentation (lock, steer overrides) |
124
123
  | **Steer** | view-state (camera, angle cut, rotation, toggles) — the ephemeral per-link layer, committed to the URL query |
125
124
  | **Provenance** | `Empty \| Local(name) \| Remote(url)` — where the working set came from; drives persistence and posture |
126
125
  | **Package** | the self-contained static folder emitted by **Publish** — drop it on any static host, zero server code |
@@ -143,18 +142,27 @@ Full design of record, including backend mapping and mode transitions:
143
142
  ## CLI
144
143
 
145
144
  ```
146
- nodehammer convert # geometry → glTF / OBJ / render IR
147
- nodehammer inspect # explore a semantic scene
148
- nodehammer validate-config # lint a TOML config before running it
149
- nodehammer config-flatten # resolve config includes/overrides
150
- nodehammer dump-semantic # dump the semantic scene as JSON
151
- nodehammer dump-render # dump the render IR as JSON
152
- nodehammer viewer # launch the interactive viewer
145
+ nodehammer convert # geometry in, anything out — the pipeline
146
+ nodehammer inspect # summary | tree | tags — ask about a scene
147
+ nodehammer config # validate | flatten — TOML and Lua configs
148
+ nodehammer project # pack | publish | info — .nhproj archives
149
+ nodehammer viewer # open | serve | shot | bench — the app
153
150
  ```
154
151
 
155
- Running the executable with no arguments at all (e.g. double-clicking
156
- `nodehammer.exe` in a file manager) also launches the viewer, in builds with
157
- `NODEHAMMER_WITH_VIEWER` enabled.
152
+ Four nouns and one verb. The design of record, including the vocabulary and why
153
+ each old name went, is [docs/cli-design.md](docs/cli-design.md).
154
+
155
+ `convert` spans the whole pipeline, and **the output format decides how far it
156
+ runs**: `-o scene.nhb` stops at the semantic scene, `-o scene.glb` tessellates
157
+ first, and asking for both in one command is one pass rather than two.
158
+ Tessellation is lossy by construction — solids become triangles — so `.nhb` is
159
+ the faithful stop and `.glb` is a one-way door.
160
+
161
+ ```bash
162
+ nodehammer project pack -c scene.toml -i odd.xml -o odd.nhproj
163
+ nodehammer viewer odd.nhproj serve # open it in a browser
164
+ nodehammer project publish odd.nhproj -o site/
165
+ ```
158
166
 
159
167
  ## Building
160
168
 
@@ -216,7 +224,7 @@ The repo ships a real detector fixture — the Open Data Detector — ready to c
216
224
 
217
225
  ```bash
218
226
  just odd # full ODD → glb (see the Justfile for single-stave recipes too)
219
- build/RelWithDebInfo/nodehammer viewer
227
+ build/RelWithDebInfo/nodehammer viewer open
220
228
  ```
221
229
 
222
230
  ### …in a browser
@@ -227,9 +235,9 @@ web build supports:
227
235
 
228
236
  | | |
229
237
  |---|---|
230
- | [`/app/`](https://paulgessinger.github.io/nodehammer/app/viewer.html) | the open application — empty start; drop a `.nhproj` or loose config/geometry files onto it |
231
- | [`/odd/`](https://paulgessinger.github.io/nodehammer/odd/viewer.html) | the full Open Data Detector, preconfigured and content-locked |
232
- | [`/odd-simple/`](https://paulgessinger.github.io/nodehammer/odd-simple/viewer.html) | the simplified ODD — same, lighter to build |
238
+ | [`/app/`](https://paulgessinger.github.io/nodehammer/app/) | the open application — empty start; drop a `.nhproj` or loose config/geometry files onto it |
239
+ | [`/odd/`](https://paulgessinger.github.io/nodehammer/odd/) | the full Open Data Detector, preconfigured and content-locked |
240
+ | [`/odd-simple/`](https://paulgessinger.github.io/nodehammer/odd-simple/) | the simplified ODD — same, lighter to build |
233
241
 
234
242
  Each directory is a self-contained static package of the kind the viewer's
235
243
  **Publish** command emits. Reproduce the whole site locally with
@@ -50,6 +50,7 @@ esac
50
50
 
51
51
  case "$cmd" in
52
52
  conan-install)
53
+ conan export recipes/cli11 --version=2.7.2
53
54
  conan export recipes/sokol --version=2026.07.02
54
55
  conan export recipes/imgui --version=1.92.8
55
56
  conan export recipes/implot --version=1.0.0
@@ -108,12 +108,13 @@ int main() {
108
108
  }
109
109
  std::cout << std::flush;
110
110
 
111
- if (!listed(semanticFormats, "synthetic") || !listed(semanticFormats, "flatbuffer")) {
111
+ if (!listed(semanticFormats, "synthetic") || !listed(semanticFormats, "nhb")) {
112
112
  std::cerr << "SemanticScene::formats() is missing a built-in format\n";
113
113
  return 1;
114
114
  }
115
115
  if (!listed(nodehammer::Config::formats(), "toml") ||
116
- !listed(nodehammer::RenderScene::formats(), "gltf")) {
116
+ !listed(nodehammer::RenderScene::formats(), "gltf") ||
117
+ !listed(nodehammer::RenderScene::formats(), "nhr")) {
117
118
  std::cerr << "a built-in format is missing from formats()\n";
118
119
  return 1;
119
120
  }
@@ -39,11 +39,14 @@ FetchContent_Declare(Catch2
39
39
  FetchContent_MakeAvailable(Catch2)
40
40
 
41
41
  # ── CLI11 ─────────────────────────────────────────────────────────────────────
42
+ # 2.7.2 is a floor, not a preference. Up to and including 2.6.2 CLI11's character
43
+ # tables were namespace-scope references bound to temporaries, which Emscripten
44
+ # cannot run an atexit chain over -- see recipes/cli11/conanfile.py and issue #76.
42
45
  FetchContent_Declare(CLI11
43
46
  SYSTEM
44
47
  GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
45
- GIT_TAG v2.6.2
46
- FIND_PACKAGE_ARGS 2.6.2
48
+ GIT_TAG v2.7.2
49
+ FIND_PACKAGE_ARGS 2.7.2
47
50
  )
48
51
  FetchContent_MakeAvailable(CLI11)
49
52
 
@@ -56,6 +59,27 @@ FetchContent_Declare(nlohmann_json
56
59
  )
57
60
  FetchContent_MakeAvailable(nlohmann_json)
58
61
 
62
+ # ── cpp-httplib ───────────────────────────────────────────────────────────────
63
+ # The static server behind `viewer serve`. Native only: the wasm build has no
64
+ # sockets, and the module it would serve is the thing being served.
65
+ #
66
+ # Chosen over the ~370 hand-rolled lines it replaces because it is *less* code
67
+ # for today's behaviour, not only because of what comes next. What comes next
68
+ # does matter though: `HttpProjectFs` needs request bodies and routing, and an
69
+ # experiment framework pushing events needs a parser that has been attacked. The
70
+ # `set_mount_point` + `set_default_headers` + `bind_to_any_port` trio covers the
71
+ # static case in a few lines, and WebSocket (since 0.33.0) plus chunked content
72
+ # providers cover the rest without a second dependency.
73
+ if(NOT EMSCRIPTEN)
74
+ FetchContent_Declare(httplib
75
+ SYSTEM
76
+ GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
77
+ GIT_TAG v0.47.0
78
+ FIND_PACKAGE_ARGS 0.47.0
79
+ )
80
+ FetchContent_MakeAvailable(httplib)
81
+ endif()
82
+
59
83
  # ── GLM ───────────────────────────────────────────────────────────────────────
60
84
  FetchContent_Declare(glm
61
85
  SYSTEM
@@ -191,7 +215,7 @@ if(TARGET flatbuffers)
191
215
  endif()
192
216
 
193
217
  # ── Lua config front-end (lua + sol2) ────────────────────────────────────────
194
- # Powers the `config-lua` CLI command and `Config::read`'s `.lua` branch — an
218
+ # Powers the `config flatten` CLI command and `Config::read`'s `.lua` branch — an
195
219
  # unconditional source in nodehammer_lib on every platform, Emscripten included.
196
220
  # Both come from Conan (lua has no clean upstream CMake — it ships a Makefile —
197
221
  # so, like imgui/implot below, we resolve via find_package rather than a git