@downdraft/engine 0.1.0 → 0.1.2-alpha.5

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 (1022) hide show
  1. package/README.md +33 -0
  2. package/app/README.md +11 -0
  3. package/app/src/renderer/bootstrap.ts +295 -19
  4. package/app/src/renderer/game-module.ts +60 -12
  5. package/app/src/renderer/hooks.ts +9 -1
  6. package/app/src/renderer/hot-reload.ts +9 -9
  7. package/app/src/renderer/mcp-harness.ts +2 -2
  8. package/app/src/renderer/standard-automation-tools.ts +104 -3
  9. package/app/src/shared/feature-log.ts +2 -1
  10. package/app/src/shared/mcp-discovery.ts +8 -3
  11. package/app/src/shared/mcp-proxy.ts +2 -2
  12. package/asset-bake/README.md +22 -0
  13. package/core/README.md +25 -0
  14. package/core/src/animation/skeleton-animator.ts +23 -5
  15. package/core/src/assets/manager.ts +4 -4
  16. package/core/src/ecs/events.ts +1 -1
  17. package/core/src/ecs/schedule.ts +1 -1
  18. package/core/src/ecs/world.ts +1 -1
  19. package/core/src/index.ts +3 -4
  20. package/core/src/library/host.ts +27 -13
  21. package/core/src/library/library.ts +13 -5
  22. package/core/src/module/cross-thread.ts +6 -0
  23. package/core/src/module/diagnostics.ts +10 -6
  24. package/core/src/module/host.ts +65 -18
  25. package/core/src/module/index.ts +1 -0
  26. package/core/src/module/module.ts +11 -5
  27. package/core/src/module/renderer-module.ts +15 -0
  28. package/core/src/physics/safety.ts +1 -1
  29. package/core/src/platform/bun-preload.ts +7 -2
  30. package/core/src/platform/glob-polyfill.ts +17 -8
  31. package/core/src/platform/pkg-root.ts +27 -0
  32. package/core/src/platform/runtime.ts +38 -0
  33. package/core/src/plugin/discovery.ts +1 -1
  34. package/core/src/plugin/extension-loaders.ts +6 -4
  35. package/core/src/plugin/host.ts +13 -13
  36. package/core/src/plugin/loader-asset.ts +5 -5
  37. package/core/src/plugin/loader-quickjs.ts +1 -1
  38. package/core/src/plugin/loader-wasm.ts +3 -3
  39. package/core/src/plugin/loader-worker.ts +1 -1
  40. package/core/src/plugin/manifest.ts +8 -3
  41. package/core/src/plugin/workshop.ts +3 -3
  42. package/core/src/profiling/index.ts +1 -1
  43. package/core/src/profiling/profiling-sab.ts +19 -0
  44. package/core/src/profiling/warnings.ts +1 -1
  45. package/core/src/profiling/worker-prelude.ts +1 -1
  46. package/core/src/render/bindless/frame-bindings.ts +1 -1
  47. package/core/src/render/bindless/material-manager.ts +2 -2
  48. package/core/src/render/bindless/texture-registry.ts +2 -2
  49. package/core/src/render/device.ts +5 -5
  50. package/core/src/render/frame-graph.ts +2 -2
  51. package/core/src/render/game-renderer.ts +42 -18
  52. package/core/src/render/hot-reload.ts +3 -3
  53. package/core/src/render/renderer-module-host.ts +32 -12
  54. package/core/src/render/shader-validator.ts +7 -7
  55. package/core/src/render/surface.ts +1 -1
  56. package/core/src/sab/errors.ts +1 -1
  57. package/core/src/sab/sab-polyfill.ts +1 -1
  58. package/core/src/save/migration-registry.ts +4 -4
  59. package/core/src/save/schema.ts +1 -1
  60. package/core/src/scene/prefab.ts +1 -1
  61. package/core/src/scene/scene-manager.ts +2 -2
  62. package/core/src/scene/scene.ts +4 -4
  63. package/core/src/scene/streaming.ts +2 -2
  64. package/core/src/scripting/hot-reload.ts +2 -2
  65. package/core/src/sim/hot-reload-pipeline.ts +30 -6
  66. package/core/src/sim/sim-state-helper.ts +1 -1
  67. package/core/src/sim/transient-state-registry.ts +1 -1
  68. package/core/src/sim/worker-loop.ts +2 -2
  69. package/core/src/telemetry/gpu-profiler.ts +3 -3
  70. package/core/src/util/index.ts +1 -1
  71. package/core/src/util/logger.ts +36 -5
  72. package/core/src/version.ts +13 -0
  73. package/core/src/worker/base-worker-host.ts +87 -25
  74. package/core/src/worker/buffer-sync.ts +1 -1
  75. package/core/src/worker/crash-recovery.ts +2 -2
  76. package/core/src/worker/instrumented-worker-host.ts +3 -3
  77. package/core/src/worker/rpc.ts +62 -11
  78. package/core/src/worker/sim-worker-base.ts +3 -8
  79. package/core/src/worker/task-pool.ts +2 -2
  80. package/dist/.dd-manifest.json +4119 -0
  81. package/dist/app/src/index.js +9 -0
  82. package/dist/app/src/renderer/bootstrap.js +446 -0
  83. package/dist/app/src/renderer/downdraft-base.css +93 -0
  84. package/dist/app/src/renderer/feature-log.js +180 -0
  85. package/dist/app/src/renderer/game-module.js +562 -0
  86. package/dist/app/src/renderer/hooks.js +82 -0
  87. package/dist/app/src/renderer/hot-reload.js +158 -0
  88. package/dist/app/src/renderer/import-cache.js +77 -0
  89. package/dist/app/src/renderer/index.js +149 -0
  90. package/dist/app/src/renderer/mcp-harness.js +112 -0
  91. package/dist/app/src/renderer/save-store-factory.js +180 -0
  92. package/dist/app/src/renderer/sim-bridge.js +138 -0
  93. package/dist/app/src/renderer/standard-automation-tools.js +720 -0
  94. package/dist/app/src/shared/feature-log.js +54 -0
  95. package/dist/app/src/shared/gpu-info.js +74 -0
  96. package/dist/app/src/shared/import-cache-store.js +123 -0
  97. package/dist/app/src/shared/index.js +4 -0
  98. package/dist/app/src/shared/mcp-discovery.js +55 -0
  99. package/dist/app/src/shared/mcp-proxy.js +71 -0
  100. package/dist/app/src/shared/types.js +13 -0
  101. package/dist/asset-bake/src/bake-audio.js +103 -0
  102. package/dist/asset-bake/src/bake-gltf.js +141 -0
  103. package/dist/asset-bake/src/bake.js +63 -0
  104. package/dist/asset-bake/src/cache.js +147 -0
  105. package/dist/asset-bake/src/config.js +93 -0
  106. package/dist/asset-bake/src/index.js +25 -0
  107. package/dist/core/src/animation/animation-event.js +24 -0
  108. package/dist/core/src/animation/bone-mask.js +103 -0
  109. package/dist/core/src/animation/clip.js +210 -0
  110. package/dist/core/src/animation/index.js +13 -0
  111. package/dist/core/src/animation/mixamo.js +78 -0
  112. package/dist/core/src/animation/morph-target.js +37 -0
  113. package/dist/core/src/animation/player.js +621 -0
  114. package/dist/core/src/animation/retarget.js +101 -0
  115. package/dist/core/src/animation/skeleton-animator.js +1361 -0
  116. package/dist/core/src/animation/skeleton.js +166 -0
  117. package/dist/core/src/animation/state-machine.js +252 -0
  118. package/dist/core/src/assets/blob-store.js +14 -0
  119. package/dist/core/src/assets/cache.js +168 -0
  120. package/dist/core/src/assets/cubemap-converter.js +129 -0
  121. package/dist/core/src/assets/environment-manager.js +84 -0
  122. package/dist/core/src/assets/import-cache.js +36 -0
  123. package/dist/core/src/assets/import-settings.js +34 -0
  124. package/dist/core/src/assets/importer.js +78 -0
  125. package/dist/core/src/assets/index.js +29 -0
  126. package/dist/core/src/assets/irradiance-generator.js +179 -0
  127. package/dist/core/src/assets/loader-audio.js +70 -0
  128. package/dist/core/src/assets/loader-cubemap.js +141 -0
  129. package/dist/core/src/assets/loader-dds.js +185 -0
  130. package/dist/core/src/assets/loader-hdr.js +430 -0
  131. package/dist/core/src/assets/loader-mesh.js +47 -0
  132. package/dist/core/src/assets/loader-shader.js +61 -0
  133. package/dist/core/src/assets/loader-texture.js +264 -0
  134. package/dist/core/src/assets/lod.js +150 -0
  135. package/dist/core/src/assets/manager.js +401 -0
  136. package/dist/core/src/assets/manifest.js +57 -0
  137. package/dist/core/src/assets/material-bridge.js +160 -0
  138. package/dist/core/src/assets/model-importer.js +32 -0
  139. package/dist/core/src/assets/model-normalizer.js +213 -0
  140. package/dist/core/src/assets/model-to-gpu.js +44 -0
  141. package/dist/core/src/assets/model-to-mesh.js +171 -0
  142. package/dist/core/src/assets/prefilter-generator.js +220 -0
  143. package/dist/core/src/audio/engine.js +153 -0
  144. package/dist/core/src/audio/interface.js +8 -0
  145. package/dist/core/src/audio/listener.js +19 -0
  146. package/dist/core/src/audio/mixer.js +124 -0
  147. package/dist/core/src/audio/registry.js +43 -0
  148. package/dist/core/src/audio/sab.js +74 -0
  149. package/dist/core/src/audio/source.js +60 -0
  150. package/dist/core/src/change-detection/atomics.js +1 -0
  151. package/dist/core/src/change-detection/tracker.js +26 -0
  152. package/dist/core/src/debug-draw/lines.js +27 -0
  153. package/dist/core/src/debug-draw/points.js +9 -0
  154. package/dist/core/src/debug-draw/queue.js +77 -0
  155. package/dist/core/src/debug-draw/text.js +12 -0
  156. package/dist/core/src/ecs/archetype.js +271 -0
  157. package/dist/core/src/ecs/component.js +109 -0
  158. package/dist/core/src/ecs/entity.js +11 -0
  159. package/dist/core/src/ecs/events.js +73 -0
  160. package/dist/core/src/ecs/hierarchy.js +104 -0
  161. package/dist/core/src/ecs/hmr-swap-registry.js +15 -0
  162. package/dist/core/src/ecs/index.js +14 -0
  163. package/dist/core/src/ecs/query.js +110 -0
  164. package/dist/core/src/ecs/resource.js +3 -0
  165. package/dist/core/src/ecs/schedule.js +157 -0
  166. package/dist/core/src/ecs/system-params.js +45 -0
  167. package/dist/core/src/ecs/system.js +18 -0
  168. package/dist/core/src/ecs/world.js +292 -0
  169. package/dist/core/src/index.js +191 -0
  170. package/dist/core/src/input/context.js +69 -0
  171. package/dist/core/src/input/dom-handler.js +288 -0
  172. package/dist/core/src/input/local-player-manager.js +145 -0
  173. package/dist/core/src/input/mapping.js +36 -0
  174. package/dist/core/src/input/multi-sab-bridge.js +224 -0
  175. package/dist/core/src/input/multi-state.js +48 -0
  176. package/dist/core/src/input/sab-bridge.js +66 -0
  177. package/dist/core/src/input/state.js +108 -0
  178. package/dist/core/src/input/ui-router.js +76 -0
  179. package/dist/core/src/library/host.js +291 -0
  180. package/dist/core/src/library/index.js +1 -0
  181. package/dist/core/src/library/library.js +20 -0
  182. package/dist/core/src/material/compiler.js +73 -0
  183. package/dist/core/src/material/graph-bridge.js +119 -0
  184. package/dist/core/src/material/index.js +6 -0
  185. package/dist/core/src/material/library.js +414 -0
  186. package/dist/core/src/material/material.js +120 -0
  187. package/dist/core/src/material/variants.js +37 -0
  188. package/dist/core/src/math/mat4.js +198 -0
  189. package/dist/core/src/math/perlin-noise-2d.js +66 -0
  190. package/dist/core/src/math/perlin-noise-3d.js +76 -0
  191. package/dist/core/src/math/quat.js +29 -0
  192. package/dist/core/src/math/rng.js +25 -0
  193. package/dist/core/src/math/trig.js +42 -0
  194. package/dist/core/src/math/value-noise.js +49 -0
  195. package/dist/core/src/mesh/builder.js +137 -0
  196. package/dist/core/src/mesh/csg.js +250 -0
  197. package/dist/core/src/mesh/greased-line.js +102 -0
  198. package/dist/core/src/mesh/mesh.js +6 -0
  199. package/dist/core/src/mesh/parametric.js +392 -0
  200. package/dist/core/src/mesh/skinning.js +30 -0
  201. package/dist/core/src/mesh/vertex-layout.js +65 -0
  202. package/dist/core/src/module/cross-thread.js +126 -0
  203. package/dist/core/src/module/diagnostics.js +99 -0
  204. package/dist/core/src/module/host.js +449 -0
  205. package/dist/core/src/module/index.js +6 -0
  206. package/dist/core/src/module/module.js +1 -0
  207. package/dist/core/src/module/registry.js +83 -0
  208. package/dist/core/src/module/renderer-module.js +13 -0
  209. package/dist/core/src/module/ts-loader.js +20 -0
  210. package/dist/core/src/particles/compute-pass.js +329 -0
  211. package/dist/core/src/particles/emitter.js +113 -0
  212. package/dist/core/src/particles/index.js +7 -0
  213. package/dist/core/src/particles/particle-data.js +33 -0
  214. package/dist/core/src/particles/render-pass.js +338 -0
  215. package/dist/core/src/particles/simulator.js +224 -0
  216. package/dist/core/src/particles/system.js +157 -0
  217. package/dist/core/src/physics/body.js +25 -0
  218. package/dist/core/src/physics/ccd-heuristic.js +46 -0
  219. package/dist/core/src/physics/character.js +184 -0
  220. package/dist/core/src/physics/collider.js +36 -0
  221. package/dist/core/src/physics/collision-system.js +62 -0
  222. package/dist/core/src/physics/events.js +74 -0
  223. package/dist/core/src/physics/index.js +24 -0
  224. package/dist/core/src/physics/interface.js +14 -0
  225. package/dist/core/src/physics/interpolation-buffer.js +182 -0
  226. package/dist/core/src/physics/lifecycle.js +66 -0
  227. package/dist/core/src/physics/load-shedder.js +155 -0
  228. package/dist/core/src/physics/physics-accumulator.js +94 -0
  229. package/dist/core/src/physics/physics-system.js +142 -0
  230. package/dist/core/src/physics/ragdoll-presets.js +248 -0
  231. package/dist/core/src/physics/ragdoll-system.js +193 -0
  232. package/dist/core/src/physics/ragdoll.js +117 -0
  233. package/dist/core/src/physics/raycast.js +97 -0
  234. package/dist/core/src/physics/realm-manager.js +431 -0
  235. package/dist/core/src/physics/realm-worker-pool.js +181 -0
  236. package/dist/core/src/physics/realm-worker.js +91 -0
  237. package/dist/core/src/physics/realm.js +137 -0
  238. package/dist/core/src/physics/registry.js +43 -0
  239. package/dist/core/src/physics/safety.js +211 -0
  240. package/dist/core/src/physics/snapshot-manager.js +118 -0
  241. package/dist/core/src/physics/worker-protocol.js +1 -0
  242. package/dist/core/src/platform/bun-preload.js +175 -0
  243. package/dist/core/src/platform/css-stub.js +4 -0
  244. package/dist/core/src/platform/glob-polyfill.js +137 -0
  245. package/dist/core/src/platform/hidpi.js +52 -0
  246. package/dist/core/src/platform/pkg-root.js +27 -0
  247. package/dist/core/src/platform/render-surface.js +15 -0
  248. package/dist/core/src/platform/rpc.js +82 -0
  249. package/dist/core/src/platform/runtime.js +93 -0
  250. package/dist/core/src/plugin/context.js +144 -0
  251. package/dist/core/src/plugin/diagnostics.js +20 -0
  252. package/dist/core/src/plugin/discovery.js +124 -0
  253. package/dist/core/src/plugin/extension-loaders.js +111 -0
  254. package/dist/core/src/plugin/host.js +542 -0
  255. package/dist/core/src/plugin/index.js +19 -0
  256. package/dist/core/src/plugin/loader-asset.js +105 -0
  257. package/dist/core/src/plugin/loader-quickjs.js +67 -0
  258. package/dist/core/src/plugin/loader-wasm.js +385 -0
  259. package/dist/core/src/plugin/loader-worker.js +228 -0
  260. package/dist/core/src/plugin/manifest.js +424 -0
  261. package/dist/core/src/plugin/material-registry.js +44 -0
  262. package/dist/core/src/plugin/mcp-tools.js +147 -0
  263. package/dist/core/src/plugin/permissions.js +152 -0
  264. package/dist/core/src/plugin/quickjs-bridge.js +219 -0
  265. package/dist/core/src/plugin/registry.js +92 -0
  266. package/dist/core/src/plugin/sandbox-shim.js +79 -0
  267. package/dist/core/src/plugin/sandbox-worker.js +194 -0
  268. package/dist/core/src/plugin/wasm-abi.js +62 -0
  269. package/dist/core/src/plugin/wasm-worker.js +234 -0
  270. package/dist/core/src/plugin/workshop.js +131 -0
  271. package/dist/core/src/profiling/event-loop.js +164 -0
  272. package/dist/core/src/profiling/index.js +23 -0
  273. package/dist/core/src/profiling/iops/idb-patch.js +211 -0
  274. package/dist/core/src/profiling/iops/opfs-patch.js +206 -0
  275. package/dist/core/src/profiling/profiling-sab.js +632 -0
  276. package/dist/core/src/profiling/task-latency.js +118 -0
  277. package/dist/core/src/profiling/thread-metrics.js +103 -0
  278. package/dist/core/src/profiling/trace-event-writer.js +165 -0
  279. package/dist/core/src/profiling/warnings.js +304 -0
  280. package/dist/core/src/profiling/worker-prelude.js +281 -0
  281. package/dist/core/src/render/bind-group.js +33 -0
  282. package/dist/core/src/render/bindless/bindless-struct.js +39 -0
  283. package/dist/core/src/render/bindless/bindless.wgsl.js +163 -0
  284. package/dist/core/src/render/bindless/frame-bindings.js +142 -0
  285. package/dist/core/src/render/bindless/index.js +6 -0
  286. package/dist/core/src/render/bindless/material-manager.js +182 -0
  287. package/dist/core/src/render/bindless/texture-registry.js +498 -0
  288. package/dist/core/src/render/buffer.js +74 -0
  289. package/dist/core/src/render/camera-2d.js +151 -0
  290. package/dist/core/src/render/camera-controller.js +370 -0
  291. package/dist/core/src/render/camera.js +332 -0
  292. package/dist/core/src/render/canvas-resize-watcher.js +36 -0
  293. package/dist/core/src/render/compute-kernel.js +130 -0
  294. package/dist/core/src/render/constants.js +2 -0
  295. package/dist/core/src/render/device.js +91 -0
  296. package/dist/core/src/render/frame-graph.js +594 -0
  297. package/dist/core/src/render/frustum.js +152 -0
  298. package/dist/core/src/render/fullscreen-vs.js +24 -0
  299. package/dist/core/src/render/g-buffer.js +156 -0
  300. package/dist/core/src/render/game-renderer.js +1165 -0
  301. package/dist/core/src/render/gpu-driven/cull-pass.js +352 -0
  302. package/dist/core/src/render/gpu-driven/hzb.js +183 -0
  303. package/dist/core/src/render/gpu-driven/index.js +6 -0
  304. package/dist/core/src/render/gpu-driven/indirect-draw-pass.js +300 -0
  305. package/dist/core/src/render/gpu-driven/instance-buffer.js +150 -0
  306. package/dist/core/src/render/gpu-driven/mesh-table.js +130 -0
  307. package/dist/core/src/render/gpu-driven/passes/hzb-build-pass.js +39 -0
  308. package/dist/core/src/render/gpu-utils.js +72 -0
  309. package/dist/core/src/render/hdr.js +69 -0
  310. package/dist/core/src/render/hot-reload.js +236 -0
  311. package/dist/core/src/render/ibl-bind-group.js +232 -0
  312. package/dist/core/src/render/ibl.js +148 -0
  313. package/dist/core/src/render/index.js +86 -0
  314. package/dist/core/src/render/input-manager.js +224 -0
  315. package/dist/core/src/render/lighting/area-light.js +142 -0
  316. package/dist/core/src/render/lighting/cluster-grid.js +255 -0
  317. package/dist/core/src/render/lighting/cluster-types.js +87 -0
  318. package/dist/core/src/render/lighting/ies-parser.js +111 -0
  319. package/dist/core/src/render/lighting.js +300 -0
  320. package/dist/core/src/render/material-types/depth.wgsl +44 -0
  321. package/dist/core/src/render/material-types/line.wgsl +50 -0
  322. package/dist/core/src/render/material-types/matcap.wgsl +51 -0
  323. package/dist/core/src/render/material-types/normal.wgsl +41 -0
  324. package/dist/core/src/render/material-types/physical.wgsl +152 -0
  325. package/dist/core/src/render/material-types/sprite.wgsl +46 -0
  326. package/dist/core/src/render/material-types/sss.wgsl +79 -0
  327. package/dist/core/src/render/material-types/toon.wgsl +79 -0
  328. package/dist/core/src/render/passes/README.md +121 -0
  329. package/dist/core/src/render/passes/atmosphere.js +107 -0
  330. package/dist/core/src/render/passes/cluster-lighting-pass.js +441 -0
  331. package/dist/core/src/render/passes/csm.js +338 -0
  332. package/dist/core/src/render/passes/cubemap-capture.js +93 -0
  333. package/dist/core/src/render/passes/debug-viz.js +248 -0
  334. package/dist/core/src/render/passes/debug.js +500 -0
  335. package/dist/core/src/render/passes/decal-mesh.js +86 -0
  336. package/dist/core/src/render/passes/decal-pass.js +344 -0
  337. package/dist/core/src/render/passes/deferred-lighting.js +406 -0
  338. package/dist/core/src/render/passes/depth-prepass.js +148 -0
  339. package/dist/core/src/render/passes/dome-360.js +68 -0
  340. package/dist/core/src/render/passes/fluid-render.js +116 -0
  341. package/dist/core/src/render/passes/gi-types.js +78 -0
  342. package/dist/core/src/render/passes/graph-compute.js +251 -0
  343. package/dist/core/src/render/passes/greased-line-pass.js +218 -0
  344. package/dist/core/src/render/passes/morph-target.js +35 -0
  345. package/dist/core/src/render/passes/opaque.js +966 -0
  346. package/dist/core/src/render/passes/point-light-shadow.js +221 -0
  347. package/dist/core/src/render/passes/procedural-texture.js +142 -0
  348. package/dist/core/src/render/passes/reflection-probe.js +100 -0
  349. package/dist/core/src/render/passes/rsm-pass.js +228 -0
  350. package/dist/core/src/render/passes/sdf-text.js +114 -0
  351. package/dist/core/src/render/passes/shadow-map.js +121 -0
  352. package/dist/core/src/render/passes/shadow.js +191 -0
  353. package/dist/core/src/render/passes/skinning-vs.js +102 -0
  354. package/dist/core/src/render/passes/skinning.js +282 -0
  355. package/dist/core/src/render/passes/sky-dome.js +380 -0
  356. package/dist/core/src/render/passes/skybox.js +146 -0
  357. package/dist/core/src/render/passes/spot-light-shadow.js +223 -0
  358. package/dist/core/src/render/passes/terrain.js +303 -0
  359. package/dist/core/src/render/passes/transparent.js +323 -0
  360. package/dist/core/src/render/passes/underwater-fog.js +173 -0
  361. package/dist/core/src/render/passes/video-texture.js +58 -0
  362. package/dist/core/src/render/passes/volumetric-pass.js +278 -0
  363. package/dist/core/src/render/passes/volumetric-types.js +96 -0
  364. package/dist/core/src/render/passes/water.js +697 -0
  365. package/dist/core/src/render/pbr.js +257 -0
  366. package/dist/core/src/render/pipeline.js +49 -0
  367. package/dist/core/src/render/render-pass.js +13 -0
  368. package/dist/core/src/render/renderer-input-bus.js +176 -0
  369. package/dist/core/src/render/renderer-module-host.js +539 -0
  370. package/dist/core/src/render/resource-tracker.js +59 -0
  371. package/dist/core/src/render/sab-canvas-overlay.js +83 -0
  372. package/dist/core/src/render/shader-validator.js +172 -0
  373. package/dist/core/src/render/shaders/debug/debug-line.wgsl +27 -0
  374. package/dist/core/src/render/shaders/debug/debug-point.wgsl +30 -0
  375. package/dist/core/src/render/shaders/debug/debug-text.wgsl +42 -0
  376. package/dist/core/src/render/shaders/debug-viz/aabb.wgsl +20 -0
  377. package/dist/core/src/render/shaders/debug-viz/depth.wgsl +29 -0
  378. package/dist/core/src/render/shaders/debug-viz/lod.wgsl +38 -0
  379. package/dist/core/src/render/shaders/debug-viz/normals.wgsl +30 -0
  380. package/dist/core/src/render/shaders/debug-viz/overdraw.wgsl +21 -0
  381. package/dist/core/src/render/shaders/debug-viz/tangents.wgsl +29 -0
  382. package/dist/core/src/render/shaders/debug-viz/wireframe.wgsl +33 -0
  383. package/dist/core/src/render/shaders/shadow-chunks.js +133 -0
  384. package/dist/core/src/render/skybox.js +123 -0
  385. package/dist/core/src/render/splitscreen.js +60 -0
  386. package/dist/core/src/render/surface.js +63 -0
  387. package/dist/core/src/render/tonemap.js +171 -0
  388. package/dist/core/src/render/tracked-render-pass.js +115 -0
  389. package/dist/core/src/render/viewport.js +81 -0
  390. package/dist/core/src/render/wgsl-hmr.js +66 -0
  391. package/dist/core/src/sab/core-input-channel.js +22 -0
  392. package/dist/core/src/sab/define.js +127 -0
  393. package/dist/core/src/sab/errors.js +60 -0
  394. package/dist/core/src/sab/game-input.js +299 -0
  395. package/dist/core/src/sab/gamepad-devices.js +205 -0
  396. package/dist/core/src/sab/grid-buffer.js +91 -0
  397. package/dist/core/src/sab/input.js +38 -0
  398. package/dist/core/src/sab/layout.js +160 -0
  399. package/dist/core/src/sab/multi-input-channel.js +39 -0
  400. package/dist/core/src/sab/record-buffer.js +130 -0
  401. package/dist/core/src/sab/sab-polyfill.js +47 -0
  402. package/dist/core/src/sab/sim-channel.js +397 -0
  403. package/dist/core/src/sab/slot-buffer.js +140 -0
  404. package/dist/core/src/sab/types.js +1 -0
  405. package/dist/core/src/safety/bounds.js +71 -0
  406. package/dist/core/src/safety/json.js +70 -0
  407. package/dist/core/src/safety/path.js +151 -0
  408. package/dist/core/src/save/binary-format.js +95 -0
  409. package/dist/core/src/save/game-save-system.js +101 -0
  410. package/dist/core/src/save/grid-save-system.js +102 -0
  411. package/dist/core/src/save/migrate.js +35 -0
  412. package/dist/core/src/save/migration-registry.js +66 -0
  413. package/dist/core/src/save/persist-types.js +4 -0
  414. package/dist/core/src/save/schema.js +36 -0
  415. package/dist/core/src/save/serializer.js +139 -0
  416. package/dist/core/src/scene/builder.js +31 -0
  417. package/dist/core/src/scene/camera.js +118 -0
  418. package/dist/core/src/scene/checkpoint.js +84 -0
  419. package/dist/core/src/scene/game-loop.js +155 -0
  420. package/dist/core/src/scene/index.js +14 -0
  421. package/dist/core/src/scene/layer.js +7 -0
  422. package/dist/core/src/scene/prefab.js +97 -0
  423. package/dist/core/src/scene/scene-manager.js +141 -0
  424. package/dist/core/src/scene/scene.js +147 -0
  425. package/dist/core/src/scene/sky.js +179 -0
  426. package/dist/core/src/scene/spatial-grid.js +140 -0
  427. package/dist/core/src/scene/streaming.js +247 -0
  428. package/dist/core/src/scene/vegetation.js +107 -0
  429. package/dist/core/src/scene/world.js +66 -0
  430. package/dist/core/src/scripting/binding.js +85 -0
  431. package/dist/core/src/scripting/hot-reload.js +123 -0
  432. package/dist/core/src/scripting/script.js +68 -0
  433. package/dist/core/src/sim/hot-reload-pipeline.js +65 -0
  434. package/dist/core/src/sim/sim-state-helper.js +40 -0
  435. package/dist/core/src/sim/transient-state-registry.js +63 -0
  436. package/dist/core/src/sim/types.js +4 -0
  437. package/dist/core/src/sim/worker-loop.js +168 -0
  438. package/dist/core/src/stores/game-store.js +81 -0
  439. package/dist/core/src/stores/hot-reload-store.js +19 -0
  440. package/dist/core/src/telemetry/collector.js +303 -0
  441. package/dist/core/src/telemetry/gc-controller.js +365 -0
  442. package/dist/core/src/telemetry/gc-profiler.js +82 -0
  443. package/dist/core/src/telemetry/gc-tracker.js +63 -0
  444. package/dist/core/src/telemetry/gpu-profiler.js +554 -0
  445. package/dist/core/src/telemetry/gpu-resource-tracker.js +234 -0
  446. package/dist/core/src/telemetry/gpu-timer-pool.js +223 -0
  447. package/dist/core/src/telemetry/gpu-timer.js +117 -0
  448. package/dist/core/src/telemetry/gpu-timestamp-gate.js +22 -0
  449. package/dist/core/src/telemetry/reporter.js +56 -0
  450. package/dist/core/src/types/engine-types.js +21 -0
  451. package/dist/core/src/ui-font-scale.js +111 -0
  452. package/dist/core/src/util/broad-phase-grid.js +77 -0
  453. package/dist/core/src/util/feature-log.js +176 -0
  454. package/dist/core/src/util/index.js +4 -0
  455. package/dist/core/src/util/logger.js +596 -0
  456. package/dist/core/src/version.js +11 -0
  457. package/dist/core/src/webgpu-destroy-augmentation.d.ts +25 -0
  458. package/dist/core/src/worker/base-worker-host.js +212 -0
  459. package/dist/core/src/worker/buffer-sync.js +454 -0
  460. package/dist/core/src/worker/crash-recovery.js +153 -0
  461. package/dist/core/src/worker/entity-sim-worker-host.js +128 -0
  462. package/dist/core/src/worker/instrumented-worker-host.js +139 -0
  463. package/dist/core/src/worker/rpc.js +244 -0
  464. package/dist/core/src/worker/sim-worker-base.js +558 -0
  465. package/dist/core/src/worker/sim-worker-host.js +271 -0
  466. package/dist/core/src/worker/task-pool.js +205 -0
  467. package/dist/core/src/worker/task-worker.js +77 -0
  468. package/dist/libraries/asset-browser/src/index.js +10 -0
  469. package/dist/libraries/asset-browser/src/software-thumbnails.js +940 -0
  470. package/dist/libraries/audio-kira/src/backend.js +405 -0
  471. package/dist/libraries/audio-kira/src/index.js +4 -0
  472. package/dist/libraries/audio-kira/src/library.js +54 -0
  473. package/dist/libraries/blitz-ui/src/index.js +13 -0
  474. package/dist/libraries/blitz-ui/src/native-module.js +162 -0
  475. package/dist/libraries/blitz-ui/src/native-osr-ffi.js +409 -0
  476. package/dist/libraries/blitz-ui/src/router.js +82 -0
  477. package/dist/libraries/blitz-ui/src/shaders/ui-blit.wgsl.js +32 -0
  478. package/dist/libraries/blitz-ui/src/ui-blit-pass.js +108 -0
  479. package/dist/libraries/character/src/character-animator.js +323 -0
  480. package/dist/libraries/character/src/customization.js +464 -0
  481. package/dist/libraries/character/src/index.js +19 -0
  482. package/dist/libraries/character/src/inspectable.js +77 -0
  483. package/dist/libraries/character/src/loader.js +336 -0
  484. package/dist/libraries/character/src/locomotion.js +84 -0
  485. package/dist/libraries/character/src/preview.js +280 -0
  486. package/dist/libraries/devtools/src/backend.js +449 -0
  487. package/dist/libraries/devtools/src/cdp-bridge.js +293 -0
  488. package/dist/libraries/devtools/src/collectors.js +318 -0
  489. package/dist/libraries/devtools/src/index.js +31 -0
  490. package/dist/libraries/devtools/src/native-providers.js +749 -0
  491. package/dist/libraries/devtools/src/snapshot.js +35 -0
  492. package/dist/libraries/devtools/src/verify.js +139 -0
  493. package/dist/libraries/devtools/src/web/browser.js +94 -0
  494. package/dist/libraries/devtools/src/web/host.js +183 -0
  495. package/dist/libraries/devtools/src/web/mirror.js +26 -0
  496. package/dist/libraries/devtools/src/web/server.js +187 -0
  497. package/dist/libraries/entities/src/index.js +3 -0
  498. package/dist/libraries/entities/src/library.js +46 -0
  499. package/dist/libraries/entities/src/model-renderer.js +1307 -0
  500. package/dist/libraries/entities/src/shaders/model.wgsl +375 -0
  501. package/dist/libraries/gamepad/src/feed-input.js +54 -0
  502. package/dist/libraries/gamepad/src/filters.js +44 -0
  503. package/dist/libraries/gamepad/src/glyphs.js +83 -0
  504. package/dist/libraries/gamepad/src/hub.js +164 -0
  505. package/dist/libraries/gamepad/src/index.js +10 -0
  506. package/dist/libraries/gamepad/src/library.js +56 -0
  507. package/dist/libraries/gamepad/src/source-sab.js +62 -0
  508. package/dist/libraries/gamepad/src/sysfs-enrich.js +125 -0
  509. package/dist/libraries/gaussian-splats/src/gpu-sort.js +506 -0
  510. package/dist/libraries/gaussian-splats/src/index.js +8 -0
  511. package/dist/libraries/gaussian-splats/src/library.js +44 -0
  512. package/dist/libraries/gaussian-splats/src/parser.js +297 -0
  513. package/dist/libraries/gaussian-splats/src/renderer.js +368 -0
  514. package/dist/libraries/gaussian-splats/src/sh-eval.js +196 -0
  515. package/dist/libraries/gaussian-splats/src/sorter.js +76 -0
  516. package/dist/libraries/gaussian-splats/src/tile-raster.js +424 -0
  517. package/dist/libraries/gpu-kernels/src/index.js +8 -0
  518. package/dist/libraries/gpu-kernels/src/kernel.js +591 -0
  519. package/dist/libraries/gpu-kernels/src/transpile.js +896 -0
  520. package/dist/libraries/html-ui-kit/src/behaviors.js +231 -0
  521. package/dist/libraries/html-ui-kit/src/components.js +219 -0
  522. package/dist/libraries/html-ui-kit/src/index.js +17 -0
  523. package/dist/libraries/html-ui-kit/src/nav/nav-controller.js +215 -0
  524. package/dist/libraries/html-ui-kit/src/nav/nav-input.js +138 -0
  525. package/dist/libraries/html-ui-kit/src/nav/osk.js +135 -0
  526. package/dist/libraries/html-ui-kit/src/nav/router.js +152 -0
  527. package/dist/libraries/html-ui-kit/src/nav/vcursor.js +177 -0
  528. package/dist/libraries/html-ui-kit/src/ten-foot.js +138 -0
  529. package/dist/libraries/html-ui-kit/src/theme.js +235 -0
  530. package/dist/libraries/inspectable/src/index.js +6 -0
  531. package/dist/libraries/inspectable/src/inspectable.js +205 -0
  532. package/dist/libraries/lighting/src/index.js +4 -0
  533. package/dist/libraries/lighting/src/library.js +48 -0
  534. package/dist/libraries/lighting/src/light-system.js +395 -0
  535. package/dist/libraries/lighting/src/lighting-system.js +57 -0
  536. package/dist/libraries/lighting/src/shaders/light-debug.wgsl +30 -0
  537. package/dist/libraries/marching-cubes/src/chunked-field.js +130 -0
  538. package/dist/libraries/marching-cubes/src/deformation.js +41 -0
  539. package/dist/libraries/marching-cubes/src/generator.js +356 -0
  540. package/dist/libraries/marching-cubes/src/index.js +13 -0
  541. package/dist/libraries/marching-cubes/src/library.js +54 -0
  542. package/dist/libraries/marching-cubes/src/lod.js +95 -0
  543. package/dist/libraries/marching-cubes/src/marching-tetrahedra.js +261 -0
  544. package/dist/libraries/marching-cubes/src/sab.js +40 -0
  545. package/dist/libraries/marching-cubes/src/streaming-config.js +28 -0
  546. package/dist/libraries/marching-cubes/src/streaming-manager.js +490 -0
  547. package/dist/libraries/marching-cubes/src/tables.js +314 -0
  548. package/dist/libraries/marching-cubes/src/types.js +1 -0
  549. package/dist/libraries/models/src/bake-node-transforms.js +146 -0
  550. package/dist/libraries/models/src/bind-unskinned-meshes.js +145 -0
  551. package/dist/libraries/models/src/codecs/basisu-codec.js +134 -0
  552. package/dist/libraries/models/src/codecs/draco-codec.js +236 -0
  553. package/dist/libraries/models/src/codecs/draco3dgltf.d.ts +40 -0
  554. package/dist/libraries/models/src/codecs/index.js +5 -0
  555. package/dist/libraries/models/src/codecs/meshopt-codec.js +59 -0
  556. package/dist/libraries/models/src/codecs/registry.js +111 -0
  557. package/dist/libraries/models/src/dae.js +665 -0
  558. package/dist/libraries/models/src/default-part-selection.js +58 -0
  559. package/dist/libraries/models/src/dxf.js +235 -0
  560. package/dist/libraries/models/src/fbx/index.js +438 -0
  561. package/dist/libraries/models/src/fbx/interpreter/animation.js +369 -0
  562. package/dist/libraries/models/src/fbx/interpreter/blend-shapes.js +283 -0
  563. package/dist/libraries/models/src/fbx/interpreter/connections.js +158 -0
  564. package/dist/libraries/models/src/fbx/interpreter/diagnostics.js +48 -0
  565. package/dist/libraries/models/src/fbx/interpreter/geometry.js +430 -0
  566. package/dist/libraries/models/src/fbx/interpreter/global-settings.js +77 -0
  567. package/dist/libraries/models/src/fbx/interpreter/materials.js +231 -0
  568. package/dist/libraries/models/src/fbx/interpreter/nodes.js +168 -0
  569. package/dist/libraries/models/src/fbx/interpreter/skeleton.js +454 -0
  570. package/dist/libraries/models/src/fbx/parsers/binary-parser.js +217 -0
  571. package/dist/libraries/models/src/fbx/types.js +88 -0
  572. package/dist/libraries/models/src/gltf-extensions.js +121 -0
  573. package/dist/libraries/models/src/gltf.js +724 -0
  574. package/dist/libraries/models/src/index.js +46 -0
  575. package/dist/libraries/models/src/library.js +44 -0
  576. package/dist/libraries/models/src/loader.js +218 -0
  577. package/dist/libraries/models/src/material-adapter.js +82 -0
  578. package/dist/libraries/models/src/mini-xml.js +145 -0
  579. package/dist/libraries/models/src/normalize.js +168 -0
  580. package/dist/libraries/models/src/obj.js +247 -0
  581. package/dist/libraries/models/src/off.js +94 -0
  582. package/dist/libraries/models/src/ply.js +329 -0
  583. package/dist/libraries/models/src/pose-sampler.js +183 -0
  584. package/dist/libraries/models/src/sidecar/blender-extras.js +32 -0
  585. package/dist/libraries/models/src/sidecar/ddmeta.js +98 -0
  586. package/dist/libraries/models/src/sidecar/godot-import.js +76 -0
  587. package/dist/libraries/models/src/sidecar/resolver.js +112 -0
  588. package/dist/libraries/models/src/sidecar/types.js +8 -0
  589. package/dist/libraries/models/src/sidecar/unity-meta.js +46 -0
  590. package/dist/libraries/models/src/skeleton-synthesis.js +122 -0
  591. package/dist/libraries/models/src/stl.js +129 -0
  592. package/dist/libraries/models/src/threeds.js +312 -0
  593. package/dist/libraries/models/src/threemf.js +203 -0
  594. package/dist/libraries/models/src/types.js +33 -0
  595. package/dist/libraries/models/src/vtk.js +242 -0
  596. package/dist/libraries/navmesh/src/crowd-system.js +207 -0
  597. package/dist/libraries/navmesh/src/debug-viz.js +52 -0
  598. package/dist/libraries/navmesh/src/index.js +7 -0
  599. package/dist/libraries/navmesh/src/library.js +47 -0
  600. package/dist/libraries/navmesh/src/navmesh-generator.js +364 -0
  601. package/dist/libraries/navmesh/src/navmesh.js +141 -0
  602. package/dist/libraries/navmesh/src/pathfinder.js +221 -0
  603. package/dist/libraries/navmesh/src/types.js +1 -0
  604. package/dist/libraries/networking/src/authority.js +107 -0
  605. package/dist/libraries/networking/src/connection.js +107 -0
  606. package/dist/libraries/networking/src/discovery.js +314 -0
  607. package/dist/libraries/networking/src/enhanced-replication.js +282 -0
  608. package/dist/libraries/networking/src/epic-adapter.js +101 -0
  609. package/dist/libraries/networking/src/index.js +16 -0
  610. package/dist/libraries/networking/src/library.js +45 -0
  611. package/dist/libraries/networking/src/lobby.js +84 -0
  612. package/dist/libraries/networking/src/platform-adapter.js +92 -0
  613. package/dist/libraries/networking/src/rcs-adapter.js +100 -0
  614. package/dist/libraries/networking/src/remote-input.js +162 -0
  615. package/dist/libraries/networking/src/replication.js +273 -0
  616. package/dist/libraries/networking/src/rpc.js +172 -0
  617. package/dist/libraries/networking/src/session.js +129 -0
  618. package/dist/libraries/networking/src/transport.js +156 -0
  619. package/dist/libraries/networking/src/webrtc.js +266 -0
  620. package/dist/libraries/pathfinding-2d/src/astar-grid.js +255 -0
  621. package/dist/libraries/pathfinding-2d/src/index.js +9 -0
  622. package/dist/libraries/persistence/src/autosave-manager.js +94 -0
  623. package/dist/libraries/persistence/src/binary-record-store.js +205 -0
  624. package/dist/libraries/persistence/src/browser.js +16 -0
  625. package/dist/libraries/persistence/src/file-save-store.js +507 -0
  626. package/dist/libraries/persistence/src/hash-utils.js +54 -0
  627. package/dist/libraries/persistence/src/index.js +17 -0
  628. package/dist/libraries/persistence/src/library.js +51 -0
  629. package/dist/libraries/persistence/src/mock-opfs.js +114 -0
  630. package/dist/libraries/persistence/src/node-fs-directory-handle.js +168 -0
  631. package/dist/libraries/persistence/src/opfs-save-store.js +584 -0
  632. package/dist/libraries/persistence/src/save-worker-proxy.js +96 -0
  633. package/dist/libraries/persistence/src/save-worker.js +76 -0
  634. package/dist/libraries/persistence/src/xxh3-ts.d.ts +10 -0
  635. package/dist/libraries/physics-native/src/backend.js +960 -0
  636. package/dist/libraries/physics-native/src/broadphase.js +79 -0
  637. package/dist/libraries/physics-native/src/index.js +6 -0
  638. package/dist/libraries/physics-native/src/library.js +57 -0
  639. package/dist/libraries/physics-native/src/narrowphase-shapes.js +348 -0
  640. package/dist/libraries/physics-native/src/narrowphase.js +60 -0
  641. package/dist/libraries/physics-native/src/solver.js +105 -0
  642. package/dist/libraries/physics-native/src/types.js +4 -0
  643. package/dist/libraries/physics-rapier/src/api.js +352 -0
  644. package/dist/libraries/physics-rapier/src/auto-backend.js +54 -0
  645. package/dist/libraries/physics-rapier/src/backend.js +1066 -0
  646. package/dist/libraries/physics-rapier/src/bulk-ops.js +46 -0
  647. package/dist/libraries/physics-rapier/src/ffi-backend.js +17 -0
  648. package/dist/libraries/physics-rapier/src/ffi-lib.js +605 -0
  649. package/dist/libraries/physics-rapier/src/index.js +9 -0
  650. package/dist/libraries/physics-rapier/src/library.js +71 -0
  651. package/dist/libraries/physics-rapier/src/rapier-backend.js +1102 -0
  652. package/dist/libraries/physics-rapier/src/realm-worker-script.js +233 -0
  653. package/dist/libraries/postfx/src/index.js +14 -0
  654. package/dist/libraries/postfx/src/library.js +207 -0
  655. package/dist/libraries/postfx/src/post-process-stack.js +1641 -0
  656. package/dist/libraries/postfx/src/shaders/post-process/afterimage.wgsl +14 -0
  657. package/dist/libraries/postfx/src/shaders/post-process/ascii.wgsl +24 -0
  658. package/dist/libraries/postfx/src/shaders/post-process/blit.wgsl +12 -0
  659. package/dist/libraries/postfx/src/shaders/post-process/bloom-blur.wgsl +21 -0
  660. package/dist/libraries/postfx/src/shaders/post-process/bloom-bright.wgsl +15 -0
  661. package/dist/libraries/postfx/src/shaders/post-process/bloom-composite.wgsl +14 -0
  662. package/dist/libraries/postfx/src/shaders/post-process/bloom-downsample.wgsl +60 -0
  663. package/dist/libraries/postfx/src/shaders/post-process/bloom-soft.wgsl +46 -0
  664. package/dist/libraries/postfx/src/shaders/post-process/bloom-upsample.wgsl +51 -0
  665. package/dist/libraries/postfx/src/shaders/post-process/channel-mixer.wgsl +36 -0
  666. package/dist/libraries/postfx/src/shaders/post-process/chromatic-aberration.wgsl +37 -0
  667. package/dist/libraries/postfx/src/shaders/post-process/dithering.wgsl +64 -0
  668. package/dist/libraries/postfx/src/shaders/post-process/dof.wgsl +131 -0
  669. package/dist/libraries/postfx/src/shaders/post-process/edges.wgsl +45 -0
  670. package/dist/libraries/postfx/src/shaders/post-process/fullscreen-vs.wgsl +15 -0
  671. package/dist/libraries/postfx/src/shaders/post-process/fxaa.wgsl +102 -0
  672. package/dist/libraries/postfx/src/shaders/post-process/gaussian-blur.wgsl +37 -0
  673. package/dist/libraries/postfx/src/shaders/post-process/glow-blur.wgsl +33 -0
  674. package/dist/libraries/postfx/src/shaders/post-process/glow-composite.wgsl +25 -0
  675. package/dist/libraries/postfx/src/shaders/post-process/grain.wgsl +37 -0
  676. package/dist/libraries/postfx/src/shaders/post-process/halftone.wgsl +80 -0
  677. package/dist/libraries/postfx/src/shaders/post-process/highlight-blur.wgsl +33 -0
  678. package/dist/libraries/postfx/src/shaders/post-process/highlight-composite.wgsl +32 -0
  679. package/dist/libraries/postfx/src/shaders/post-process/lens-distortion.wgsl +43 -0
  680. package/dist/libraries/postfx/src/shaders/post-process/lens-flare.wgsl +68 -0
  681. package/dist/libraries/postfx/src/shaders/post-process/lut.wgsl +30 -0
  682. package/dist/libraries/postfx/src/shaders/post-process/motion-blur.wgsl +55 -0
  683. package/dist/libraries/postfx/src/shaders/post-process/occluder-chunk.wgsl +28 -0
  684. package/dist/libraries/postfx/src/shaders/post-process/outline.wgsl +51 -0
  685. package/dist/libraries/postfx/src/shaders/post-process/pixelation.wgsl +47 -0
  686. package/dist/libraries/postfx/src/shaders/post-process/sharpen.wgsl +32 -0
  687. package/dist/libraries/postfx/src/shaders/post-process/sobel.wgsl +26 -0
  688. package/dist/libraries/postfx/src/shaders/post-process/split-tone.wgsl +36 -0
  689. package/dist/libraries/postfx/src/shaders/post-process/ssao-blur.wgsl +38 -0
  690. package/dist/libraries/postfx/src/shaders/post-process/ssao-composite.wgsl +25 -0
  691. package/dist/libraries/postfx/src/shaders/post-process/ssao.wgsl +147 -0
  692. package/dist/libraries/postfx/src/shaders/post-process/ssr.wgsl +155 -0
  693. package/dist/libraries/postfx/src/shaders/post-process/taa.wgsl +98 -0
  694. package/dist/libraries/postfx/src/shaders/post-process/tonemap.wgsl +40 -0
  695. package/dist/libraries/postfx/src/shaders/post-process/watercolor.wgsl +82 -0
  696. package/dist/libraries/postfx/src/shaders/post-process/white-balance.wgsl +41 -0
  697. package/dist/libraries/recast/src/backend.js +124 -0
  698. package/dist/libraries/recast/src/crowd-system.js +310 -0
  699. package/dist/libraries/recast/src/index.js +4 -0
  700. package/dist/libraries/recast/src/library.js +59 -0
  701. package/dist/libraries/recast/src/types.js +4 -0
  702. package/dist/libraries/sand/src/cell.js +32 -0
  703. package/dist/libraries/sand/src/fields.js +27 -0
  704. package/dist/libraries/sand/src/fluid-grid.js +267 -0
  705. package/dist/libraries/sand/src/grid-dims.js +47 -0
  706. package/dist/libraries/sand/src/grid-sim-buffer.js +184 -0
  707. package/dist/libraries/sand/src/index.js +20 -0
  708. package/dist/libraries/sand/src/library.js +67 -0
  709. package/dist/libraries/sand/src/materials.js +437 -0
  710. package/dist/libraries/sand/src/palette.js +87 -0
  711. package/dist/libraries/sand/src/particles.js +163 -0
  712. package/dist/libraries/sand/src/render/sand-grid-pass.js +377 -0
  713. package/dist/libraries/sand/src/rng.js +44 -0
  714. package/dist/libraries/sand/src/rules/builtin-rules.js +125 -0
  715. package/dist/libraries/sand/src/rules/rule-compiler.js +164 -0
  716. package/dist/libraries/sand/src/rules/rule-engine.js +210 -0
  717. package/dist/libraries/sand/src/rules/rule-types.js +27 -0
  718. package/dist/libraries/sand/src/sand-step-pool.js +458 -0
  719. package/dist/libraries/sand/src/sand-step-worker.js +101 -0
  720. package/dist/libraries/sand/src/sand-world.js +3382 -0
  721. package/dist/libraries/stickman/src/index.js +7 -0
  722. package/dist/libraries/stickman/src/library.js +44 -0
  723. package/dist/libraries/stickman/src/proportions.js +40 -0
  724. package/dist/libraries/stickman/src/shader.js +113 -0
  725. package/dist/libraries/stickman/src/skeleton.js +163 -0
  726. package/dist/libraries/stickman/src/stickman-pass.js +210 -0
  727. package/dist/libraries/stickman/src/thick-line.js +120 -0
  728. package/dist/libraries/surface-nets/src/chunked-field.js +5 -0
  729. package/dist/libraries/surface-nets/src/deformation.js +29 -0
  730. package/dist/libraries/surface-nets/src/index.js +15 -0
  731. package/dist/libraries/surface-nets/src/library.js +41 -0
  732. package/dist/libraries/surface-nets/src/lod.js +6 -0
  733. package/dist/libraries/surface-nets/src/sab.js +4 -0
  734. package/dist/libraries/surface-nets/src/streaming-config.js +4 -0
  735. package/dist/libraries/surface-nets/src/streaming-manager.js +9 -0
  736. package/dist/libraries/surface-nets/src/surface-nets.js +361 -0
  737. package/dist/libraries/surface-nets/src/types.js +1 -0
  738. package/dist/libraries/water/src/buoyancy.js +80 -0
  739. package/dist/libraries/water/src/index.js +12 -0
  740. package/dist/libraries/water/src/library.js +65 -0
  741. package/dist/libraries/water/src/shore-damping.js +70 -0
  742. package/dist/libraries/water/src/water-buffer.js +78 -0
  743. package/dist/libraries/water/src/water-chunks.js +5 -0
  744. package/dist/libraries/water/src/water-physics.js +315 -0
  745. package/dist/libraries/water/src/water-renderer.js +736 -0
  746. package/dist/libraries/water/src/water-sab.js +138 -0
  747. package/dist/libraries/water/src/wave-sources.js +45 -0
  748. package/dist/libraries/weather/src/index.js +5 -0
  749. package/dist/libraries/weather/src/library.js +48 -0
  750. package/dist/libraries/weather/src/types.js +29 -0
  751. package/dist/libraries/weather/src/weather-blend.js +108 -0
  752. package/dist/libraries/weather/src/weather-system.js +275 -0
  753. package/dist/libraries/weatherfx/src/cloud-provider.js +5 -0
  754. package/dist/libraries/weatherfx/src/cloud-system.js +294 -0
  755. package/dist/libraries/weatherfx/src/index.js +4 -0
  756. package/dist/libraries/weatherfx/src/library.js +41 -0
  757. package/dist/libraries/weatherfx/src/particle-system.js +350 -0
  758. package/dist/libraries/weatherfx/src/shaders/cloud.wgsl +111 -0
  759. package/dist/libraries/weatherfx/src/shaders/particle-compute.wgsl +187 -0
  760. package/dist/libraries/weatherfx/src/shaders/particle-render.wgsl +95 -0
  761. package/dist/mcp/src/client.js +669 -0
  762. package/dist/mcp/src/engine-context.js +99 -0
  763. package/dist/mcp/src/http-transport.js +423 -0
  764. package/dist/mcp/src/index.js +5 -0
  765. package/dist/mcp/src/prompts/add-entity.js +39 -0
  766. package/dist/mcp/src/prompts/create-scene.js +41 -0
  767. package/dist/mcp/src/prompts/debug-frame.js +36 -0
  768. package/dist/mcp/src/prompts/index.js +10 -0
  769. package/dist/mcp/src/resources/asset-list.js +28 -0
  770. package/dist/mcp/src/resources/checkpoint-list.js +29 -0
  771. package/dist/mcp/src/resources/entity-state.js +45 -0
  772. package/dist/mcp/src/resources/gpu-info.js +90 -0
  773. package/dist/mcp/src/resources/index.js +51 -0
  774. package/dist/mcp/src/resources/performance.js +33 -0
  775. package/dist/mcp/src/resources/scene-tree.js +37 -0
  776. package/dist/mcp/src/server.js +307 -0
  777. package/dist/mcp/src/tools/animation.js +102 -0
  778. package/dist/mcp/src/tools/asset.js +146 -0
  779. package/dist/mcp/src/tools/audio.js +80 -0
  780. package/dist/mcp/src/tools/build.js +128 -0
  781. package/dist/mcp/src/tools/camera.js +157 -0
  782. package/dist/mcp/src/tools/checkpoint.js +90 -0
  783. package/dist/mcp/src/tools/component.js +176 -0
  784. package/dist/mcp/src/tools/debug.js +273 -0
  785. package/dist/mcp/src/tools/entity.js +309 -0
  786. package/dist/mcp/src/tools/inspect.js +192 -0
  787. package/dist/mcp/src/tools/lighting.js +239 -0
  788. package/dist/mcp/src/tools/material.js +225 -0
  789. package/dist/mcp/src/tools/mesh.js +210 -0
  790. package/dist/mcp/src/tools/physics.js +251 -0
  791. package/dist/mcp/src/tools/scene.js +139 -0
  792. package/dist/mcp/src/tools/script.js +114 -0
  793. package/dist/mcp/src/types.js +9 -0
  794. package/dist/mcp/src/undo-redo.js +64 -0
  795. package/dist/modules/camera-controls/src/index.js +116 -0
  796. package/dist/modules/controller-ui/src/index.js +149 -0
  797. package/dist/modules/devtools/src/api.js +317 -0
  798. package/dist/modules/devtools/src/asset-utils.js +102 -0
  799. package/dist/modules/devtools/src/bind-debug-store.js +34 -0
  800. package/dist/modules/devtools/src/blitz/host.js +391 -0
  801. package/dist/modules/devtools/src/blitz/module.js +65 -0
  802. package/dist/modules/devtools/src/blitz/panels/console.js +217 -0
  803. package/dist/modules/devtools/src/blitz/panels/elements.js +79 -0
  804. package/dist/modules/devtools/src/blitz/panels/gpu.js +61 -0
  805. package/dist/modules/devtools/src/blitz/panels/performance.js +113 -0
  806. package/dist/modules/devtools/src/blitz/panels/snapshot.js +141 -0
  807. package/dist/modules/devtools/src/blitz/panels/types.js +55 -0
  808. package/dist/modules/devtools/src/blitz/theme.js +167 -0
  809. package/dist/modules/devtools/src/data-bridge.js +247 -0
  810. package/dist/modules/devtools/src/debug-overlay.js +181 -0
  811. package/dist/modules/devtools/src/debug-raycast.js +296 -0
  812. package/dist/modules/devtools/src/debug-store.js +28 -0
  813. package/dist/modules/devtools/src/debug-view-descriptors.js +24 -0
  814. package/dist/modules/devtools/src/doctor-panel.js +163 -0
  815. package/dist/modules/devtools/src/gizmo-module.js +95 -0
  816. package/dist/modules/devtools/src/graph-model.js +387 -0
  817. package/dist/modules/devtools/src/grid-renderer.js +145 -0
  818. package/dist/modules/devtools/src/height-ruler-renderer.js +189 -0
  819. package/dist/modules/devtools/src/index.js +46 -0
  820. package/dist/modules/devtools/src/init.js +204 -0
  821. package/dist/modules/devtools/src/label-overlay.js +129 -0
  822. package/dist/modules/devtools/src/material-stats-panel.js +171 -0
  823. package/dist/modules/devtools/src/profiling-bridge.js +288 -0
  824. package/dist/modules/devtools/src/profiling-hooks.js +63 -0
  825. package/dist/modules/devtools/src/renderer-adapter.js +61 -0
  826. package/dist/modules/devtools/src/scene-inspector.js +571 -0
  827. package/dist/modules/devtools/src/scene-store.js +212 -0
  828. package/dist/modules/devtools/src/scene-sync.js +92 -0
  829. package/dist/modules/devtools/src/shaders/transform-gizmo.wgsl +38 -0
  830. package/dist/modules/devtools/src/sim-stats-panel.js +250 -0
  831. package/dist/modules/devtools/src/sim-stats-provider.js +73 -0
  832. package/dist/modules/devtools/src/skeleton-renderer.js +326 -0
  833. package/dist/modules/devtools/src/transform-gizmo.js +677 -0
  834. package/dist/modules/devtools/src/types.js +5 -0
  835. package/dist/modules/devtools/src/worker-expose.js +59 -0
  836. package/dist/modules/devtools/src/worker-sync.js +115 -0
  837. package/dist/modules/editor/src/commands/component.js +151 -0
  838. package/dist/modules/editor/src/commands/entity.js +253 -0
  839. package/dist/modules/editor/src/commands/hierarchy.js +79 -0
  840. package/dist/modules/editor/src/commands/index.js +57 -0
  841. package/dist/modules/editor/src/commands/prefab.js +149 -0
  842. package/dist/modules/editor/src/commands/registry.js +246 -0
  843. package/dist/modules/editor/src/commands/scene-io.js +206 -0
  844. package/dist/modules/editor/src/commands/selection.js +71 -0
  845. package/dist/modules/editor/src/commands/transform.js +88 -0
  846. package/dist/modules/editor/src/ddscene.js +189 -0
  847. package/dist/modules/editor/src/document.js +96 -0
  848. package/dist/modules/editor/src/editor-context.js +115 -0
  849. package/dist/modules/editor/src/index.js +11 -0
  850. package/dist/modules/editor/src/mcp.js +91 -0
  851. package/dist/modules/editor/src/module.js +115 -0
  852. package/dist/modules/editor/src/selection.js +60 -0
  853. package/dist/modules/editor/src/shell.js +397 -0
  854. package/dist/modules/editor/src/viewport.js +186 -0
  855. package/dist/modules/html-ui/src/composite.js +116 -0
  856. package/dist/modules/html-ui/src/create-html-ui.js +137 -0
  857. package/dist/modules/html-ui/src/doc-backend.js +518 -0
  858. package/dist/modules/html-ui/src/host.js +819 -0
  859. package/dist/modules/html-ui/src/index.js +5 -0
  860. package/dist/modules/html-ui/src/jsx-dev-runtime.js +9 -0
  861. package/dist/modules/html-ui/src/jsx-runtime.js +121 -0
  862. package/dist/modules/html-ui/src/protocol.js +6 -0
  863. package/dist/modules/html-ui/src/ui-worker.js +10 -0
  864. package/dist/modules/mcp/src/index.js +62 -0
  865. package/dist/modules/movement-2d/src/grid-character.js +345 -0
  866. package/dist/modules/movement-2d/src/index.js +27 -0
  867. package/dist/modules/movement-3d/src/character-motor.js +166 -0
  868. package/dist/modules/movement-3d/src/index.js +27 -0
  869. package/dist/modules/native-osr/src/index.js +12 -0
  870. package/dist/modules/native-osr/src/input-router.js +335 -0
  871. package/dist/modules/native-osr/src/native-osr-manager.js +210 -0
  872. package/dist/modules/native-osr/src/native-texture-source.js +66 -0
  873. package/dist/modules/native-osr/src/types.js +8 -0
  874. package/dist/modules/native-osr/src/world-space-ui-pass.js +313 -0
  875. package/dist/modules/sailing/src/index.js +39 -0
  876. package/dist/modules/terrain/src/index.js +44 -0
  877. package/dist/modules/vitals/src/index.js +25 -0
  878. package/dist/modules/vitals/src/vitals.js +195 -0
  879. package/dist/modules/xr/src/camera-rig.js +119 -0
  880. package/dist/modules/xr/src/debug.js +45 -0
  881. package/dist/modules/xr/src/frame-loop.js +139 -0
  882. package/dist/modules/xr/src/index.js +10 -0
  883. package/dist/modules/xr/src/input.js +164 -0
  884. package/dist/modules/xr/src/layer.js +100 -0
  885. package/dist/modules/xr/src/session.js +133 -0
  886. package/dist/modules/xr/src/sim-module.js +21 -0
  887. package/dist/modules/xr/src/types.js +4 -0
  888. package/dist/modules/xr/src/webxr.d.ts +182 -0
  889. package/dist/modules/xr/src/xr-module.js +134 -0
  890. package/dist/shader-graph/src/chunks.js +340 -0
  891. package/dist/shader-graph/src/compiler.js +639 -0
  892. package/dist/shader-graph/src/compute-compiler.js +384 -0
  893. package/dist/shader-graph/src/compute-graph.js +55 -0
  894. package/dist/shader-graph/src/compute-profiles.js +39 -0
  895. package/dist/shader-graph/src/graph.js +38 -0
  896. package/dist/shader-graph/src/index.js +15 -0
  897. package/dist/shader-graph/src/profiles.js +305 -0
  898. package/dist/shader-graph/src/validator.js +42 -0
  899. package/dist/shader-graph/src/wgsl-binding-validator.js +110 -0
  900. package/dist/shader-graph/src/wgsl-struct-validator.js +222 -0
  901. package/dist/shader-graph/src/wgsl-struct.js +251 -0
  902. package/dist/test/src/index.js +1 -0
  903. package/dist/test/src/vision-test.js +228 -0
  904. package/libraries/asset-browser/src/software-thumbnails.ts +2 -2
  905. package/libraries/audio-kira/src/backend.ts +2 -1
  906. package/libraries/blitz-ui/native/src/shell.rs +35 -1
  907. package/libraries/blitz-ui/native-osr/Cargo.toml +8 -0
  908. package/libraries/blitz-ui/native-osr/src/lib.rs +213 -22
  909. package/libraries/blitz-ui/native-osr/src/mutate.rs +109 -14
  910. package/libraries/blitz-ui/src/native-osr-ffi.ts +71 -8
  911. package/libraries/blitz-ui/src/router.ts +3 -1
  912. package/libraries/blitz-ui/src/ui-blit-pass.ts +1 -1
  913. package/libraries/character/src/character-animator.ts +1 -1
  914. package/libraries/character/src/customization.ts +513 -0
  915. package/libraries/character/src/index.ts +6 -0
  916. package/libraries/character/src/inspectable.ts +111 -0
  917. package/libraries/character/src/loader.ts +38 -13
  918. package/libraries/character/src/locomotion.ts +13 -1
  919. package/libraries/character/src/preview.ts +94 -24
  920. package/libraries/devtools/README.md +16 -18
  921. package/libraries/devtools/src/backend.ts +505 -0
  922. package/libraries/devtools/src/cdp-bridge.ts +8 -8
  923. package/libraries/devtools/src/collectors.ts +41 -37
  924. package/libraries/devtools/src/index.ts +32 -14
  925. package/libraries/devtools/src/native-providers.ts +20 -12
  926. package/libraries/devtools/src/snapshot.ts +77 -0
  927. package/libraries/devtools/src/web/host.ts +11 -12
  928. package/libraries/devtools/src/web/mirror.ts +14 -405
  929. package/libraries/devtools/src/web/server.ts +4 -3
  930. package/libraries/entities/src/model-renderer.ts +96 -23
  931. package/libraries/gamepad/src/library.ts +2 -1
  932. package/libraries/inspectable/src/index.ts +11 -0
  933. package/libraries/inspectable/src/inspectable.ts +277 -0
  934. package/libraries/marching-cubes/src/streaming-manager.ts +4 -4
  935. package/libraries/models/src/bind-unskinned-meshes.ts +131 -0
  936. package/libraries/models/src/index.ts +1 -0
  937. package/libraries/models/src/types.ts +22 -0
  938. package/libraries/persistence/src/autosave-manager.ts +1 -1
  939. package/libraries/persistence/src/binary-record-store.ts +1 -1
  940. package/libraries/persistence/src/file-save-store.ts +4 -4
  941. package/libraries/persistence/src/library.ts +1 -1
  942. package/libraries/persistence/src/opfs-save-store.ts +5 -5
  943. package/libraries/persistence/src/save-worker.ts +13 -14
  944. package/libraries/physics-rapier/src/ffi-lib.ts +2 -1
  945. package/libraries/postfx/src/post-process-stack.ts +1 -1
  946. package/libraries/sand/src/sand-step-pool.ts +5 -0
  947. package/libraries/water/src/water-renderer.ts +1 -1
  948. package/libraries/weatherfx/src/cloud-system.ts +3 -3
  949. package/mcp/README.md +20 -0
  950. package/mcp/src/client.ts +75 -22
  951. package/mcp/src/undo-redo.ts +2 -2
  952. package/modules/devtools/src/blitz/host.ts +430 -0
  953. package/modules/devtools/src/blitz/module.ts +101 -0
  954. package/modules/devtools/src/blitz/panels/console.ts +223 -0
  955. package/modules/devtools/src/blitz/panels/elements.ts +92 -0
  956. package/modules/devtools/src/blitz/panels/gpu.ts +70 -0
  957. package/modules/devtools/src/blitz/panels/performance.ts +120 -0
  958. package/modules/devtools/src/blitz/panels/snapshot.ts +152 -0
  959. package/modules/devtools/src/blitz/panels/types.ts +120 -0
  960. package/modules/devtools/src/blitz/theme.ts +168 -0
  961. package/modules/devtools/src/data-bridge.ts +1 -1
  962. package/modules/devtools/src/index.ts +6 -0
  963. package/modules/devtools/src/profiling-bridge.ts +17 -13
  964. package/modules/devtools/src/profiling-hooks.ts +22 -13
  965. package/modules/devtools/src/scene-inspector.ts +1 -1
  966. package/modules/devtools/src/worker-sync.ts +9 -1
  967. package/modules/editor/src/commands/registry.ts +2 -2
  968. package/modules/editor/src/module.ts +1 -1
  969. package/modules/html-ui/src/composite.ts +1 -1
  970. package/modules/html-ui/src/create-html-ui.ts +21 -9
  971. package/modules/html-ui/src/doc-backend.ts +189 -10
  972. package/modules/html-ui/src/host.ts +354 -40
  973. package/modules/html-ui/src/index.ts +1 -1
  974. package/modules/html-ui/src/jsx-runtime.ts +1 -1
  975. package/modules/html-ui/src/protocol.ts +53 -6
  976. package/modules/mcp/README.md +6 -0
  977. package/modules/mcp/src/index.ts +70 -3
  978. package/modules/movement-3d/src/character-motor.ts +83 -10
  979. package/package.json +838 -165
  980. package/shader-graph/README.md +25 -0
  981. package/test/README.md +16 -0
  982. package/libraries/blitz-ui/native-osr-spike.ts +0 -70
  983. package/libraries/devtools/native/Cargo.toml +0 -12
  984. package/libraries/devtools/native/src/lib.rs +0 -1646
  985. package/libraries/devtools/native/src/panels/console.rs +0 -338
  986. package/libraries/devtools/native/src/panels/dom_tree.rs +0 -47
  987. package/libraries/devtools/native/src/panels/generic.rs +0 -317
  988. package/libraries/devtools/native/src/panels/gpu.rs +0 -107
  989. package/libraries/devtools/native/src/panels/input.rs +0 -88
  990. package/libraries/devtools/native/src/panels/mod.rs +0 -154
  991. package/libraries/devtools/native/src/panels/perf_metrics.rs +0 -91
  992. package/libraries/devtools/native/src/panels/perf_recorder.rs +0 -158
  993. package/libraries/devtools/native/src/panels/scene.rs +0 -72
  994. package/libraries/devtools/native/src/state.rs +0 -394
  995. package/libraries/devtools/src/egui-ffi.ts +0 -804
  996. package/libraries/devtools/src/egui-renderer.ts +0 -407
  997. package/libraries/devtools/src/host.ts +0 -363
  998. package/libraries/devtools/src/mirror.ts +0 -794
  999. package/libraries/models/test-fixtures/fbx/LICENSE-notice.txt +0 -24
  1000. package/libraries/models/test-fixtures/fbx/README.md +0 -46
  1001. package/libraries/models/test-fixtures/fbx/m01_cube_phong.fbx +0 -0
  1002. package/libraries/models/test-fixtures/fbx/m02_geo_ngons.fbx +0 -0
  1003. package/libraries/models/test-fixtures/fbx/m03_normals.fbx +0 -0
  1004. package/libraries/models/test-fixtures/fbx/m04_material_properties.fbx +0 -0
  1005. package/libraries/models/test-fixtures/fbx/m05_external_diffuse.png +0 -0
  1006. package/libraries/models/test-fixtures/fbx/m05_textures.fbx +0 -0
  1007. package/libraries/models/test-fixtures/fbx/m06_uv_transform.fbx +0 -0
  1008. package/libraries/models/test-fixtures/fbx/m07_multimaterial.fbx +0 -0
  1009. package/libraries/models/test-fixtures/fbx/m08_transforms.fbx +0 -0
  1010. package/libraries/models/test-fixtures/fbx/m09_skinning.fbx +0 -0
  1011. package/libraries/models/test-fixtures/fbx/m10_morph.fbx +0 -0
  1012. package/libraries/models/test-fixtures/fbx/m11_node_anim.fbx +0 -0
  1013. package/libraries/models/test-fixtures/fbx/m12_skeletal_anim.fbx +0 -0
  1014. package/libraries/models/test-fixtures/fbx/m13_morph_anim.fbx +0 -0
  1015. package/libraries/models/test-fixtures/fbx/m14_multiclip.fbx +0 -0
  1016. package/libraries/models/test-fixtures/fbx/m15_camera_lights.fbx +0 -0
  1017. package/libraries/models/test-fixtures/fbx/m16_axis_yup.fbx +0 -0
  1018. package/libraries/models/test-fixtures/fbx/m16_axis_zup.fbx +0 -0
  1019. package/libraries/models/test-fixtures/fbx/m16_units_254.fbx +0 -0
  1020. package/libraries/physics-native/src/ffi-spike-worker.ts +0 -71
  1021. package/libraries/physics-rapier/bench/ffi-bench.ts +0 -79
  1022. package/libraries/physics-rapier/bench/wasm-baseline.ts +0 -90
@@ -6,9 +6,10 @@
6
6
  // done by PanelBlitPass via the compositor object exposed by `compositor`.
7
7
  // ============================================================================
8
8
 
9
- import type { InputEventControl, RendererInputBus } from "@downdraft/engine";
10
- import { createLogger } from "@downdraft/engine";
11
9
  import type { OsrDomEvent } from "@downdraft/engine/libraries/blitz-ui/native-osr-ffi";
10
+ import type { InputEventControl, RendererInputBus } from "@downdraft/engine/module/renderer-module";
11
+ import { getHostCapabilities, getNativeHost } from "@downdraft/engine/platform/runtime";
12
+ import { createLogger } from "@downdraft/engine/util/logger";
12
13
  import { PanelBlitPass } from "./composite";
13
14
  import { createLocalBackend, createWorkerBackend, type DocBackend } from "./doc-backend";
14
15
  import type { DocInputMsg, DocMutation, NavNodeInfo, UiPointerMsg, WorkerToUi } from "./protocol";
@@ -30,6 +31,13 @@ export interface PanelSpec {
30
31
  z?: number;
31
32
  /** Supersample factor (raster size = rect * scale). Default 2 — crisper text. */
32
33
  scale?: number;
34
+ /** UI zoom — the doc is laid out at `rect/zoom` CSS px so everything renders
35
+ * `zoom`× larger on screen. `scale` stays relative to display px: pair
36
+ * `zoom` with `scale:1` for a native-res raster (hardest edges) or the
37
+ * default `scale:2` for supersampled text. Doc-space coords (events,
38
+ * getRect, navSnapshot) stay in layout CSS px — multiply by `zoom` for
39
+ * display px. Pointer input is converted automatically. Default 1. */
40
+ zoom?: number;
33
41
  /** Raster-rate cap for animating docs (0 = uncapped). Static docs repaint on demand regardless. */
34
42
  maxFps?: number;
35
43
  /** Initial markup (or `vdom` rendered beforehand by the caller). */
@@ -49,7 +57,10 @@ interface Panel {
49
57
  spec: PanelSpec;
50
58
  rect: PanelRect;
51
59
  z: number;
60
+ /** Raster px per display px (PanelSpec.scale). */
52
61
  scale: number;
62
+ /** Display px per CSS px (PanelSpec.zoom). */
63
+ zoom: number;
53
64
  /** Doc layout height when it differs from rect.h (scrollable texture). */
54
65
  docH: number | null;
55
66
  /** Texture sub-region in texel px — displayed at `rect` (GPU scroll). */
@@ -65,6 +76,23 @@ interface Panel {
65
76
  /** Bound SAB frame channel — frames arrive as headers, pixels stay shared. */
66
77
  sab: SharedArrayBuffer | null;
67
78
  sabI32: Int32Array | null;
79
+ /** Seq of the buffer state at the last SAB upload + the rect it covered.
80
+ * Dedupes poll uploads and stale "frame" messages: a message is a no-op
81
+ * when a newer-or-equal upload already covered its rect. */
82
+ lastSeq: number;
83
+ lastRect: { x: number; y: number; w: number; h: number } | null;
84
+ /** True once the worker has demonstrably written the CURRENT texture —
85
+ * set when a gpu:true frame's texPtr matches the displayed texture, and
86
+ * cleared on SAB fallback (gpuFallback bind) or a stale-target frame.
87
+ * While false the host uploads SAB frames itself — the doc's raster
88
+ * scratch SAB is always current, so fallback needs no negotiation. */
89
+ gpuBound: boolean;
90
+ /** The texPtr the worker is confirmed to be writing — keeps retired
91
+ * textures alive until the worker drops its borrow (texAck). */
92
+ boundPtr: bigint | null;
93
+ /** The texPtr of the last texBind posted — suppresses duplicate posts
94
+ * and keeps the target alive while the bind may still be in flight. */
95
+ postedBindPtr: bigint | null;
68
96
  }
69
97
 
70
98
  const UI_TRACE = typeof process !== "undefined" && !!process.env?.DD_UI_TRACE;
@@ -89,6 +117,12 @@ export interface UiPanelHandle {
89
117
  removeAttr(target: number | string, name: string): void;
90
118
  setStyle(target: number | string, prop: string, value: string): void;
91
119
  setInnerHtml(target: number | string, html: string): void;
120
+ /** Append parsed HTML as the node's last children (`innerHTML +=`) —
121
+ * existing children survive. No-op when the cdylib predates
122
+ * dd_osr_append_html — check `HtmlUiHost.docCaps.incrementalDom`. */
123
+ appendHtml(target: number | string, html: string): void;
124
+ /** Drop all but the last `keep` children of `target`. */
125
+ trimChildren(target: number | string, keep: number): void;
92
126
  /** Apply multiple DOM mutations in one backend pass — a single relayout. */
93
127
  mutate(ops: DocMutation[]): void;
94
128
  focus(target?: number | string): void;
@@ -119,6 +153,9 @@ export interface UiPanelHandle {
119
153
  focusedNode(): Promise<number>;
120
154
  /** Scroll the doc so `target` is visible. */
121
155
  scrollIntoView(target: number | string, opts?: { smooth?: boolean; vertical?: "start" | "center" | "end" | "nearest"; horizontal?: "start" | "center" | "end" | "nearest" }): void;
156
+ /** Scroll a scroll-container node to absolute offsets — reaches nested
157
+ * scrollports (scrollIntoView only moves the root viewport). */
158
+ scrollTo(target: number | string, x: number, y: number, smooth?: boolean): void;
122
159
  /** Snapshot every node matching `sel` with rect/zone/disabled/editable —
123
160
  * the nav engine's focusable enumeration. */
124
161
  navSnapshot(selector: string): Promise<NavNodeInfo[]>;
@@ -149,6 +186,9 @@ export class HtmlUiHost {
149
186
  private unsubInput: Array<() => void> = [];
150
187
  private focusedPanel: string | null = null;
151
188
  private pointerPos = { x: -1, y: -1 };
189
+ /** Doc-backend capabilities from the `ready` handshake — e.g. whether the
190
+ * loaded cdylib supports appendHtml/trimChildren. */
191
+ private caps = { incrementalDom: false };
152
192
 
153
193
  readonly blit: PanelBlitPass;
154
194
 
@@ -156,16 +196,88 @@ export class HtmlUiHost {
156
196
  private device: GPUDevice,
157
197
  format: GPUTextureFormat,
158
198
  backend?: DocBackend,
199
+ opts?: {
200
+ /** ProfilingSAB slot tag for this host's ui worker. */
201
+ profilingTag?: string;
202
+ /** Upload panels via the worker's shared-device view (native only).
203
+ * Default true; false forces the SAB upload path. */
204
+ gpuUpload?: boolean;
205
+ },
159
206
  ) {
160
207
  this.blit = new PanelBlitPass(device, format);
161
208
  this.backend = backend ?? HtmlUiHost.spawnWorker() ?? createLocalBackend();
162
209
  this.backend.onMessage((m) => this.handleMessage(m));
210
+ this.profilingTag = opts?.profilingTag ?? "ui";
211
+ this.gpuUpload = opts?.gpuUpload !== false
212
+ && !(typeof process !== "undefined" && process.env?.DOWNDRAFT_NO_UI_GPU === "1");
213
+ // The doc-backend story isn't settled while a gpu-direct upgrade is
214
+ // still possible — the gpuReady ack logs the final form at info.
215
+ const gpuDirectPossible = this.gpuUpload
216
+ && this.backend.kind === "worker"
217
+ && getHostCapabilities().supportsMultiWorkerGpu;
218
+ log[gpuDirectPossible ? "debug" : "info"]("html-ui", `doc backend: ${this.backend.kind}`);
219
+ this.attachProfiling();
220
+ this.attachGpu();
221
+ }
222
+
223
+ private profilingTag = "ui";
224
+ private profilingSent = false;
225
+
226
+ // ── GPU-direct upload ──
227
+ // The ui worker attaches to the host's shared wgpu device (one attach per
228
+ // worker, all docs share it) and borrows each panel's texture by ptr —
229
+ // uploads become the worker's queue.writeTexture calls instead of ours.
230
+ private gpuUpload = true;
231
+ private gpuAttachSent = false;
232
+ private gpuReady = false;
233
+ private gpuDetachAcked = false;
234
+ private terminating = false;
235
+ /** Textures retired while still possibly borrowed by the worker —
236
+ * destroyed on texAck or a fallback timer (whichever lands first). */
237
+ private retiredTex = new Map<bigint, { tex: GPUTexture; timer: ReturnType<typeof setTimeout> }>();
238
+
239
+ /** Hand the worker the shared-device attach payload. Retried from mount()
240
+ * — like the profiling bridge, the native host may postdate the ctor. */
241
+ private attachGpu(): void {
242
+ if (this.gpuAttachSent || !this.gpuUpload || this.backend.kind !== "worker") return;
243
+ if (!getHostCapabilities().supportsMultiWorkerGpu) return;
244
+ const payload = getNativeHost()?.gpuShare?.payload?.();
245
+ if (!payload) return;
246
+ this.gpuAttachSent = true;
247
+ this.send({
248
+ type: "gpuAttach",
249
+ gpu: payload.gpu as { devicePtr: number | bigint; instancePtr: number | bigint; queuePtr: number | bigint; generation: number },
250
+ cells: payload.cells,
251
+ });
252
+ }
253
+
254
+ /** Hand the engine ProfilingSAB to the ui worker so the devtools perf tab
255
+ * can see it. Retried from mount() — the profiling bridge is created by
256
+ * initDevTools, which may run after this host exists. */
257
+ private attachProfiling(): void {
258
+ if (this.profilingSent || this.backend.kind !== "worker") return;
259
+ const g = globalThis as Record<string, any>;
260
+ const bridge = g.window?.__sceneInspector?.__getProfilingBridge?.()
261
+ ?? g.__sceneInspector?.__getProfilingBridge?.();
262
+ const sab = bridge?.getProfilingSAB?.();
263
+ if (!sab) return;
264
+ this.profilingSent = true;
265
+ this.send({ type: "profilingAttach", sab, workerTag: this.profilingTag, layout: bridge.getLayoutParams?.() });
163
266
  }
164
267
 
165
268
  private static spawnWorker(): DocBackend | null {
166
269
  try {
167
270
  const w = new Worker(new URL("./ui-worker.ts", import.meta.url));
168
- w.addEventListener("error", (e) => log.error("html-ui", `ui-worker error: ${(e as ErrorEvent).message ?? e}`));
271
+ // Don't let a leaked doc worker pin the runtime after the window closes.
272
+ (w as any).unref?.();
273
+ w.addEventListener("error", (e) => {
274
+ // Expected terminate() during teardown fires a contentless error
275
+ // event — not a fault (see doc-backend.ts dispose).
276
+ if ((w as any).__ddExpectTerminate && !(e as ErrorEvent).message) return;
277
+ const ee = e as ErrorEvent;
278
+ const detail = ee.message ?? (ee.filename ? `${ee.filename}:${ee.lineno ?? "?"}` : `type=${e.type}`);
279
+ log.error("html-ui", `ui-worker error: ${detail}`);
280
+ });
169
281
  w.addEventListener("messageerror", (e) => log.error("html-ui", `ui-worker messageerror: ${e.data}`));
170
282
  return createWorkerBackend(w);
171
283
  } catch (err) {
@@ -177,18 +289,27 @@ export class HtmlUiHost {
177
289
  // ── Panels ──
178
290
 
179
291
  mount(spec: PanelSpec): UiPanelHandle {
292
+ this.attachProfiling(); // retry — the profiling bridge may postdate ctor
293
+ this.attachGpu(); // retry — the native host may postdate the ctor
180
294
  const id = spec.id ?? `panel-${this.nextId++}`;
181
295
  const scale = spec.scale ?? 2;
296
+ const zoom = spec.zoom && spec.zoom > 0 ? spec.zoom : 1;
182
297
  const panel: Panel = {
183
- id, spec, rect: { ...spec.rect }, z: spec.z ?? 0, scale,
298
+ id, spec, rect: { ...spec.rect }, z: spec.z ?? 0, scale, zoom,
184
299
  docH: spec.docH ?? null, src: null,
185
300
  texture: null, texW: 0, texH: 0, ubo: null, bindGroup: null,
186
301
  handlers: new Set(spec.onEvent ? [spec.onEvent] : []),
187
- editing: false, sab: null, sabI32: null,
302
+ editing: false, sab: null, sabI32: null, lastSeq: 0, lastRect: null,
303
+ gpuBound: false, boundPtr: null, postedBindPtr: null,
188
304
  };
189
305
  this.panels.set(id, panel);
190
306
  this.order.push(id);
191
- this.send({ type: "create", id, cssW: spec.rect.w, cssH: spec.docH ?? spec.rect.h, scale, html: spec.html, maxFps: spec.maxFps });
307
+ // Doc viewport scale = raster px per CSS px = scale * zoom; layout size
308
+ // is rect/zoom CSS px so the raster still covers rect*scale texture px.
309
+ this.send({ type: "create", id, cssW: spec.rect.w / zoom, cssH: spec.docH ?? spec.rect.h / zoom, scale: scale * zoom, html: spec.html, maxFps: spec.maxFps });
310
+ // GPU-direct: create the panel texture eagerly so the worker's texBind
311
+ // lands before its first upload — the host knows raster dims at mount.
312
+ if (this.gpuReady) this.bindPanelTex(panel);
192
313
  return this.handleFor(panel);
193
314
  }
194
315
 
@@ -233,6 +354,8 @@ export class HtmlUiHost {
233
354
  removeAttr: (t, name) => mutate({ op: "rattr", ...tgt(t), name }),
234
355
  setStyle: (t, prop, value) => mutate({ op: "style", ...tgt(t), prop, value }),
235
356
  setInnerHtml: (t, html) => mutate({ op: "innerHtml", ...tgt(t), html }),
357
+ appendHtml: (t, html) => mutate({ op: "appendHtml", ...tgt(t), html }),
358
+ trimChildren: (t, keep) => mutate({ op: "trimChildren", ...tgt(t), keep }),
236
359
  mutate: (ops) => {
237
360
  const out = filterOps(ops);
238
361
  if (out.length) this.send({ type: "mutate", id: p.id, ops: out });
@@ -248,12 +371,14 @@ export class HtmlUiHost {
248
371
  const r = p.rect;
249
372
  if (r.x === rect.x && r.y === rect.y && r.w === rect.w && r.h === rect.h) return;
250
373
  p.rect = { ...rect };
251
- this.send({ type: "resize", id: p.id, cssW: rect.w, cssH: p.docH ?? rect.h, scale: p.scale });
374
+ this.send({ type: "resize", id: p.id, cssW: rect.w / p.zoom, cssH: p.docH ?? rect.h / p.zoom, scale: p.scale * p.zoom });
375
+ this.bindPanelTex(p); // rebind the worker to the resized texture
252
376
  },
253
377
  setDocHeight: (h) => {
254
378
  if (p.docH === h) return;
255
379
  p.docH = h;
256
- this.send({ type: "resize", id: p.id, cssW: p.rect.w, cssH: h, scale: p.scale });
380
+ this.send({ type: "resize", id: p.id, cssW: p.rect.w / p.zoom, cssH: h, scale: p.scale * p.zoom });
381
+ this.bindPanelTex(p);
257
382
  },
258
383
  setSrcRect: (src) => { p.src = src ? { ...src } : null; },
259
384
  setZ: (z) => { p.z = z; },
@@ -286,10 +411,17 @@ export class HtmlUiHost {
286
411
  }),
287
412
  scrollIntoView: (t, opts) =>
288
413
  mutate({ op: "scrollIntoView", ...tgt(t), smooth: opts?.smooth, vertical: opts?.vertical, horizontal: opts?.horizontal }),
414
+ scrollTo: (t, x, y, smooth) =>
415
+ mutate({ op: "scrollTo", ...tgt(t), x, y, smooth }),
289
416
  click: (t) => mutate({ op: "click", ...tgt(t) }),
290
417
  sendKey: (down, key, opts) =>
291
418
  this.send({ type: "input", id: p.id, msg: { kind: "key", down, key, code: opts?.code, text: opts?.text, mods: opts?.mods } }),
292
- sendPointer: (msg) => this.input(p.id, msg),
419
+ // Callers pass panel-local display px (like real pointer events) —
420
+ // convert to doc CSS px here the same way local() does.
421
+ sendPointer: (msg) => this.input(p.id,
422
+ msg.kind === "wheel"
423
+ ? { ...msg, x: msg.x / p.zoom, y: msg.y / p.zoom, deltaX: msg.deltaX / p.zoom, deltaY: msg.deltaY / p.zoom }
424
+ : { ...msg, x: msg.x / p.zoom, y: msg.y / p.zoom }),
293
425
  navSnapshot: (sel) => new Promise((resolve) => {
294
426
  const reqId = this.nextReqId++;
295
427
  this.navReqs.set(reqId, resolve);
@@ -304,7 +436,7 @@ export class HtmlUiHost {
304
436
  if (!p) return;
305
437
  this.panels.delete(id);
306
438
  this.order = this.order.filter((x) => x !== id);
307
- p.texture?.destroy();
439
+ this.retireTexture(p);
308
440
  p.ubo?.destroy();
309
441
  p.sab = null;
310
442
  p.sabI32 = null;
@@ -326,16 +458,30 @@ export class HtmlUiHost {
326
458
  return () => { set.delete(fn); };
327
459
  }
328
460
 
329
- /** True when the pointer is inside any panel rect (UI owns the cursor). */
330
- isPointerOverUI(): boolean {
331
- return this.panelAt(this.pointerPos.x, this.pointerPos.y) !== null;
461
+ /** True when the pointer is inside any panel rect (UI owns the cursor).
462
+ * Optional coords hit-test a specific point instead of the last seen
463
+ * pointer position — the right check inside pointer-event handlers, where
464
+ * pointerPos may lag the event. */
465
+ isPointerOverUI(x?: number, y?: number): boolean {
466
+ return this.panelAt(x ?? this.pointerPos.x, y ?? this.pointerPos.y) !== null;
332
467
  }
333
468
 
469
+ /** Doc-backend capabilities (populated by the `ready` handshake —
470
+ * `incrementalDom` is false until then, and forever on old cdylibs). */
471
+ get docCaps(): { incrementalDom: boolean } { return this.caps; }
472
+
334
473
  /** Compositor surface for GameRenderer's end-of-frame UI pass. */
335
474
  get compositor(): { hasContent(): boolean; render(pass: GPURenderPassEncoder, w: number, h: number): void } {
336
475
  return {
337
- hasContent: () => [...this.panels.values()].some((p) => p.bindGroup !== null),
476
+ // Polling here (not only in render) means a freshly-bound panel's
477
+ // first SAB frame lands the same frame — hasContent is what gates the
478
+ // compositor into the UI pass.
479
+ hasContent: () => {
480
+ this.pollSabFrames();
481
+ return [...this.panels.values()].some((p) => p.bindGroup !== null);
482
+ },
338
483
  render: (pass, w, h) => {
484
+ this.pollSabFrames();
339
485
  const draw = this.sortedPanels()
340
486
  .filter((p) => p.bindGroup && p.ubo)
341
487
  .map((p) => ({
@@ -354,10 +500,30 @@ export class HtmlUiHost {
354
500
  this.unsubInput.forEach((u) => u());
355
501
  this.unsubInput = [];
356
502
  if (this.moveTimer) { clearTimeout(this.moveTimer); this.moveTimer = null; }
357
- for (const p of this.panels.values()) { p.texture?.destroy(); p.ubo?.destroy(); p.sab = null; p.sabI32 = null; }
503
+ for (const p of this.panels.values()) { this.retireTexture(p); p.ubo?.destroy(); p.sab = null; p.sabI32 = null; }
358
504
  this.panels.clear();
359
505
  this.order = [];
506
+ if (this.gpuAttachSent && this.backend.kind === "worker" && !this.gpuDetachAcked) {
507
+ // Graceful detach: let the worker drop its shared-device view before
508
+ // terminate() kills it — an un-detached view stalls the broker's
509
+ // retire() until timeout, and retired textures must outlive the
510
+ // worker's last writeTexture. Both settle on gpuDetached or 150ms.
511
+ this.terminating = true;
512
+ this.send({ type: "gpuDetach" });
513
+ const backend = this.backend;
514
+ setTimeout(() => {
515
+ if (!this.gpuDetachAcked) backend.dispose();
516
+ this.destroyRetired();
517
+ }, 150);
518
+ return;
519
+ }
360
520
  this.backend.dispose();
521
+ this.destroyRetired();
522
+ }
523
+
524
+ private destroyRetired(): void {
525
+ for (const r of this.retiredTex.values()) { clearTimeout(r.timer); r.tex.destroy(); }
526
+ this.retiredTex.clear();
361
527
  }
362
528
 
363
529
  // ── Input coalescing ──
@@ -402,7 +568,7 @@ export class HtmlUiHost {
402
568
  };
403
569
  const input = (id: string, msg: DocInputMsg) => this.input(id, msg);
404
570
  const local = (p: Panel, e: { clientX: number; clientY: number }) => ({
405
- x: e.clientX - p.rect.x, y: e.clientY - p.rect.y,
571
+ x: (e.clientX - p.rect.x) / p.zoom, y: (e.clientY - p.rect.y) / p.zoom,
406
572
  });
407
573
 
408
574
  this.unsubInput.push(
@@ -440,7 +606,7 @@ export class HtmlUiHost {
440
606
  const p = this.panelAt(e.clientX, e.clientY);
441
607
  if (!p) return;
442
608
  ctrl.stopPropagation();
443
- input(p.id, { kind: "wheel", ...local(p, e), deltaX: e.deltaX, deltaY: e.deltaY, mods: modsOf(e) });
609
+ input(p.id, { kind: "wheel", ...local(p, e), deltaX: e.deltaX / p.zoom, deltaY: e.deltaY / p.zoom, mods: modsOf(e) });
444
610
  }, -10),
445
611
  bus.onKeyDown((e: KeyboardEvent, ctrl: InputEventControl) => {
446
612
  const p = this.focusedPanel ? this.panels.get(this.focusedPanel) : null;
@@ -498,36 +664,90 @@ export class HtmlUiHost {
498
664
  if (!p) return;
499
665
  p.sab = m.buf;
500
666
  p.sabI32 = new Int32Array(m.buf);
667
+ // Fresh buffer — its seqlock restarts at 0, so reset the dedupe
668
+ // state or the stale lastSeq could suppress real uploads.
669
+ p.lastSeq = 0;
670
+ p.lastRect = null;
671
+ // gpuFallback binds mean the worker dropped GPU-direct delivery —
672
+ // resume host-side uploads. Plain binds just keep p.sab current so
673
+ // fallback is instant when needed.
674
+ if (m.gpuFallback === true) {
675
+ p.gpuBound = false;
676
+ p.boundPtr = null;
677
+ }
678
+ break;
679
+ }
680
+ case "gpuReady": {
681
+ this.gpuReady = m.ok;
682
+ log.info("html-ui", `doc backend: ${this.backend.kind}${m.ok ? " (gpu-direct)" : ""}`);
683
+ if (m.ok) {
684
+ this.panels.forEach((p) => this.bindPanelTex(p));
685
+ }
686
+ break;
687
+ }
688
+ case "gpuDetached": {
689
+ this.gpuDetachAcked = true;
690
+ if (this.terminating) {
691
+ this.backend.dispose();
692
+ this.destroyRetired();
693
+ }
694
+ break;
695
+ }
696
+ case "texAck": {
697
+ // The worker dropped its borrow of this ptr — safe to destroy the
698
+ // retired texture now (no worker FFI call can still be in flight).
699
+ const ptr = BigInt(m.texPtr);
700
+ const r = this.retiredTex.get(ptr);
701
+ if (r) {
702
+ this.retiredTex.delete(ptr);
703
+ clearTimeout(r.timer);
704
+ r.tex.destroy();
705
+ }
706
+ // Release bookkeeping — a bind for the same ptr may be reposted.
707
+ const p = this.panels.get(m.id);
708
+ if (p) {
709
+ if (p.postedBindPtr === ptr) p.postedBindPtr = null;
710
+ if (p.boundPtr === ptr) { p.boundPtr = null; p.gpuBound = false; }
711
+ }
501
712
  break;
502
713
  }
503
714
  case "frame": {
504
715
  const p = this.panels.get(m.id);
505
716
  if (process.env.DD_UI_TRACE_FRAMES === "1") {
506
- log.info("html-ui", `frame ${m.id} x=${m.x} y=${m.y} w=${m.w} h=${m.h} pw=${m.pw} ph=${m.ph} seq=${m.seq ?? "-"}`);
717
+ log.info("html-ui", `frame ${m.id} x=${m.x} y=${m.y} w=${m.w} h=${m.h} pw=${m.pw} ph=${m.ph} seq=${m.seq ?? "-"} gpu=${m.gpu === true}${m.texPtr !== undefined ? ` tex=${m.texPtr}` : ""}`);
507
718
  }
508
719
  if (!p) return;
720
+ if (m.gpu === true) {
721
+ // GPU-direct: the worker already wrote the dirty rect into a
722
+ // texture — nothing to upload when it's the displayed one. A
723
+ // mismatched texPtr means the worker is writing a stale target
724
+ // (a bind it ignored, or a texture retired underneath it): fall
725
+ // back to SAB and repost the live texture's bind to reconverge.
726
+ const cur = p.texture ? BigInt((p.texture as unknown as { ptr: number | bigint }).ptr) : null;
727
+ const fp = m.texPtr !== undefined ? BigInt(m.texPtr) : null;
728
+ if (fp === null || fp !== cur) {
729
+ if (p.gpuBound) { p.gpuBound = false; p.boundPtr = null; }
730
+ if (cur !== null && p.postedBindPtr !== cur) this.bindPanelTex(p);
731
+ break;
732
+ }
733
+ // Confirmed: the worker uploads the displayed texture itself —
734
+ // host-side SAB uploads stay skipped until the next fallback.
735
+ p.gpuBound = true;
736
+ p.boundPtr = fp;
737
+ if (p.texW !== m.pw || p.texH !== m.ph) this.bindPanelTex(p);
738
+ break;
739
+ }
509
740
  if (m.seq !== undefined && m.stride !== undefined && p.sab && p.sabI32) {
741
+ if (p.gpuBound) break; // stale seq frame — worker owns uploads now
510
742
  // Zero-copy path: the backend wrote the dirty rect into the shared
511
- // buffer — seqlock-check and upload straight from it. Use the
512
- // message's captured rect, NOT the live SAB header: a newer write
513
- // may have already overwritten the header, and re-reading it would
514
- // silently drop this emit's dirty region (ghost pixels).
515
- const i32 = p.sabI32;
516
- const seq0 = Atomics.load(i32, 0);
517
- if (seq0 === 0 || (seq0 & 1) !== 0) { this.send({ type: "refresh", id: p.id }); break; }
518
- const x = m.x, y = m.y, w = m.w, h = m.h;
519
- const pw = m.pw, ph = m.ph, stride = m.stride;
520
- if (w <= 0 || h <= 0) break;
521
- this.ensureTexture(p, pw, ph);
522
- if (!p.texture) break;
523
- this.device.queue.writeTexture(
524
- { texture: p.texture, origin: [x, y, 0] },
525
- p.sab as unknown as GPUAllowSharedBufferSource,
526
- { offset: 64 + y * stride + x * 4, bytesPerRow: stride, rowsPerImage: h },
527
- { width: w, height: h, depthOrArrayLayers: 1 },
528
- );
529
- // Torn read (a newer write started mid-upload) — ask for a re-emit.
530
- if (Atomics.load(i32, 0) !== seq0) this.send({ type: "refresh", id: p.id });
743
+ // buffer. Skip when a poll already uploaded this emit (or a newer
744
+ // frame covering its rect) — otherwise upload the message's
745
+ // captured rect: superseded header entries still carry regions the
746
+ // newest frame's rect may not cover.
747
+ const r = p.lastRect;
748
+ if (p.lastSeq >= m.seq && r &&
749
+ m.x >= r.x && m.y >= r.y && m.x + m.w <= r.x + r.w && m.y + m.h <= r.y + r.h) break;
750
+ this.uploadSabFrame(p, m.x, m.y, m.w, m.h, m.pw, m.ph, m.stride);
531
751
  break;
532
752
  }
533
753
  if (!m.pixels) break;
@@ -603,13 +823,107 @@ export class HtmlUiHost {
603
823
  break;
604
824
  }
605
825
  case "error": log.error("html-ui", `doc ${m.id} backend error: ${m.message}`); break;
606
- case "ready": break;
826
+ case "ready": {
827
+ this.caps.incrementalDom = m.caps?.incrementalDom === true;
828
+ break;
829
+ }
830
+ }
831
+ }
832
+
833
+ /** Upload one dirty rect straight out of the panel's bound SAB, seqlock
834
+ * verified. Records lastSeq/lastRect so the poll path and late "frame"
835
+ * messages don't re-upload the same content. */
836
+ private uploadSabFrame(p: Panel, x: number, y: number, w: number, h: number, pw: number, ph: number, stride: number): void {
837
+ if (p.gpuBound) return; // the worker uploads directly — don't race it
838
+ const i32 = p.sabI32!;
839
+ const seq0 = Atomics.load(i32, 0);
840
+ // seq0 === 0 → bound but nothing emitted yet; odd → write in progress.
841
+ // A frame message implies a write, so ask for a re-emit; the poll path
842
+ // skips both cases itself and just retries next frame.
843
+ if (seq0 === 0 || (seq0 & 1) !== 0) { this.send({ type: "refresh", id: p.id }); return; }
844
+ if (w <= 0 || h <= 0) return;
845
+ this.ensureTexture(p, pw, ph);
846
+ if (!p.texture) return;
847
+ this.device.queue.writeTexture(
848
+ { texture: p.texture, origin: [x, y, 0] },
849
+ p.sab as unknown as GPUAllowSharedBufferSource,
850
+ { offset: 64 + y * stride + x * 4, bytesPerRow: stride, rowsPerImage: h },
851
+ { width: w, height: h, depthOrArrayLayers: 1 },
852
+ );
853
+ // Torn read (a newer write started mid-upload) — ask for a re-emit.
854
+ if (Atomics.load(i32, 0) !== seq0) { this.send({ type: "refresh", id: p.id }); return; }
855
+ p.lastSeq = seq0;
856
+ p.lastRect = { x, y, w, h };
857
+ }
858
+
859
+ /** Poll bound SAB frame channels once per render frame and upload pending
860
+ * dirty rects directly — the worker's "frame" postMessage is delivered on
861
+ * a macrotask boundary, so waiting for it can cost a whole frame of lag
862
+ * when it lands behind a long renderFrame. The header only describes the
863
+ * newest emit; superseded dirty rects still arrive via their messages. */
864
+ private pollSabFrames(): void {
865
+ for (const p of this.panels.values()) {
866
+ const i32 = p.sabI32;
867
+ if (!i32 || !p.sab || p.gpuBound) continue;
868
+ const seq0 = Atomics.load(i32, 0);
869
+ if (seq0 === 0 || (seq0 & 1) !== 0 || seq0 === p.lastSeq) continue;
870
+ const x = i32[1], y = i32[2], w = i32[3], h = i32[4];
871
+ const pw = i32[5], ph = i32[6], stride = i32[8];
872
+ this.uploadSabFrame(p, x, y, w, h, pw, ph, stride);
873
+ }
874
+ }
875
+
876
+ /**
877
+ * Create (or recreate) the panel texture and post it to the worker as a
878
+ * borrowed upload target. No-op when the worker's attach hasn't resolved
879
+ * or a bind for the same texture is already in flight/confirmed. Host
880
+ * uploads keep flowing until a gpu:true frame proves the worker is
881
+ * writing the displayed texture — an ignored bind is a no-op, never a
882
+ * deadlock. Raster dims are always rect*scale — the doc's layout height
883
+ * may exceed the display rect for scrollable views (docH).
884
+ */
885
+ private bindPanelTex(p: Panel): void {
886
+ if (!this.gpuReady || this.backend.kind !== "worker") return;
887
+ const pw = Math.max(1, Math.round(p.rect.w * p.scale));
888
+ // docH is a layout-px override: it scales by zoom like the doc does.
889
+ const ph = Math.max(1, Math.round((p.docH !== null ? p.docH * p.zoom : p.rect.h) * p.scale));
890
+ this.ensureTexture(p, pw, ph);
891
+ if (!p.texture) return;
892
+ const ptr = BigInt((p.texture as unknown as { ptr: number | bigint }).ptr);
893
+ if (p.postedBindPtr === ptr || (p.gpuBound && p.boundPtr === ptr)) return;
894
+ this.send({ type: "texBind", id: p.id, texPtr: ptr, w: pw, h: ph, format: "rgba8unorm" });
895
+ p.postedBindPtr = ptr;
896
+ }
897
+
898
+ /**
899
+ * Release a panel's texture — deferred when the worker may still be
900
+ * writing through it. A bound texture's ptr could be mid-writeTexture on
901
+ * the worker right now; destroying the handle while an FFI call derefs it
902
+ * is a use-after-free inside the shim. Bound textures go to retiredTex
903
+ * and die on texAck (worker swapped) or a 1s fallback timer (worker gone).
904
+ */
905
+ private retireTexture(p: Panel): void {
906
+ const t = p.texture;
907
+ p.texture = null;
908
+ if (!t) return;
909
+ const ptr = (t as unknown as { ptr?: number | bigint }).ptr;
910
+ const borrowed = ptr !== undefined
911
+ && ((p.boundPtr !== null && BigInt(ptr) === p.boundPtr)
912
+ || (p.postedBindPtr !== null && BigInt(ptr) === p.postedBindPtr));
913
+ if (borrowed) {
914
+ const key = BigInt(ptr);
915
+ const timer = setTimeout(() => {
916
+ if (this.retiredTex.delete(key)) t.destroy();
917
+ }, 1000);
918
+ this.retiredTex.set(key, { tex: t, timer });
919
+ return;
607
920
  }
921
+ t.destroy();
608
922
  }
609
923
 
610
924
  private ensureTexture(p: Panel, w: number, h: number): void {
611
925
  if (p.texture && p.texW === w && p.texH === h) return;
612
- p.texture?.destroy();
926
+ this.retireTexture(p);
613
927
  const tw = Math.max(1, w), th = Math.max(1, h);
614
928
  p.texture = this.device.createTexture({
615
929
  size: { width: tw, height: th },
@@ -4,7 +4,7 @@ export type { CompositePanel } from "./composite";
4
4
  export { createHtmlUi, HtmlUiTok, isPointerOverUI } from "./create-html-ui";
5
5
  export type { HtmlUiContext, HtmlUiOptions, UISubscribable } from "./create-html-ui";
6
6
  export { createDocCore, createLocalBackend, createWorkerBackend } from "./doc-backend";
7
- export type { DocBackend } from "./doc-backend";
7
+ export type { DocBackend, DocGpuHooks, DocGpuView } from "./doc-backend";
8
8
  export { HtmlUiHost } from "./host";
9
9
  export type { PanelActionHandler, PanelEventHandler, PanelRect, PanelSpec, UiPanelHandle } from "./host";
10
10
  export { Fragment, jsx, jsxDEV, jsxs, renderHtml } from "./jsx-runtime";
@@ -13,7 +13,7 @@
13
13
  // event queue, dispatched by data-action / selector handlers.
14
14
  // ============================================================================
15
15
 
16
- import { createLogger } from "@downdraft/engine";
16
+ import { createLogger } from "@downdraft/engine/util/logger";
17
17
 
18
18
  const log = createLogger();
19
19