@fps-games/editor 0.1.6-beta.1 → 0.1.7-beta.2

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 (373) hide show
  1. package/dist/agent-bridge/capabilities/assets.d.ts +8 -0
  2. package/dist/agent-bridge/capabilities/assets.d.ts.map +1 -0
  3. package/dist/agent-bridge/capabilities/assets.js +226 -0
  4. package/dist/agent-bridge/capabilities/assets.js.map +1 -0
  5. package/dist/agent-bridge/capabilities/editor-state.d.ts +5 -0
  6. package/dist/agent-bridge/capabilities/editor-state.d.ts.map +1 -0
  7. package/dist/agent-bridge/capabilities/editor-state.js +72 -0
  8. package/dist/agent-bridge/capabilities/editor-state.js.map +1 -0
  9. package/dist/agent-bridge/capabilities/host-lifecycle.d.ts +4 -0
  10. package/dist/agent-bridge/capabilities/host-lifecycle.d.ts.map +1 -0
  11. package/dist/agent-bridge/capabilities/host-lifecycle.js +87 -0
  12. package/dist/agent-bridge/capabilities/host-lifecycle.js.map +1 -0
  13. package/dist/agent-bridge/capabilities/prefabs.d.ts +5 -0
  14. package/dist/agent-bridge/capabilities/prefabs.d.ts.map +1 -0
  15. package/dist/agent-bridge/capabilities/prefabs.js +735 -0
  16. package/dist/agent-bridge/capabilities/prefabs.js.map +1 -0
  17. package/dist/agent-bridge/capabilities/scene-objects.d.ts +9 -0
  18. package/dist/agent-bridge/capabilities/scene-objects.d.ts.map +1 -0
  19. package/dist/agent-bridge/capabilities/scene-objects.js +394 -0
  20. package/dist/agent-bridge/capabilities/scene-objects.js.map +1 -0
  21. package/dist/agent-bridge/capabilities/selection.d.ts +5 -0
  22. package/dist/agent-bridge/capabilities/selection.d.ts.map +1 -0
  23. package/dist/agent-bridge/capabilities/selection.js +57 -0
  24. package/dist/agent-bridge/capabilities/selection.js.map +1 -0
  25. package/dist/agent-bridge/capabilities/shadows.d.ts +5 -0
  26. package/dist/agent-bridge/capabilities/shadows.d.ts.map +1 -0
  27. package/dist/agent-bridge/capabilities/shadows.js +1876 -0
  28. package/dist/agent-bridge/capabilities/shadows.js.map +1 -0
  29. package/dist/agent-bridge/capabilities/transform.d.ts +5 -0
  30. package/dist/agent-bridge/capabilities/transform.d.ts.map +1 -0
  31. package/dist/agent-bridge/capabilities/transform.js +162 -0
  32. package/dist/agent-bridge/capabilities/transform.js.map +1 -0
  33. package/dist/agent-bridge/capabilities/ui-regions.d.ts +4 -0
  34. package/dist/agent-bridge/capabilities/ui-regions.d.ts.map +1 -0
  35. package/dist/agent-bridge/capabilities/ui-regions.js +168 -0
  36. package/dist/agent-bridge/capabilities/ui-regions.js.map +1 -0
  37. package/dist/agent-bridge/capabilities/viewport.d.ts +5 -0
  38. package/dist/agent-bridge/capabilities/viewport.d.ts.map +1 -0
  39. package/dist/agent-bridge/capabilities/viewport.js +407 -0
  40. package/dist/agent-bridge/capabilities/viewport.js.map +1 -0
  41. package/dist/agent-bridge/capability-sources.d.ts +6 -0
  42. package/dist/agent-bridge/capability-sources.d.ts.map +1 -0
  43. package/dist/agent-bridge/capability-sources.js +26 -0
  44. package/dist/agent-bridge/capability-sources.js.map +1 -0
  45. package/dist/agent-bridge/diagnostics.d.ts +12 -0
  46. package/dist/agent-bridge/diagnostics.d.ts.map +1 -0
  47. package/dist/agent-bridge/diagnostics.js +45 -0
  48. package/dist/agent-bridge/diagnostics.js.map +1 -0
  49. package/dist/agent-bridge/index.d.ts +5 -0
  50. package/dist/agent-bridge/index.d.ts.map +1 -0
  51. package/dist/agent-bridge/index.js +5 -0
  52. package/dist/agent-bridge/index.js.map +1 -0
  53. package/dist/agent-bridge/register.d.ts +4 -0
  54. package/dist/agent-bridge/register.d.ts.map +1 -0
  55. package/dist/agent-bridge/register.js +908 -0
  56. package/dist/agent-bridge/register.js.map +1 -0
  57. package/dist/agent-bridge/shared.d.ts +189 -0
  58. package/dist/agent-bridge/shared.d.ts.map +1 -0
  59. package/dist/agent-bridge/shared.js +39 -0
  60. package/dist/agent-bridge/shared.js.map +1 -0
  61. package/dist/agent-bridge/source-types.d.ts +90 -0
  62. package/dist/agent-bridge/source-types.d.ts.map +1 -0
  63. package/dist/agent-bridge/source-types.js +2 -0
  64. package/dist/agent-bridge/source-types.js.map +1 -0
  65. package/dist/build-info.json +17 -17
  66. package/dist/index.d.ts +1 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js.map +1 -1
  69. package/dist/local-editor-agent-bridge-transport.d.ts +95 -0
  70. package/dist/local-editor-agent-bridge-transport.d.ts.map +1 -0
  71. package/dist/local-editor-agent-bridge-transport.js +340 -0
  72. package/dist/local-editor-agent-bridge-transport.js.map +1 -0
  73. package/dist/local-editor-agent-bridge.d.ts +2 -0
  74. package/dist/local-editor-agent-bridge.d.ts.map +1 -0
  75. package/dist/local-editor-agent-bridge.js +2 -0
  76. package/dist/local-editor-agent-bridge.js.map +1 -0
  77. package/dist/local-editor-harness.d.ts +26 -2
  78. package/dist/local-editor-harness.d.ts.map +1 -1
  79. package/dist/local-editor-harness.js +773 -75
  80. package/dist/local-editor-harness.js.map +1 -1
  81. package/dist/playable-babylon-rendering.js +20 -0
  82. package/dist/playable-babylon-rendering.js.map +1 -1
  83. package/dist/playable-local-editor-host.d.ts +5 -0
  84. package/dist/playable-local-editor-host.d.ts.map +1 -1
  85. package/dist/playable-local-editor-host.js +2 -0
  86. package/dist/playable-local-editor-host.js.map +1 -1
  87. package/dist/playable-sdk.d.ts +1 -1
  88. package/dist/playable-sdk.d.ts.map +1 -1
  89. package/dist/playable-sdk.js.map +1 -1
  90. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.d.ts.map +1 -1
  91. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js +6 -4
  92. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js.map +1 -1
  93. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-shaders.d.ts.map +1 -1
  94. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-shaders.js +103 -1
  95. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-shaders.js.map +1 -1
  96. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-system.d.ts.map +1 -1
  97. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-system.js +330 -27
  98. package/node_modules/@fps-games/babylon-renderer/dist/shadows/planar-shadow-system.js.map +1 -1
  99. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -1
  100. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +159 -0
  101. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -1
  102. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +8 -1
  103. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -1
  104. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +53 -2
  105. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
  106. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +1 -0
  107. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
  108. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  109. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +30 -0
  110. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  111. package/node_modules/@fps-games/editor-babylon/dist/projection.js +346 -11
  112. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  113. package/node_modules/@fps-games/editor-babylon/dist/scene-view-camera-controller.d.ts +11 -0
  114. package/node_modules/@fps-games/editor-babylon/dist/scene-view-camera-controller.d.ts.map +1 -1
  115. package/node_modules/@fps-games/editor-babylon/dist/scene-view-camera-controller.js +113 -29
  116. package/node_modules/@fps-games/editor-babylon/dist/scene-view-camera-controller.js.map +1 -1
  117. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +13 -1
  118. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
  119. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +543 -3
  120. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
  121. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  122. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +5 -2
  123. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  124. package/node_modules/@fps-games/editor-browser/dist/index.js +3 -1
  125. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  126. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-context-menu.js +1 -1
  127. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-context-menu.js.map +1 -1
  128. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.d.ts.map +1 -1
  129. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js +7 -9
  130. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js.map +1 -1
  131. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js +2 -2
  132. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js.map +1 -1
  133. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-command-adapter.d.ts +21 -0
  134. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-command-adapter.d.ts.map +1 -0
  135. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-command-adapter.js +75 -0
  136. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-command-adapter.js.map +1 -0
  137. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
  138. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +288 -71
  139. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
  140. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.d.ts +5 -0
  141. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.d.ts.map +1 -0
  142. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.js +92 -0
  143. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-scope.js.map +1 -0
  144. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts +3 -0
  145. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  146. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +22 -7
  147. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  148. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts +4 -0
  149. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts.map +1 -1
  150. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js +21 -14
  151. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js.map +1 -1
  152. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  153. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +6 -4
  154. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  155. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts +19 -1
  156. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts.map +1 -1
  157. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js +79 -39
  158. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js.map +1 -1
  159. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.js +2 -2
  160. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.js.map +1 -1
  161. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +68 -1
  162. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  163. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts +2 -0
  164. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts.map +1 -1
  165. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js +10 -0
  166. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js.map +1 -1
  167. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +3 -2
  168. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  169. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +401 -241
  170. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  171. package/node_modules/@fps-games/editor-browser/dist/runtime-camera-debug-panel.d.ts +1 -0
  172. package/node_modules/@fps-games/editor-browser/dist/runtime-camera-debug-panel.d.ts.map +1 -1
  173. package/node_modules/@fps-games/editor-browser/dist/runtime-camera-debug-panel.js +1 -0
  174. package/node_modules/@fps-games/editor-browser/dist/runtime-camera-debug-panel.js.map +1 -1
  175. package/node_modules/@fps-games/editor-browser/dist/runtime-debug-panel-shell.d.ts +2 -0
  176. package/node_modules/@fps-games/editor-browser/dist/runtime-debug-panel-shell.d.ts.map +1 -1
  177. package/node_modules/@fps-games/editor-browser/dist/runtime-debug-panel-shell.js +27 -13
  178. package/node_modules/@fps-games/editor-browser/dist/runtime-debug-panel-shell.js.map +1 -1
  179. package/node_modules/@fps-games/editor-browser/dist/runtime-lighting-debug-panel.d.ts +1 -0
  180. package/node_modules/@fps-games/editor-browser/dist/runtime-lighting-debug-panel.d.ts.map +1 -1
  181. package/node_modules/@fps-games/editor-browser/dist/runtime-lighting-debug-panel.js +1 -0
  182. package/node_modules/@fps-games/editor-browser/dist/runtime-lighting-debug-panel.js.map +1 -1
  183. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  184. package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts +18 -0
  185. package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts.map +1 -0
  186. package/node_modules/@fps-games/editor-core/dist/agent-bridge.js +102 -0
  187. package/node_modules/@fps-games/editor-core/dist/agent-bridge.js.map +1 -0
  188. package/node_modules/@fps-games/editor-core/dist/index.d.ts +1 -0
  189. package/node_modules/@fps-games/editor-core/dist/index.d.ts.map +1 -1
  190. package/node_modules/@fps-games/editor-core/dist/index.js +1 -0
  191. package/node_modules/@fps-games/editor-core/dist/index.js.map +1 -1
  192. package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts +1 -1
  193. package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts.map +1 -1
  194. package/node_modules/@fps-games/editor-core/dist/viewport-tools.js.map +1 -1
  195. package/node_modules/@fps-games/editor-core/package.json +2 -2
  196. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/config.d.ts +3 -0
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/config.d.ts.map +1 -0
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/config.js +9 -0
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/config.js.map +1 -0
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/generated-module.d.ts +6 -0
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/generated-module.d.ts.map +1 -0
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/generated-module.js +89 -0
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/generated-module.js.map +1 -0
  205. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/identity.d.ts +18 -0
  206. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/identity.d.ts.map +1 -0
  207. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/identity.js +121 -0
  208. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/identity.js.map +1 -0
  209. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/index.d.ts +4 -0
  210. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/index.d.ts.map +1 -0
  211. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/index.js +3 -0
  212. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/index.js.map +1 -0
  213. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/metadata.d.ts +27 -0
  214. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/metadata.d.ts.map +1 -0
  215. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/metadata.js +782 -0
  216. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/metadata.js.map +1 -0
  217. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/node.d.ts +5 -0
  218. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/node.d.ts.map +1 -0
  219. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/node.js +5 -0
  220. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/node.js.map +1 -0
  221. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/registry.d.ts +80 -0
  222. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/registry.d.ts.map +1 -0
  223. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/registry.js +600 -0
  224. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/registry.js.map +1 -0
  225. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/types.d.ts +51 -0
  226. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/types.d.ts.map +1 -0
  227. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/types.js +2 -0
  228. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-database/types.js.map +1 -0
  229. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts +0 -1
  230. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  231. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +4 -42
  232. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  233. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts +1 -1
  234. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts.map +1 -1
  235. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js +1 -1
  236. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js.map +1 -1
  237. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
  238. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +2 -1
  239. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
  240. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/types.d.ts +3 -0
  241. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/types.d.ts.map +1 -1
  242. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +42 -2
  243. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  244. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +612 -8
  245. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  246. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +42 -0
  247. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  248. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts +1 -1
  249. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts.map +1 -1
  250. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js +1 -1
  251. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js.map +1 -1
  252. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  253. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +16 -9
  254. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  255. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts +5 -0
  256. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts.map +1 -1
  257. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js +28 -0
  258. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js.map +1 -1
  259. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +3 -0
  260. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
  261. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +3 -0
  262. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
  263. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +82 -2
  264. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
  265. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +396 -22
  266. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
  267. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
  268. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
  269. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
  270. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
  271. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/validation.d.ts.map +1 -1
  272. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/validation.js +0 -3
  273. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/validation.js.map +1 -1
  274. package/node_modules/@fps-games/editor-playable-sdk/dist/lighting-debug/math.d.ts +29 -1
  275. package/node_modules/@fps-games/editor-playable-sdk/dist/lighting-debug/math.d.ts.map +1 -1
  276. package/node_modules/@fps-games/editor-playable-sdk/dist/lighting-debug/math.js +143 -0
  277. package/node_modules/@fps-games/editor-playable-sdk/dist/lighting-debug/math.js.map +1 -1
  278. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  279. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +99 -11
  280. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  281. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
  282. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
  283. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
  284. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/transform.d.ts.map +1 -1
  285. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/transform.js +19 -1
  286. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/transform.js.map +1 -1
  287. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
  288. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +19 -3
  289. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
  290. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/assets.d.ts +1 -2
  291. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/assets.d.ts.map +1 -1
  292. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/assets.js +0 -14
  293. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/assets.js.map +1 -1
  294. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/import-plan.d.ts +1 -7
  295. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/import-plan.d.ts.map +1 -1
  296. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/import-plan.js +3 -32
  297. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/import-plan.js.map +1 -1
  298. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  299. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +16 -32
  300. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  301. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +5 -22
  302. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  303. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/compiler.d.ts +5 -0
  304. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/compiler.d.ts.map +1 -0
  305. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/compiler.js +996 -0
  306. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/compiler.js.map +1 -0
  307. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/index.d.ts +3 -0
  308. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/index.d.ts.map +1 -0
  309. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/index.js +3 -0
  310. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/index.js.map +1 -0
  311. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/types.d.ts +152 -0
  312. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/types.d.ts.map +1 -0
  313. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/types.js +2 -0
  314. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-compiler/types.js.map +1 -0
  315. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.d.ts.map +1 -1
  316. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js +4 -0
  317. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js.map +1 -1
  318. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  319. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +224 -12
  320. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  321. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -1
  322. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +158 -50
  323. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -1
  324. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/patch.d.ts.map +1 -1
  325. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/patch.js +45 -1
  326. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/patch.js.map +1 -1
  327. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/index.d.ts +5 -0
  328. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/index.d.ts.map +1 -0
  329. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/index.js +5 -0
  330. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/index.js.map +1 -0
  331. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/legacy.d.ts +21 -0
  332. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/legacy.d.ts.map +1 -0
  333. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/legacy.js +158 -0
  334. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/legacy.js.map +1 -0
  335. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/quality.d.ts +5 -0
  336. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/quality.d.ts.map +1 -0
  337. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/quality.js +83 -0
  338. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/quality.js.map +1 -0
  339. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/resolver.d.ts +35 -0
  340. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/resolver.d.ts.map +1 -0
  341. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/resolver.js +363 -0
  342. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/resolver.js.map +1 -0
  343. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/types.d.ts +105 -0
  344. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/types.d.ts.map +1 -0
  345. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/types.js +6 -0
  346. package/node_modules/@fps-games/editor-playable-sdk/dist/shadow-system/types.js.map +1 -0
  347. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +3 -0
  348. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -1
  349. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +44 -0
  350. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -1
  351. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/asset-authoring.d.ts +26 -0
  352. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/asset-authoring.d.ts.map +1 -0
  353. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/asset-authoring.js +105 -0
  354. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/asset-authoring.js.map +1 -0
  355. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts +3 -0
  356. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts.map +1 -1
  357. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js +3 -0
  358. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js.map +1 -1
  359. package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
  360. package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts +1127 -0
  361. package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts.map +1 -0
  362. package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.js +2180 -0
  363. package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.js.map +1 -0
  364. package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts +68 -0
  365. package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts.map +1 -0
  366. package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js +23 -0
  367. package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js.map +1 -0
  368. package/node_modules/@fps-games/editor-protocol/dist/index.d.ts +2 -0
  369. package/node_modules/@fps-games/editor-protocol/dist/index.d.ts.map +1 -1
  370. package/node_modules/@fps-games/editor-protocol/dist/index.js +2 -0
  371. package/node_modules/@fps-games/editor-protocol/dist/index.js.map +1 -1
  372. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  373. package/package.json +8 -8
@@ -0,0 +1,1876 @@
1
+ import { collectEditorShadowReceiverCandidates, detectEditorSceneDirectionalLightOrientationDrift, findEditorSceneTransform, mergeEditorShadowSettings, normalizeEditorSceneLightDirectionVector, readEditorShadowSettings, readEditorShadowSettingsWithLegacy, resolveEditorSceneGameObjectShadowSettings, resolveEditorShadowParams, resolveEditorShadowPlan, } from '@fps-games/editor-playable-sdk';
2
+ import { EDITOR_AGENT_BRIDGE_CAPABILITY_ID, } from '@fps-games/editor-protocol';
3
+ import { createLocalEditorAgentBridgeFailure, editorTransformSnapshotToAgentTransform, } from '../diagnostics.js';
4
+ import { normalizeAgentBridgeIdList, normalizeAgentBridgeString, } from '../shared.js';
5
+ const PREFAB_STAGE_ITEM_PREFIX = 'prefab-node:';
6
+ const SHADOW_POLICY_FIELDS = [
7
+ 'shadow.cast',
8
+ 'shadow.receive',
9
+ 'shadow.mode',
10
+ 'shadow.quality',
11
+ 'shadow.light.mode',
12
+ 'shadow.light.lightId',
13
+ 'shadow.params.opacity',
14
+ 'shadow.params.softness',
15
+ 'shadow.params.bias',
16
+ 'shadow.params.normalBias',
17
+ 'shadow.params.maxDistance',
18
+ 'shadow.params.resolution',
19
+ 'shadow.params.cascadeCount',
20
+ 'shadow.params.bakeSamples',
21
+ 'shadow.params.blurKernel',
22
+ ];
23
+ export function createLocalEditorAgentBridgeShadowSource(state, options, renderUi, operations) {
24
+ return {
25
+ getPolicy(input) {
26
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_GET, state, input, operations);
27
+ if (!resolved.ok)
28
+ return resolved.result;
29
+ return createShadowPolicyGetOutput(resolved.target);
30
+ },
31
+ setPolicy(input) {
32
+ const policy = normalizeShadowPolicy(input.policy);
33
+ if (!policy.ok) {
34
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_SET, policy.message, { code: 'shadow.invalidInput', details: { hasPolicy: input.policy != null } });
35
+ }
36
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_SET, state, input, operations);
37
+ if (!resolved.ok)
38
+ return resolved.result;
39
+ if (resolved.target.kind === 'scene') {
40
+ return setSceneShadowPolicy(state, options, renderUi, operations, resolved.target, policy.settings);
41
+ }
42
+ return setPrefabStageShadowPolicy(renderUi, operations, resolved.target, policy.settings);
43
+ },
44
+ listReceivers(input) {
45
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_RECEIVERS_LIST, state, input, operations);
46
+ if (!resolved.ok)
47
+ return resolved.result;
48
+ const casterId = getResolvedTargetCasterId(resolved.target);
49
+ const projectionContext = createShadowProjectionContext(resolved.target, operations);
50
+ return {
51
+ receivers: mapShadowReceivers(collectEditorShadowReceiverCandidates({
52
+ document: resolved.target.document,
53
+ casterId,
54
+ }), state, { casterId, projectionContext }).filter(receiver => input.includeAuto === true || receiver.source !== 'auto'),
55
+ diagnostics: createShadowTargetDiagnostics(resolved.target),
56
+ };
57
+ },
58
+ resolvePreview(input) {
59
+ const policy = input.policy === undefined ? { ok: true, settings: undefined } : normalizeShadowPolicy(input.policy);
60
+ if (!policy.ok) {
61
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_RESOLVE_PREVIEW, policy.message, { code: 'shadow.invalidInput', details: { hasPolicy: input.policy != null } });
62
+ }
63
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_RESOLVE_PREVIEW, state, input, operations);
64
+ if (!resolved.ok)
65
+ return resolved.result;
66
+ const receiverIds = normalizeAgentBridgeIdList(input.receiverIds ?? []);
67
+ const casterId = getResolvedTargetCasterId(resolved.target);
68
+ const planInput = {
69
+ document: resolved.target.document,
70
+ casterId,
71
+ explicitReceiverIds: receiverIds.length > 0 ? receiverIds : undefined,
72
+ strictExplicitReceivers: receiverIds.length > 0,
73
+ ...(policy.settings !== undefined ? { settings: { instance: policy.settings } } : {}),
74
+ };
75
+ const plan = mapShadowPlan(resolveEditorShadowPlan(planInput));
76
+ const allReceivers = mapShadowReceivers(collectEditorShadowReceiverCandidates({
77
+ document: resolved.target.document,
78
+ casterId,
79
+ explicitReceiverIds: receiverIds.length > 0 ? receiverIds : undefined,
80
+ }), state, {
81
+ casterId,
82
+ lightId: plan.lightId,
83
+ projectionContext: createShadowProjectionContext(resolved.target, operations),
84
+ });
85
+ const receiverIdSet = new Set(plan.receiverIds);
86
+ const receivers = receiverIds.length > 0
87
+ ? allReceivers.filter(receiver => receiverIdSet.has(receiver.receiverId))
88
+ : allReceivers;
89
+ const light = createShadowLightSummary(resolved.target.document, plan.lightId);
90
+ return {
91
+ target: resolved.target.target,
92
+ plan,
93
+ caster: createShadowDebugTargetSummary(resolved.target, state, createShadowProjectionContext(resolved.target, operations)),
94
+ ...(light ? { light } : {}),
95
+ footprint: createShadowFootprintSummary(plan, receivers, state, createShadowProjectionContext(resolved.target, operations), light),
96
+ receivers,
97
+ diagnostics: createShadowTargetDiagnostics(resolved.target),
98
+ };
99
+ },
100
+ inspectDebug(input) {
101
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_DEBUG_INSPECT, state, input, operations);
102
+ if (!resolved.ok)
103
+ return resolved.result;
104
+ return createShadowDebugInspectOutput(resolved.target, state, {
105
+ projectionContext: createShadowProjectionContext(resolved.target, operations),
106
+ }, {
107
+ shadowPreviewDebugInfo: operations.getShadowPreviewDebugInfo?.() ?? null,
108
+ });
109
+ },
110
+ enterDebugContext(input) {
111
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_DEBUG_CONTEXT_ENTER, state, input, operations);
112
+ if (!resolved.ok)
113
+ return resolved.result;
114
+ return enterShadowDebugContext(state, renderUi, operations, resolved.target, input);
115
+ },
116
+ clearDebugContext() {
117
+ return clearShadowDebugContext(state, renderUi, operations);
118
+ },
119
+ setDebugOverlay(input) {
120
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_DEBUG_OVERLAY_SET, state, input, operations);
121
+ if (!resolved.ok)
122
+ return resolved.result;
123
+ const inspect = createShadowDebugInspectOutput(resolved.target, state, {
124
+ receiverIds: input.receiverIds ?? [],
125
+ projectionContext: createShadowProjectionContext(resolved.target, operations),
126
+ });
127
+ const overlayItems = createShadowDebugOverlayItems(inspect, input);
128
+ const overlayIds = operations.setShadowDebugOverlay?.(overlayItems)
129
+ ?? state.projection?.setShadowDebugOverlay?.(overlayItems)
130
+ ?? overlayItems.map(item => item.id);
131
+ operations.requestSceneFrame('agent-shadow-debug-overlay-set');
132
+ renderUi();
133
+ const diagnostics = [
134
+ ...(inspect.diagnostics ?? []),
135
+ ...(!overlayItems.length ? [{
136
+ severity: 'warning',
137
+ source: 'editor',
138
+ code: 'shadow.debugOverlayEmpty',
139
+ message: 'No shadow debug overlay items could be created for the resolved target.',
140
+ }] : []),
141
+ ];
142
+ return {
143
+ enabled: overlayItems.length > 0,
144
+ target: inspect.target,
145
+ overlayIds,
146
+ ...(diagnostics.length ? { diagnostics } : {}),
147
+ };
148
+ },
149
+ clearDebugOverlay() {
150
+ const cleared = operations.clearShadowDebugOverlay?.()
151
+ ?? state.projection?.clearShadowDebugOverlay?.()
152
+ ?? false;
153
+ operations.requestSceneFrame('agent-shadow-debug-overlay-clear');
154
+ renderUi();
155
+ return {
156
+ cleared,
157
+ };
158
+ },
159
+ measureVisibility(input) {
160
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_DEBUG_VISIBILITY_MEASURE, state, input, operations);
161
+ if (!resolved.ok)
162
+ return resolved.result;
163
+ const inspect = createShadowDebugInspectOutput(resolved.target, state, {
164
+ receiverIds: input.receiverIds ?? [],
165
+ projectionContext: createShadowProjectionContext(resolved.target, operations),
166
+ });
167
+ return createShadowDebugVisibilityMeasureOutput(inspect, input);
168
+ },
169
+ async bakeStatic(input) {
170
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_STATIC_BAKE, state, input, operations);
171
+ if (!resolved.ok)
172
+ return resolved.result;
173
+ const receiverIds = normalizeAgentBridgeIdList(input.receiverIds ?? []);
174
+ const casterId = getResolvedTargetCasterId(resolved.target);
175
+ const quality = input.quality && input.quality !== 'inherit' ? input.quality : undefined;
176
+ const effectivePolicy = getResolvedTargetShadowPolicy(resolved.target);
177
+ const bakePolicy = mergeEditorShadowSettings(effectivePolicy, {
178
+ mode: 'static',
179
+ ...(quality ? { quality } : {}),
180
+ });
181
+ const planInput = {
182
+ document: resolved.target.document,
183
+ casterId,
184
+ explicitReceiverIds: receiverIds.length > 0 ? receiverIds : undefined,
185
+ strictExplicitReceivers: receiverIds.length > 0,
186
+ settings: { instance: bakePolicy },
187
+ };
188
+ const plan = mapShadowPlan(resolveEditorShadowPlan(planInput));
189
+ const targetDiagnostics = createShadowTargetDiagnostics(resolved.target);
190
+ if (resolved.target.kind !== 'scene') {
191
+ return {
192
+ target: resolved.target.target,
193
+ baked: false,
194
+ plan,
195
+ stale: true,
196
+ diagnostics: [
197
+ ...targetDiagnostics,
198
+ {
199
+ severity: 'warning',
200
+ source: 'editor',
201
+ code: 'shadow.staticBakeSceneOnly',
202
+ message: 'Static shadow baking runs against the main scene. Prefab stage policies are baked after prefab instances are placed in a scene.',
203
+ },
204
+ ],
205
+ };
206
+ }
207
+ if (!operations.runRenderingAction) {
208
+ return {
209
+ target: resolved.target.target,
210
+ baked: false,
211
+ plan,
212
+ stale: true,
213
+ diagnostics: [
214
+ ...targetDiagnostics,
215
+ {
216
+ severity: 'warning',
217
+ source: 'editor',
218
+ code: 'shadow.staticBakeUnavailable',
219
+ message: 'Static shadow bake is unavailable because this editor session does not expose the rendering action pipeline.',
220
+ },
221
+ ],
222
+ };
223
+ }
224
+ const actionResult = await operations.runRenderingAction('bake-static-shadows');
225
+ const bakedSourceNodeIds = readRenderingActionStaticBakeSourceNodeIds(actionResult);
226
+ const targetConfirmed = bakedSourceNodeIds?.includes(casterId) === true;
227
+ const baked = actionResult.ok === true && actionResult.changed === true && targetConfirmed;
228
+ const bakeDiagnostic = createStaticBakeDiagnostic(actionResult, targetConfirmed, bakedSourceNodeIds);
229
+ return {
230
+ target: resolved.target.target,
231
+ baked,
232
+ plan,
233
+ stale: !baked,
234
+ diagnostics: [
235
+ ...targetDiagnostics,
236
+ bakeDiagnostic,
237
+ ],
238
+ };
239
+ },
240
+ invalidateStatic(input) {
241
+ const resolved = resolveShadowTarget(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_STATIC_INVALIDATE, state, input, operations);
242
+ if (!resolved.ok)
243
+ return resolved.result;
244
+ const targetDiagnostics = createShadowTargetDiagnostics(resolved.target);
245
+ if (resolved.target.kind !== 'scene') {
246
+ return {
247
+ target: resolved.target.target,
248
+ invalidated: false,
249
+ stale: true,
250
+ diagnostics: [
251
+ ...targetDiagnostics,
252
+ {
253
+ severity: 'warning',
254
+ source: 'editor',
255
+ code: 'shadow.staticInvalidateSceneOnly',
256
+ message: 'Static shadow invalidation runs against scene instances. Prefab stage policies are invalidated after placement in a scene.',
257
+ },
258
+ ],
259
+ };
260
+ }
261
+ const plan = mapShadowPlan(resolveEditorShadowPlan({
262
+ document: resolved.target.document,
263
+ casterId: resolved.target.objectId,
264
+ }));
265
+ if (plan.backend !== 'static-baked') {
266
+ return {
267
+ target: resolved.target.target,
268
+ invalidated: false,
269
+ stale: false,
270
+ diagnostics: [
271
+ ...targetDiagnostics,
272
+ {
273
+ severity: 'warning',
274
+ source: 'editor',
275
+ code: 'shadow.staticInvalidateNonStaticTarget',
276
+ message: 'Static shadow invalidation only applies to targets resolved to the static-baked backend.',
277
+ details: { backend: plan.backend, mode: plan.mode },
278
+ },
279
+ ],
280
+ };
281
+ }
282
+ if (!operations.invalidateStaticShadowArtifact) {
283
+ return {
284
+ target: resolved.target.target,
285
+ invalidated: false,
286
+ stale: true,
287
+ diagnostics: [
288
+ ...targetDiagnostics,
289
+ {
290
+ severity: 'warning',
291
+ source: 'editor',
292
+ code: 'shadow.staticInvalidateUnavailable',
293
+ message: 'Static shadow invalidation is unavailable because this editor session does not expose the shadow preview artifact lifecycle.',
294
+ },
295
+ ],
296
+ };
297
+ }
298
+ const invalidated = operations.invalidateStaticShadowArtifact();
299
+ return {
300
+ target: resolved.target.target,
301
+ invalidated,
302
+ stale: true,
303
+ diagnostics: [
304
+ ...targetDiagnostics,
305
+ {
306
+ severity: invalidated ? 'info' : 'warning',
307
+ source: 'editor',
308
+ code: invalidated ? 'shadow.staticInvalidated' : 'shadow.staticInvalidateNoArtifact',
309
+ message: invalidated
310
+ ? 'Static shadow preview artifact was invalidated; run shadow.static.bake to refresh scene artifacts.'
311
+ : 'Static shadow target is static, but no active preview artifact was available to invalidate.',
312
+ details: { backend: plan.backend, mode: plan.mode },
313
+ },
314
+ ],
315
+ };
316
+ },
317
+ };
318
+ }
319
+ function createShadowPolicyGetOutput(resolved) {
320
+ if (resolved.kind === 'scene') {
321
+ const effective = resolveEditorSceneGameObjectShadowSettings(resolved.document, resolved.gameObject);
322
+ return {
323
+ target: resolved.target,
324
+ ...(resolved.gameObject.shadow ? { policy: structuredClone(resolved.gameObject.shadow) } : {}),
325
+ effectivePolicy: (effective.settings ? structuredClone(effective.settings) : {}),
326
+ plan: mapShadowPlan(resolveEditorShadowPlan({
327
+ document: resolved.document,
328
+ casterId: resolved.objectId,
329
+ })),
330
+ diagnostics: [
331
+ ...mapShadowDiagnostics(effective.diagnostics),
332
+ ...createShadowTargetDiagnostics(resolved),
333
+ ],
334
+ };
335
+ }
336
+ const policy = readPrefabNodeShadowPolicy(resolved.node);
337
+ return {
338
+ target: resolved.target,
339
+ ...(policy ? { policy: structuredClone(policy) } : {}),
340
+ effectivePolicy: (policy ? structuredClone(policy) : {}),
341
+ plan: mapShadowPlan(resolveEditorShadowPlan({
342
+ document: resolved.document,
343
+ casterId: resolved.nodeId,
344
+ })),
345
+ diagnostics: createShadowTargetDiagnostics(resolved),
346
+ };
347
+ }
348
+ function createShadowDebugInspectOutput(resolved, state, options = {}, extraOptions) {
349
+ const casterId = getResolvedTargetCasterId(resolved);
350
+ const projectionContext = options.projectionContext ?? createIdentityShadowProjectionContext();
351
+ const effectivePolicy = getResolvedTargetShadowPolicy(resolved);
352
+ const receiverIds = normalizeAgentBridgeIdList(options.receiverIds ?? []);
353
+ const planInput = {
354
+ document: resolved.document,
355
+ casterId,
356
+ explicitReceiverIds: receiverIds.length > 0 ? receiverIds : undefined,
357
+ strictExplicitReceivers: receiverIds.length > 0,
358
+ };
359
+ const plan = mapShadowPlan(resolveEditorShadowPlan(planInput));
360
+ const allReceivers = mapShadowReceivers(collectEditorShadowReceiverCandidates({
361
+ document: resolved.document,
362
+ casterId,
363
+ explicitReceiverIds: receiverIds.length > 0 ? receiverIds : undefined,
364
+ }), state, { casterId, lightId: plan.lightId, projectionContext });
365
+ const resolvedReceiverIds = new Set(plan.receiverIds);
366
+ const receivers = receiverIds.length > 0
367
+ ? allReceivers.filter(receiver => resolvedReceiverIds.has(receiver.receiverId))
368
+ : allReceivers;
369
+ const authoredPolicy = getResolvedTargetAuthoredPolicy(resolved);
370
+ const light = createShadowLightSummary(resolved.document, plan.lightId);
371
+ const runtimeEvidence = createShadowDebugRuntimeEvidence(plan, receivers, extraOptions?.shadowPreviewDebugInfo, createShadowRuntimeEvidenceCasterIds(resolved, casterId, projectionContext));
372
+ const diagnostics = [
373
+ ...createShadowTargetDiagnostics(resolved),
374
+ ...plan.diagnostics,
375
+ ...(runtimeEvidence.diagnostics ?? []),
376
+ ];
377
+ return {
378
+ target: resolved.target,
379
+ caster: createShadowDebugTargetSummary(resolved, state, projectionContext),
380
+ ...(authoredPolicy ? { policy: structuredClone(authoredPolicy) } : {}),
381
+ effectivePolicy: (effectivePolicy ? structuredClone(effectivePolicy) : {}),
382
+ plan,
383
+ ...(light ? { light } : {}),
384
+ receivers,
385
+ footprint: createShadowFootprintSummary(plan, receivers, state, projectionContext, light),
386
+ runtimeEvidence,
387
+ ...(diagnostics.length ? { diagnostics } : {}),
388
+ };
389
+ }
390
+ function enterShadowDebugContext(state, renderUi, operations, resolved, input) {
391
+ const projectionContext = createShadowProjectionContext(resolved, operations);
392
+ const receiverIds = normalizeAgentBridgeIdList(input.receiverIds ?? []);
393
+ const initialInspect = createShadowDebugInspectOutput(resolved, state, {
394
+ receiverIds,
395
+ projectionContext,
396
+ }, {
397
+ shadowPreviewDebugInfo: operations.getShadowPreviewDebugInfo?.() ?? null,
398
+ });
399
+ const targetId = getResolvedTargetCasterId(resolved);
400
+ const logicalKeepIds = new Set([targetId]);
401
+ const protectedReceiverIds = initialInspect.plan.receiverIds.length > 0
402
+ ? initialInspect.plan.receiverIds
403
+ : initialInspect.receivers.map(receiver => receiver.receiverId);
404
+ for (const receiverId of protectedReceiverIds)
405
+ logicalKeepIds.add(receiverId);
406
+ if (initialInspect.light?.lightId)
407
+ logicalKeepIds.add(initialInspect.light.lightId);
408
+ const ambientLightIds = input.includeAmbientLights === false
409
+ ? []
410
+ : collectShadowDebugAmbientLightIds(resolved.document, initialInspect.light?.lightId);
411
+ for (const ambientId of ambientLightIds)
412
+ logicalKeepIds.add(ambientId);
413
+ const projectionKeepIds = new Set();
414
+ for (const id of logicalKeepIds) {
415
+ const projectionId = projectionContext.resolveProjectionId(id);
416
+ projectionKeepIds.add(projectionId);
417
+ for (const parentId of state.projection?.getProjectionParentIds?.(projectionId) ?? []) {
418
+ projectionKeepIds.add(parentId);
419
+ }
420
+ }
421
+ const objectIds = state.projection?.getProjectedNodeIds?.() ?? [...projectionKeepIds];
422
+ if (objectIds.length === 0) {
423
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_DEBUG_CONTEXT_ENTER, 'Viewport projection is unavailable or has no projected objects for Shadow Debug Context.', { code: 'viewport.projectionUnavailable' });
424
+ }
425
+ const nextOverrides = {};
426
+ for (const objectId of objectIds)
427
+ nextOverrides[objectId] = projectionKeepIds.has(objectId);
428
+ const previous = JSON.stringify(state.previewVisibility);
429
+ state.previewVisibility.overrides = nextOverrides;
430
+ state.previewVisibility.isolatedObjectIds = [...projectionKeepIds];
431
+ state.previewVisibility.protectedReceiverIds = [...new Set(protectedReceiverIds.flatMap(id => [
432
+ id,
433
+ projectionContext.resolveProjectionId(id),
434
+ ]))];
435
+ state.previewVisibility.protectedObjectIds = [...new Set([...state.previewVisibility.protectedReceiverIds, ...ambientLightIds.flatMap(id => [
436
+ id,
437
+ projectionContext.resolveProjectionId(id),
438
+ ])])];
439
+ state.previewVisibility.reason = normalizeAgentBridgeString(input.reason)
440
+ || `Shadow Debug Context for ${targetId}`;
441
+ state.projection?.clearPreviewVisibilityOverrides?.();
442
+ const entries = state.projection?.setPreviewVisibilityOverrides?.(nextOverrides) ?? [];
443
+ const inspect = createShadowDebugInspectOutput(resolved, state, {
444
+ receiverIds,
445
+ projectionContext,
446
+ }, {
447
+ shadowPreviewDebugInfo: operations.getShadowPreviewDebugInfo?.() ?? null,
448
+ });
449
+ const overlayItems = input.showOverlay === false
450
+ ? []
451
+ : createShadowDebugOverlayItems(inspect, {
452
+ ...input,
453
+ showCasterBounds: true,
454
+ showReceiverBounds: true,
455
+ showLightDirection: true,
456
+ showFootprint: true,
457
+ showArtifactBounds: true,
458
+ });
459
+ const overlayIds = overlayItems.length > 0
460
+ ? operations.setShadowDebugOverlay?.(overlayItems)
461
+ ?? state.projection?.setShadowDebugOverlay?.(overlayItems)
462
+ ?? overlayItems.map(item => item.id)
463
+ : [];
464
+ const visibilityMeasure = createShadowDebugVisibilityMeasureOutput(inspect, input);
465
+ const hiddenObjectIds = objectIds.filter(objectId => !projectionKeepIds.has(objectId));
466
+ const diagnostics = [
467
+ ...(inspect.diagnostics ?? []),
468
+ ...(!protectedReceiverIds.length ? [{
469
+ severity: 'warning',
470
+ source: 'editor',
471
+ code: 'shadow.debugContextNoReceiver',
472
+ message: 'Shadow Debug Context could not resolve a receiver to protect; screenshots may still be ambiguous.',
473
+ details: { targetId },
474
+ }] : []),
475
+ ...(!initialInspect.light?.lightId && initialInspect.plan.backend !== 'none' ? [{
476
+ severity: 'warning',
477
+ source: 'editor',
478
+ code: 'shadow.debugContextNoLight',
479
+ message: 'Shadow Debug Context could not resolve a shadow light to preserve.',
480
+ details: { backend: initialInspect.plan.backend, targetId },
481
+ }] : []),
482
+ ...(!ambientLightIds.length && input.includeAmbientLights !== false ? [{
483
+ severity: 'info',
484
+ source: 'editor',
485
+ code: 'shadow.debugContextNoAmbientLight',
486
+ message: 'No ambient/environment light was found to preserve for visual debugging.',
487
+ }] : []),
488
+ ];
489
+ operations.requestSceneFrame('agent-shadow-debug-context-enter');
490
+ renderUi();
491
+ return {
492
+ entered: previous !== JSON.stringify(state.previewVisibility) || overlayIds.length > 0,
493
+ target: inspect.target,
494
+ keptObjectIds: [...logicalKeepIds],
495
+ hiddenObjectIds,
496
+ protectedReceiverIds,
497
+ lightIds: initialInspect.light?.lightId ? [initialInspect.light.lightId] : [],
498
+ ambientLightIds,
499
+ overlayIds,
500
+ snapshot: createShadowDebugContextVisibilitySnapshot(state, entries, diagnostics),
501
+ inspect,
502
+ visibilityMeasure,
503
+ ...(diagnostics.length ? { diagnostics } : {}),
504
+ };
505
+ }
506
+ function clearShadowDebugContext(state, renderUi, operations) {
507
+ const previousCount = Object.keys(state.previewVisibility.overrides).length;
508
+ const hadIsolation = state.previewVisibility.isolatedObjectIds.length > 0;
509
+ const hadProtection = (state.previewVisibility.protectedObjectIds?.length ?? 0) > 0
510
+ || (state.previewVisibility.protectedReceiverIds?.length ?? 0) > 0;
511
+ state.previewVisibility.overrides = {};
512
+ state.previewVisibility.isolatedObjectIds = [];
513
+ delete state.previewVisibility.protectedObjectIds;
514
+ delete state.previewVisibility.protectedReceiverIds;
515
+ delete state.previewVisibility.reason;
516
+ state.projection?.clearPreviewVisibilityOverrides?.();
517
+ const overlayCleared = operations.clearShadowDebugOverlay?.()
518
+ ?? state.projection?.clearShadowDebugOverlay?.()
519
+ ?? false;
520
+ const visibilityCleared = previousCount > 0 || hadIsolation || hadProtection;
521
+ operations.requestSceneFrame('agent-shadow-debug-context-clear');
522
+ renderUi();
523
+ return {
524
+ cleared: visibilityCleared || overlayCleared,
525
+ overlayCleared,
526
+ visibilityCleared,
527
+ };
528
+ }
529
+ function createShadowDebugContextVisibilitySnapshot(state, entries, diagnostics) {
530
+ const entryById = new Map(entries.map(entry => [entry.nodeId, entry]));
531
+ const objectIds = new Set([
532
+ ...Object.keys(state.previewVisibility.overrides),
533
+ ...entries.map(entry => entry.nodeId),
534
+ ...state.previewVisibility.isolatedObjectIds,
535
+ ]);
536
+ const isolatedIds = new Set(state.previewVisibility.isolatedObjectIds);
537
+ return {
538
+ isolated: isolatedIds.size > 0,
539
+ isolatedObjectIds: [...isolatedIds],
540
+ entries: [...objectIds].sort().map((objectId) => {
541
+ const entry = entryById.get(objectId);
542
+ const overrideVisible = state.previewVisibility.overrides[objectId];
543
+ const authoredVisible = entry?.authoredActive ?? true;
544
+ return {
545
+ objectId,
546
+ authoredVisible,
547
+ previewVisible: entry?.effectiveVisible ?? (authoredVisible && overrideVisible !== false),
548
+ ...(typeof overrideVisible === 'boolean' ? { overrideVisible } : {}),
549
+ isolated: isolatedIds.has(objectId),
550
+ ...(state.previewVisibility.protectedReceiverIds?.includes(objectId) ? {
551
+ diagnostics: [{
552
+ severity: 'info',
553
+ source: 'editor',
554
+ code: 'shadow.receiverProtectedInDebugContext',
555
+ message: 'This receiver is protected by the active Shadow Debug Context and should remain visible for screenshot validation.',
556
+ details: { objectId },
557
+ }],
558
+ } : {}),
559
+ };
560
+ }),
561
+ ...(state.previewVisibility.reason ? { reason: state.previewVisibility.reason } : {}),
562
+ ...(diagnostics.length ? { diagnostics: [...diagnostics] } : {}),
563
+ };
564
+ }
565
+ function collectShadowDebugAmbientLightIds(document, shadowLightId) {
566
+ const ids = [];
567
+ const seen = new Set();
568
+ const gameObjects = Array.isArray(document.scene?.gameObjects) ? document.scene.gameObjects : [];
569
+ for (const gameObject of gameObjects) {
570
+ if (!isRecord(gameObject))
571
+ continue;
572
+ const id = typeof gameObject.id === 'string' ? gameObject.id : '';
573
+ if (!id || id === shadowLightId || seen.has(id))
574
+ continue;
575
+ const name = typeof gameObject.name === 'string' ? gameObject.name : '';
576
+ const light = isRecord(gameObject.light) ? gameObject.light : null;
577
+ const lightType = typeof light?.type === 'string' ? light.type.toLowerCase() : '';
578
+ const haystack = `${id} ${name}`.toLowerCase();
579
+ const isAmbient = lightType === 'hemispheric'
580
+ || lightType === 'ambient'
581
+ || lightType === 'environment'
582
+ || haystack.includes('environment_light')
583
+ || haystack.includes('environment light')
584
+ || haystack.includes('ambient');
585
+ if (!isAmbient)
586
+ continue;
587
+ seen.add(id);
588
+ ids.push(id);
589
+ }
590
+ return ids;
591
+ }
592
+ function createShadowDebugOverlayItems(inspect, input) {
593
+ const items = [];
594
+ const flags = readShadowDebugOverlayFlags(input);
595
+ const receiverIds = new Set(normalizeAgentBridgeIdList(input.receiverIds ?? []));
596
+ const targetId = inspect.caster?.objectId ?? inspect.caster?.nodeId ?? 'target';
597
+ const casterBounds = createOverlayBounds(inspect.caster?.bounds);
598
+ if (flags.showCasterBounds && casterBounds) {
599
+ items.push({
600
+ id: `shadow-debug:caster:${targetId}`,
601
+ kind: 'caster-bounds',
602
+ bounds: casterBounds,
603
+ });
604
+ }
605
+ const receivers = receiverIds.size
606
+ ? inspect.receivers.filter(receiver => receiverIds.has(receiver.receiverId))
607
+ : inspect.receivers;
608
+ if (flags.showReceiverBounds) {
609
+ for (const receiver of receivers) {
610
+ const bounds = createOverlayBounds(receiver.bounds);
611
+ if (!bounds)
612
+ continue;
613
+ items.push({
614
+ id: `shadow-debug:receiver:${receiver.receiverId}`,
615
+ kind: 'receiver-bounds',
616
+ bounds,
617
+ });
618
+ items.push({
619
+ id: `shadow-debug:receiver-surface:${receiver.receiverId}`,
620
+ kind: 'receiver-surface',
621
+ bounds,
622
+ });
623
+ }
624
+ }
625
+ if (flags.showFootprint && inspect.footprint.center && inspect.footprint.size) {
626
+ items.push({
627
+ id: `shadow-debug:footprint:${inspect.footprint.receiverId ?? targetId}`,
628
+ kind: 'footprint',
629
+ center: { ...inspect.footprint.center },
630
+ size: {
631
+ x: Math.max(inspect.footprint.size.x, 0.01),
632
+ y: Math.max(inspect.footprint.size.y, 0.015),
633
+ z: Math.max(inspect.footprint.size.z, 0.01),
634
+ },
635
+ });
636
+ }
637
+ if (flags.showLightDirection) {
638
+ const lightDirection = inspect.light?.direction ?? inspect.footprint.normal;
639
+ const center = inspect.footprint.center ?? casterBounds?.center;
640
+ const size = inspect.footprint.size ?? casterBounds?.size ?? { x: 2, y: 2, z: 2 };
641
+ if (center && lightDirection) {
642
+ items.push({
643
+ id: `shadow-debug:light:${inspect.light?.lightId ?? targetId}`,
644
+ kind: 'light-direction',
645
+ center: { ...center },
646
+ size: { ...size },
647
+ direction: { ...lightDirection },
648
+ });
649
+ }
650
+ }
651
+ if (flags.showArtifactBounds && inspect.footprint.kind === 'artifact') {
652
+ const artifactBounds = inspect.footprint.center && inspect.footprint.size
653
+ ? createOverlayBoundsFromCenterSize(inspect.footprint.center, inspect.footprint.size)
654
+ : undefined;
655
+ if (artifactBounds) {
656
+ items.push({
657
+ id: `shadow-debug:artifact:${targetId}`,
658
+ kind: 'artifact-bounds',
659
+ bounds: artifactBounds,
660
+ });
661
+ }
662
+ }
663
+ return items;
664
+ }
665
+ function createShadowDebugVisibilityMeasureOutput(inspect, input) {
666
+ const diagnostics = [
667
+ ...(inspect.diagnostics ?? []),
668
+ {
669
+ severity: 'info',
670
+ source: 'editor',
671
+ code: 'shadow.pixelReadbackUnavailable',
672
+ message: 'Pixel readback is not available in this editor bridge session, so shadow visibility is measured structurally from policy, receivers, footprint, and runtime evidence.',
673
+ },
674
+ ];
675
+ const requestedReceiverIds = normalizeAgentBridgeIdList(input.receiverIds ?? []);
676
+ const renderableCount = inspect.runtimeEvidence.renderableShadowPrimitiveCount ?? 0;
677
+ let visibleScore = 0;
678
+ let coverage = 0;
679
+ const opacity = clamp01(readNumber(inspect.plan.params.opacity, 0.42));
680
+ const casterInactive = inspect.caster?.active === false || inspect.caster?.visible === false;
681
+ const lightRequired = inspect.plan.backend === 'dynamic-map' || inspect.plan.backend === 'static-baked' || inspect.plan.backend === 'projected';
682
+ const lightMissing = lightRequired && !inspect.light?.lightId;
683
+ const missingCasterBounds = !inspect.caster?.bounds;
684
+ const plannedReceivers = inspect.receivers.filter(receiver => inspect.plan.receiverIds.includes(receiver.receiverId));
685
+ const visiblePlannedReceivers = plannedReceivers.filter(receiver => isShadowReceiverUsableForVisibility(receiver));
686
+ const selectedReceiver = selectShadowFootprintReceiver(inspect.plan, plannedReceivers);
687
+ const missingReceiverBounds = inspect.plan.receiverIds.length > 0
688
+ && inspect.plan.receiverIds.some(receiverId => !plannedReceivers.some(receiver => receiver.receiverId === receiverId && !!receiver.bounds));
689
+ const hiddenReceiverIds = plannedReceivers
690
+ .filter(receiver => receiver.active === false || receiver.visible === false)
691
+ .map(receiver => receiver.receiverId);
692
+ const ignoredHiddenReceiverIds = hiddenReceiverIds.filter(receiverId => receiverId !== selectedReceiver?.receiverId);
693
+ if (inspect.plan.backend === 'none' || inspect.plan.mode === 'none') {
694
+ diagnostics.push({
695
+ severity: 'info',
696
+ source: 'editor',
697
+ code: 'shadow.visibilityPolicyNone',
698
+ message: 'Resolved Shadow V2 policy is none, so no visible shadow is expected.',
699
+ details: { backend: inspect.plan.backend, mode: inspect.plan.mode },
700
+ });
701
+ }
702
+ else if (opacity <= 0.001) {
703
+ diagnostics.push({
704
+ severity: 'warning',
705
+ source: 'editor',
706
+ code: 'shadow.visibilityOpacityZero',
707
+ message: 'Resolved Shadow V2 opacity is zero, so no visible shadow is expected.',
708
+ details: { opacity },
709
+ });
710
+ }
711
+ else if (casterInactive) {
712
+ diagnostics.push({
713
+ severity: 'warning',
714
+ source: 'editor',
715
+ code: 'shadow.visibilityCasterInactive',
716
+ message: 'The resolved caster is inactive or hidden, so no visible shadow is expected.',
717
+ details: { active: inspect.caster?.active, visible: inspect.caster?.visible },
718
+ });
719
+ }
720
+ else if (lightMissing) {
721
+ diagnostics.push({
722
+ severity: 'warning',
723
+ source: 'editor',
724
+ code: 'shadow.visibilityLightMissing',
725
+ message: 'The resolved shadow backend requires a light, but no usable shadow light was resolved.',
726
+ details: { backend: inspect.plan.backend, lightId: inspect.plan.lightId },
727
+ });
728
+ }
729
+ else if (missingCasterBounds || missingReceiverBounds) {
730
+ diagnostics.push({
731
+ severity: 'warning',
732
+ source: 'editor',
733
+ code: 'shadow.visibilityBoundsUnavailable',
734
+ message: 'Caster or receiver projection bounds are unavailable, so structural visibility cannot confirm a visible shadow.',
735
+ details: { missingCasterBounds, missingReceiverBounds, receiverIds: inspect.plan.receiverIds },
736
+ });
737
+ }
738
+ else if (visiblePlannedReceivers.length === 0 && hiddenReceiverIds.length > 0) {
739
+ diagnostics.push({
740
+ severity: 'warning',
741
+ source: 'editor',
742
+ code: 'shadow.visibilityReceiverInactive',
743
+ message: 'One or more resolved receivers are inactive or hidden in the current preview, so structural visibility cannot confirm a visible shadow.',
744
+ details: { receiverIds: hiddenReceiverIds },
745
+ });
746
+ }
747
+ else if (inspect.receivers.length === 0 || inspect.plan.receiverIds.length === 0) {
748
+ diagnostics.push({
749
+ severity: 'warning',
750
+ source: 'editor',
751
+ code: 'shadow.visibilityNoReceiver',
752
+ message: 'Resolved Shadow V2 plan has no receiver, so a visible shadow is unlikely.',
753
+ details: { receiverIds: inspect.plan.receiverIds, requestedReceiverIds },
754
+ });
755
+ }
756
+ else if (renderableCount <= 0) {
757
+ diagnostics.push({
758
+ severity: 'warning',
759
+ source: 'editor',
760
+ code: 'shadow.visibilityNoRuntimePrimitive',
761
+ message: 'Resolved Shadow V2 plan has receivers but no renderable shadow primitive evidence.',
762
+ details: { backend: inspect.plan.backend, renderableShadowPrimitiveCount: renderableCount },
763
+ });
764
+ }
765
+ else {
766
+ if (ignoredHiddenReceiverIds.length > 0) {
767
+ diagnostics.push({
768
+ severity: 'info',
769
+ source: 'editor',
770
+ code: 'shadow.visibilityIgnoredHiddenReceiver',
771
+ message: 'Some resolved receivers are hidden in the current preview; structural visibility used the best visible receiver instead.',
772
+ details: {
773
+ receiverIds: ignoredHiddenReceiverIds,
774
+ selectedReceiverId: selectedReceiver?.receiverId,
775
+ },
776
+ });
777
+ }
778
+ const footprintConfidence = clamp01(readNumber(inspect.footprint.confidence, 0.5));
779
+ const receiverCoverage = clamp01((visiblePlannedReceivers.length > 0 ? visiblePlannedReceivers : plannedReceivers).reduce((max, receiver) => {
780
+ const overlap = receiver.suitability?.overlap;
781
+ return Math.max(max, typeof overlap === 'number' ? overlap : 0);
782
+ }, 0));
783
+ if (receiverCoverage <= 0.01) {
784
+ diagnostics.push({
785
+ severity: 'warning',
786
+ source: 'editor',
787
+ code: 'shadow.visibilityReceiverCoverageTooLow',
788
+ message: 'Resolved receivers have no meaningful X/Z overlap with the caster, so structural visibility cannot confirm a visible shadow.',
789
+ details: { coverage: receiverCoverage, receiverIds: inspect.plan.receiverIds },
790
+ });
791
+ }
792
+ else {
793
+ const backendFactor = inspect.plan.backend === 'dynamic-map'
794
+ ? 0.9
795
+ : inspect.plan.backend === 'static-baked'
796
+ ? inspect.plan.stale === true ? 0.35 : 0.85
797
+ : inspect.plan.backend === 'blob' || inspect.plan.backend === 'projected'
798
+ ? 0.75
799
+ : 0.5;
800
+ coverage = clamp01(Math.max(receiverCoverage, footprintConfidence * 0.65));
801
+ visibleScore = clamp01((0.2 + opacity * 0.35 + coverage * 0.3 + backendFactor * 0.15) * (renderableCount > 0 ? 1 : 0));
802
+ if (inspect.plan.stale === true || inspect.runtimeEvidence.artifactStale === true) {
803
+ visibleScore = Math.min(visibleScore, 0.35);
804
+ diagnostics.push({
805
+ severity: 'warning',
806
+ source: 'editor',
807
+ code: 'shadow.visibilityStaticStale',
808
+ message: 'Static shadow evidence is stale; treat visibility as low confidence until rebaked.',
809
+ });
810
+ }
811
+ }
812
+ }
813
+ return {
814
+ target: inspect.target,
815
+ visible: visibleScore >= 0.45,
816
+ visibleScore,
817
+ coverage,
818
+ renderableShadowPrimitiveCount: renderableCount,
819
+ measurementKind: 'structural',
820
+ diagnostics,
821
+ };
822
+ }
823
+ function isShadowReceiverUsableForVisibility(receiver) {
824
+ return receiver.active !== false && receiver.visible !== false && !!receiver.bounds;
825
+ }
826
+ function readNumber(value, fallback) {
827
+ return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
828
+ }
829
+ function clamp01(value) {
830
+ return Math.max(0, Math.min(1, value));
831
+ }
832
+ function readShadowDebugOverlayFlags(input) {
833
+ const explicit = input.showCasterBounds !== undefined
834
+ || input.showReceiverBounds !== undefined
835
+ || input.showLightDirection !== undefined
836
+ || input.showFootprint !== undefined
837
+ || input.showArtifactBounds !== undefined;
838
+ return {
839
+ showCasterBounds: explicit ? input.showCasterBounds === true : true,
840
+ showReceiverBounds: explicit ? input.showReceiverBounds === true : true,
841
+ showLightDirection: explicit ? input.showLightDirection === true : true,
842
+ showFootprint: explicit ? input.showFootprint === true : true,
843
+ showArtifactBounds: explicit ? input.showArtifactBounds === true : true,
844
+ };
845
+ }
846
+ function createOverlayBounds(bounds) {
847
+ if (!bounds?.center || !bounds.size)
848
+ return undefined;
849
+ const min = bounds.min ?? {
850
+ x: bounds.center.x - bounds.size.x / 2,
851
+ y: bounds.center.y - bounds.size.y / 2,
852
+ z: bounds.center.z - bounds.size.z / 2,
853
+ };
854
+ const max = bounds.max ?? {
855
+ x: bounds.center.x + bounds.size.x / 2,
856
+ y: bounds.center.y + bounds.size.y / 2,
857
+ z: bounds.center.z + bounds.size.z / 2,
858
+ };
859
+ return {
860
+ min: { ...min },
861
+ max: { ...max },
862
+ size: { ...bounds.size },
863
+ center: { ...bounds.center },
864
+ };
865
+ }
866
+ function createOverlayBoundsFromCenterSize(center, size) {
867
+ return {
868
+ center: { ...center },
869
+ size: { ...size },
870
+ min: {
871
+ x: center.x - size.x / 2,
872
+ y: center.y - size.y / 2,
873
+ z: center.z - size.z / 2,
874
+ },
875
+ max: {
876
+ x: center.x + size.x / 2,
877
+ y: center.y + size.y / 2,
878
+ z: center.z + size.z / 2,
879
+ },
880
+ };
881
+ }
882
+ function setSceneShadowPolicy(state, options, renderUi, operations, resolved, policy) {
883
+ if (!state.session) {
884
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_SET, 'Editor is not in edit mode.', { code: 'editor.notReady', objectId: resolved.objectId });
885
+ }
886
+ let changed = false;
887
+ let workingDocument = resolved.rawDocument;
888
+ for (const { path, value } of createShadowPolicyFieldPatches(policy)) {
889
+ const patch = options.documentAdapter.createSerializedPropertyPatch({
890
+ document: workingDocument,
891
+ targetId: resolved.objectId,
892
+ path,
893
+ value,
894
+ commitMode: 'change',
895
+ persistence: 'document',
896
+ source: 'custom',
897
+ });
898
+ if (!patch)
899
+ continue;
900
+ const result = state.session.dispatch({
901
+ type: 'document.patch',
902
+ label: patch.label ?? `Agent set shadow ${path}`,
903
+ patch: patch.patch,
904
+ targetId: resolved.objectId,
905
+ ...operations.withProjectionImpact(operations.resolveProjectionImpact(patch, operations.createReprojectProjectionImpact(patch.reprojectIds ?? [patch.changedId ?? resolved.objectId]))),
906
+ });
907
+ workingDocument = result.workingDocument;
908
+ if (result.documentChanged)
909
+ changed = true;
910
+ }
911
+ if (!changed) {
912
+ const output = createShadowPolicyGetOutput(resolved);
913
+ return {
914
+ target: output.target,
915
+ changed: false,
916
+ ...(output.policy ? { policy: output.policy } : {}),
917
+ effectivePolicy: output.effectivePolicy,
918
+ plan: output.plan,
919
+ diagnostics: output.diagnostics,
920
+ };
921
+ }
922
+ operations.reprojectProjectionForChangedIds(workingDocument, [resolved.objectId]);
923
+ state.summary = operations.summarizeDocument(workingDocument, state.session.getSource());
924
+ state.status = `Agent set shadow policy ${resolved.objectId}`;
925
+ renderUi();
926
+ const nextDocument = asEditorSceneDocument(workingDocument);
927
+ const nextObject = nextDocument ? findShadowGameObject(nextDocument, resolved.objectId) : null;
928
+ if (!nextDocument || !nextObject) {
929
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_SET, `Shadow target disappeared after patch: ${resolved.objectId}`, { code: 'shadow.targetMissing', objectId: resolved.objectId });
930
+ }
931
+ const output = createShadowPolicyGetOutput({
932
+ kind: 'scene',
933
+ target: resolved.target,
934
+ document: nextDocument,
935
+ rawDocument: workingDocument,
936
+ objectId: resolved.objectId,
937
+ gameObject: nextObject,
938
+ });
939
+ return {
940
+ target: output.target,
941
+ changed: true,
942
+ ...(output.policy ? { policy: output.policy } : {}),
943
+ effectivePolicy: output.effectivePolicy,
944
+ plan: output.plan,
945
+ diagnostics: output.diagnostics,
946
+ };
947
+ }
948
+ function setPrefabStageShadowPolicy(renderUi, operations, resolved, policy) {
949
+ const rootNodeId = findPrefabRootNodeId(resolved.details);
950
+ const changed = resolved.nodeId === rootNodeId
951
+ ? setPrefabRootShadowPolicy(operations, resolved.details, policy)
952
+ : operations.runPrefabStageAssetAction({
953
+ actionId: 'prefab.node.setShadow',
954
+ targetPrefabAssetId: resolved.details.stage.assetId,
955
+ nodeId: resolved.nodeId,
956
+ value: policy ?? null,
957
+ });
958
+ if (!changed) {
959
+ return createLocalEditorAgentBridgeFailure(EDITOR_AGENT_BRIDGE_CAPABILITY_ID.SHADOW_POLICY_SET, `Shadow policy action did not change prefab node: ${resolved.nodeId}`, { code: 'shadow.policyUnchanged', details: { assetId: resolved.details.stage.assetId, nodeId: resolved.nodeId } });
960
+ }
961
+ renderUi();
962
+ const nextDetails = operations.getPrefabStageDetails() ?? resolved.details;
963
+ const nextResolved = resolvePrefabShadowTargetFromDetails(nextDetails, {
964
+ nodeId: resolved.nodeId,
965
+ assetId: resolved.details.stage.assetId,
966
+ });
967
+ const output = createShadowPolicyGetOutput(nextResolved ?? resolved);
968
+ return {
969
+ target: output.target,
970
+ changed: true,
971
+ ...(output.policy ? { policy: output.policy } : {}),
972
+ effectivePolicy: output.effectivePolicy,
973
+ plan: output.plan,
974
+ diagnostics: output.diagnostics,
975
+ };
976
+ }
977
+ function setPrefabRootShadowPolicy(operations, details, policy) {
978
+ let changed = false;
979
+ for (const { path, value } of createShadowPolicyFieldPatches(policy)) {
980
+ const patched = operations.runPrefabStageAssetAction({
981
+ actionId: 'asset.edit-prefab-field',
982
+ assetId: details.stage.assetId,
983
+ browserAssetId: details.stage.browserAssetId,
984
+ assetKind: 'prefab',
985
+ targetPrefabAssetId: details.stage.assetId,
986
+ fieldPath: `prefab.defaults.${path}`,
987
+ value,
988
+ });
989
+ if (patched)
990
+ changed = true;
991
+ }
992
+ return changed;
993
+ }
994
+ function createShadowProjectionContext(resolved, operations) {
995
+ if (resolved.kind !== 'prefab-stage')
996
+ return createIdentityShadowProjectionContext();
997
+ return {
998
+ resolveProjectionId: targetId => operations.resolvePrefabStageProjectionNodeId?.(targetId) ?? targetId,
999
+ };
1000
+ }
1001
+ function createIdentityShadowProjectionContext() {
1002
+ return {
1003
+ resolveProjectionId: targetId => targetId,
1004
+ };
1005
+ }
1006
+ function resolveShadowTarget(capabilityId, state, input, operations) {
1007
+ if (state.mode !== 'editor' || !state.session) {
1008
+ return {
1009
+ ok: false,
1010
+ result: createLocalEditorAgentBridgeFailure(capabilityId, 'Editor is not in edit mode.', { code: 'editor.notReady' }),
1011
+ };
1012
+ }
1013
+ const sessionState = state.session.getState({ cloneDocuments: false });
1014
+ const document = asEditorSceneDocument(sessionState.workingDocument);
1015
+ const objectId = normalizeAgentBridgeString(input.objectId);
1016
+ if (objectId) {
1017
+ if (!document) {
1018
+ return {
1019
+ ok: false,
1020
+ result: createLocalEditorAgentBridgeFailure(capabilityId, 'Shadow capabilities require an editor scene document.', {
1021
+ code: 'shadow.unsupportedDocument',
1022
+ details: { objectId },
1023
+ }),
1024
+ };
1025
+ }
1026
+ const gameObject = findShadowGameObject(document, objectId);
1027
+ if (!gameObject) {
1028
+ return {
1029
+ ok: false,
1030
+ result: createLocalEditorAgentBridgeFailure(capabilityId, `Shadow target object not found: ${objectId}`, {
1031
+ code: 'shadow.targetNotFound',
1032
+ objectId,
1033
+ }),
1034
+ };
1035
+ }
1036
+ return {
1037
+ ok: true,
1038
+ target: {
1039
+ kind: 'scene',
1040
+ target: { objectId },
1041
+ document,
1042
+ rawDocument: sessionState.workingDocument,
1043
+ objectId,
1044
+ gameObject,
1045
+ },
1046
+ };
1047
+ }
1048
+ const details = operations.getPrefabStageDetails();
1049
+ if (details) {
1050
+ const prefabTarget = resolvePrefabShadowTargetFromDetails(details, input);
1051
+ if (prefabTarget)
1052
+ return { ok: true, target: prefabTarget };
1053
+ }
1054
+ const activeId = normalizeAgentBridgeString(sessionState.selection.activeId);
1055
+ if (activeId && document) {
1056
+ const gameObject = findShadowGameObject(document, activeId);
1057
+ if (gameObject) {
1058
+ return {
1059
+ ok: true,
1060
+ target: {
1061
+ kind: 'scene',
1062
+ target: { objectId: activeId },
1063
+ document,
1064
+ rawDocument: sessionState.workingDocument,
1065
+ objectId: activeId,
1066
+ gameObject,
1067
+ },
1068
+ };
1069
+ }
1070
+ }
1071
+ return {
1072
+ ok: false,
1073
+ result: createLocalEditorAgentBridgeFailure(capabilityId, 'Shadow target is required. Provide objectId, or open a Prefab stage and provide nodeId/assetId.', {
1074
+ code: 'shadow.targetRequired',
1075
+ details: { objectId: input.objectId, nodeId: input.nodeId, assetId: 'assetId' in input ? input.assetId : undefined },
1076
+ }),
1077
+ };
1078
+ }
1079
+ function resolvePrefabShadowTargetFromDetails(details, input) {
1080
+ const requestedAssetId = 'assetId' in input ? normalizeAgentBridgeString(input.assetId) : '';
1081
+ if (requestedAssetId && requestedAssetId !== details.stage.assetId && requestedAssetId !== details.stage.browserAssetId)
1082
+ return null;
1083
+ const nodes = listPrefabShadowNodes(details);
1084
+ const nodeId = normalizePrefabNodeId(input.nodeId)
1085
+ || getSelectedPrefabNodeId(details.stage.selectedItemId)
1086
+ || findPrefabRootNodeId(details);
1087
+ const node = nodes.find(candidate => candidate.id === nodeId) ?? null;
1088
+ if (!node)
1089
+ return null;
1090
+ const document = createPrefabStageShadowDocument(details, nodes);
1091
+ return {
1092
+ kind: 'prefab-stage',
1093
+ target: { assetId: details.stage.assetId, nodeId: node.id },
1094
+ details,
1095
+ nodeId: node.id,
1096
+ node,
1097
+ document,
1098
+ };
1099
+ }
1100
+ function createPrefabStageShadowDocument(details, nodes) {
1101
+ return {
1102
+ version: 1,
1103
+ schemaVersion: 1,
1104
+ assets: [],
1105
+ scene: {
1106
+ gameObjects: nodes.map((node) => ({
1107
+ id: node.id,
1108
+ name: node.label,
1109
+ parentId: node.parentId ?? undefined,
1110
+ active: readBoolean(node.defaults?.active, true),
1111
+ kind: node.kind === 'primitive' ? 'primitive' : 'transform',
1112
+ ...(node.defaults?.shadowMode ? { shadowMode: node.defaults.shadowMode } : {}),
1113
+ ...(node.defaults?.shadow ? { shadow: structuredClone(node.defaults.shadow) } : {}),
1114
+ ...(node.primitive ? { primitive: structuredClone(node.primitive) } : {}),
1115
+ ...(node.light ? { light: structuredClone(node.light) } : {}),
1116
+ components: [],
1117
+ })),
1118
+ },
1119
+ metadata: {
1120
+ prefabStageAssetId: details.stage.assetId,
1121
+ },
1122
+ };
1123
+ }
1124
+ function listPrefabShadowNodes(details) {
1125
+ const nodes = [];
1126
+ const visit = (item, parentId) => {
1127
+ const nodeId = normalizePrefabNodeId(item?.nodeId ?? item?.id);
1128
+ const isNode = item?.itemType === 'prefab-node' || !!item?.nodeId || String(item?.id ?? '').startsWith(PREFAB_STAGE_ITEM_PREFIX);
1129
+ const currentParent = isNode && nodeId ? nodeId : parentId;
1130
+ if (isNode && nodeId) {
1131
+ nodes.push({
1132
+ id: nodeId,
1133
+ label: typeof item.label === 'string' ? item.label : nodeId,
1134
+ kind: typeof item.kind === 'string' ? item.kind : 'group',
1135
+ parentId,
1136
+ ...(isRecord(item.defaults) ? { defaults: structuredClone(item.defaults) } : {}),
1137
+ ...(isRecord(item.primitive) ? { primitive: structuredClone(item.primitive) } : {}),
1138
+ ...(isRecord(item.light) ? { light: structuredClone(item.light) } : {}),
1139
+ });
1140
+ }
1141
+ for (const child of Array.isArray(item?.children) ? item.children : [])
1142
+ visit(child, currentParent);
1143
+ };
1144
+ for (const item of details.structureItems)
1145
+ visit(item, null);
1146
+ return nodes;
1147
+ }
1148
+ function createShadowPolicyFieldPatches(policy) {
1149
+ const record = (policy ?? {});
1150
+ return SHADOW_POLICY_FIELDS.map(path => ({
1151
+ path,
1152
+ value: readShadowPolicyFieldValue(record, path) ?? null,
1153
+ }));
1154
+ }
1155
+ function readShadowPolicyFieldValue(policy, path) {
1156
+ if (path === 'shadow.cast')
1157
+ return policy.cast;
1158
+ if (path === 'shadow.receive')
1159
+ return policy.receive;
1160
+ if (path === 'shadow.mode')
1161
+ return policy.mode;
1162
+ if (path === 'shadow.quality')
1163
+ return policy.quality;
1164
+ if (path === 'shadow.light.mode')
1165
+ return policy.light?.mode;
1166
+ if (path === 'shadow.light.lightId')
1167
+ return policy.light?.lightId;
1168
+ const param = path.slice('shadow.params.'.length);
1169
+ return policy.params?.[param];
1170
+ }
1171
+ function normalizeShadowPolicy(value) {
1172
+ if (!isRecord(value))
1173
+ return { ok: false, message: 'shadow policy must be an object.' };
1174
+ if (Object.keys(value).length === 0)
1175
+ return { ok: true, settings: undefined };
1176
+ const settings = readEditorShadowSettings(value);
1177
+ if (!settings)
1178
+ return { ok: false, message: 'shadow policy did not contain any valid Shadow V2 fields.' };
1179
+ return { ok: true, settings };
1180
+ }
1181
+ function readPrefabNodeShadowPolicy(node) {
1182
+ return readEditorShadowSettingsWithLegacy({
1183
+ shadow: node.defaults?.shadow,
1184
+ shadowMode: node.defaults?.shadowMode,
1185
+ }).shadow;
1186
+ }
1187
+ function createRenderingActionDiagnosticDetails(result) {
1188
+ return {
1189
+ ok: result.ok,
1190
+ changed: result.changed,
1191
+ rendered: result.rendered,
1192
+ ...(result.status ? { status: result.status } : {}),
1193
+ ...(result.statusTone ? { statusTone: result.statusTone } : {}),
1194
+ ...(result.statusDetails ? { statusDetails: result.statusDetails } : {}),
1195
+ ...(isRecord(result.details) ? { actionDetails: result.details } : {}),
1196
+ ...(result.error ? { error: result.error } : {}),
1197
+ };
1198
+ }
1199
+ function createStaticBakeDiagnostic(result, targetConfirmed, sourceNodeIds) {
1200
+ if (result.ok === true && result.changed === true && targetConfirmed) {
1201
+ return {
1202
+ severity: 'info',
1203
+ source: 'editor',
1204
+ code: 'shadow.staticBakeCompleted',
1205
+ message: 'Static shadow bake rendering action completed and included the requested caster.',
1206
+ details: createRenderingActionDiagnosticDetails(result),
1207
+ };
1208
+ }
1209
+ if (result.ok === true && result.changed === true && sourceNodeIds !== null) {
1210
+ return {
1211
+ severity: 'warning',
1212
+ source: 'editor',
1213
+ code: 'shadow.staticBakeTargetNotFound',
1214
+ message: 'Static shadow bake produced an artifact, but the requested caster was not included in the baked source nodes.',
1215
+ details: createRenderingActionDiagnosticDetails(result),
1216
+ };
1217
+ }
1218
+ if (result.ok === true && result.changed === true) {
1219
+ return {
1220
+ severity: 'warning',
1221
+ source: 'editor',
1222
+ code: 'shadow.staticBakeTargetUnknown',
1223
+ message: 'Static shadow bake produced an artifact, but the rendering action did not report target source nodes.',
1224
+ details: createRenderingActionDiagnosticDetails(result),
1225
+ };
1226
+ }
1227
+ return {
1228
+ severity: 'warning',
1229
+ source: 'editor',
1230
+ code: 'shadow.staticBakeNoChange',
1231
+ message: result.ok === false
1232
+ ? 'Static shadow bake rendering action did not complete successfully.'
1233
+ : 'Static shadow bake rendering action completed without producing a changed artifact.',
1234
+ details: createRenderingActionDiagnosticDetails(result),
1235
+ };
1236
+ }
1237
+ function readRenderingActionStaticBakeSourceNodeIds(result) {
1238
+ if (!isRecord(result.details))
1239
+ return null;
1240
+ const details = result.details;
1241
+ if (!Object.prototype.hasOwnProperty.call(details, 'sourceNodeIds'))
1242
+ return null;
1243
+ return normalizeAgentBridgeIdList(readRenderingActionStringList(details.sourceNodeIds));
1244
+ }
1245
+ function readRenderingActionStringList(value) {
1246
+ return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
1247
+ }
1248
+ function getResolvedTargetShadowPolicy(target) {
1249
+ if (target.kind === 'scene') {
1250
+ return resolveEditorSceneGameObjectShadowSettings(target.document, target.gameObject).settings;
1251
+ }
1252
+ return readPrefabNodeShadowPolicy(target.node);
1253
+ }
1254
+ function getResolvedTargetAuthoredPolicy(target) {
1255
+ return target.kind === 'scene'
1256
+ ? readEditorShadowSettings(target.gameObject.shadow)
1257
+ : readPrefabNodeShadowPolicy(target.node);
1258
+ }
1259
+ function createShadowDebugRuntimeEvidence(plan, receivers, shadowPreviewDebugInfo, casterIds) {
1260
+ const diagnostics = [];
1261
+ if (plan.backend === 'none') {
1262
+ diagnostics.push({
1263
+ severity: 'info',
1264
+ source: 'editor',
1265
+ code: 'shadow.runtimeBackendNone',
1266
+ message: 'Resolved backend is none, so no runtime shadow primitive is expected.',
1267
+ });
1268
+ }
1269
+ if (plan.backend !== 'none' && receivers.length === 0) {
1270
+ diagnostics.push({
1271
+ severity: 'warning',
1272
+ source: 'editor',
1273
+ code: 'shadow.runtimeNoReceivers',
1274
+ message: 'Resolved shadow backend requires receivers, but no receiver candidates are available.',
1275
+ });
1276
+ }
1277
+ if (plan.backend === 'static-baked') {
1278
+ diagnostics.push({
1279
+ severity: 'warning',
1280
+ source: 'editor',
1281
+ code: 'shadow.staticArtifactEvidenceUnavailable',
1282
+ message: 'Static-baked shadow visibility requires a baked artifact; this editor bridge session does not expose artifact presence evidence to shadow.debug.visibilityMeasure.',
1283
+ });
1284
+ }
1285
+ return {
1286
+ backend: plan.backend,
1287
+ renderableShadowPrimitiveCount: plan.backend === 'none' || plan.backend === 'static-baked'
1288
+ ? 0
1289
+ : receivers.filter(receiver => receiver.active !== false && receiver.visible !== false).length,
1290
+ casterRuntimeObjectCount: plan.backend === 'none' ? 0 : 1,
1291
+ receiverRuntimeObjectCount: receivers.length,
1292
+ ...createPlanarShadowRuntimeEvidence(shadowPreviewDebugInfo, casterIds),
1293
+ ...(plan.stale === true ? { artifactStale: true } : {}),
1294
+ ...(diagnostics.length ? { diagnostics } : {}),
1295
+ };
1296
+ }
1297
+ function createPlanarShadowRuntimeEvidence(shadowPreviewDebugInfo, casterIds) {
1298
+ const planar = shadowPreviewDebugInfo?.planar;
1299
+ if (!planar)
1300
+ return {};
1301
+ const matchingCasters = planar.casters.filter(caster => isPlanarShadowCasterEvidenceForTarget(collectPlanarShadowCasterSourceNodeIds(caster), casterIds));
1302
+ const casters = matchingCasters;
1303
+ if (casters.length === 0)
1304
+ return {};
1305
+ const fallbackReasons = uniqueStrings(casters.flatMap(caster => caster.fallbackReasons ?? []));
1306
+ const alphaCutoutChannels = uniqueStrings(casters.flatMap(caster => caster.alphaCutoutChannels ?? []))
1307
+ .filter((channel) => channel === 'alpha' || channel === 'luminance' || channel === 'red');
1308
+ const alphaCutoutUvSets = uniqueNumbers(casters.flatMap(caster => caster.alphaCutoutUvSets ?? []));
1309
+ const alphaCutoutLevels = uniqueNumbers(casters.flatMap(caster => caster.alphaCutoutLevels ?? []));
1310
+ const strategy = summarizePlanarShadowDebugStrategy(casters);
1311
+ return {
1312
+ planar: {
1313
+ ...(strategy ? { strategy } : {}),
1314
+ sourceMeshCount: casters.length,
1315
+ projectedMeshCount: casters.reduce((sum, caster) => sum + caster.projectedMeshCount, 0),
1316
+ convexHullMeshCount: casters.reduce((sum, caster) => sum + caster.convexHullMeshCount, 0),
1317
+ alphaCutoutMeshCount: casters.reduce((sum, caster) => sum + caster.alphaCutoutMeshCount, 0),
1318
+ ...(alphaCutoutChannels.length ? { alphaCutoutChannels } : {}),
1319
+ ...(alphaCutoutUvSets.length ? { alphaCutoutUvSets } : {}),
1320
+ ...(alphaCutoutLevels.length ? { alphaCutoutLevels } : {}),
1321
+ ...(fallbackReasons.length ? { fallbackReasons } : {}),
1322
+ casters: casters.map(caster => ({
1323
+ sourceName: caster.sourceName,
1324
+ ...(caster.sourceNodeId ? { sourceNodeId: caster.sourceNodeId } : {}),
1325
+ ...(caster.sourceNodeIds?.length ? { sourceNodeIds: [...caster.sourceNodeIds] } : {}),
1326
+ ...(caster.sourceMeshNames?.length ? { sourceMeshNames: [...caster.sourceMeshNames] } : {}),
1327
+ shadowName: caster.shadowName,
1328
+ strategy: caster.strategy,
1329
+ hasSkeleton: caster.hasSkeleton,
1330
+ projectedMeshCount: caster.projectedMeshCount,
1331
+ convexHullMeshCount: caster.convexHullMeshCount,
1332
+ alphaCutoutMeshCount: caster.alphaCutoutMeshCount,
1333
+ ...(caster.alphaCutoutChannels?.length ? { alphaCutoutChannels: [...caster.alphaCutoutChannels] } : {}),
1334
+ ...(caster.fallbackReasons?.length ? { fallbackReasons: [...caster.fallbackReasons] } : {}),
1335
+ })),
1336
+ },
1337
+ };
1338
+ }
1339
+ function createShadowRuntimeEvidenceCasterIds(resolved, casterId, projectionContext) {
1340
+ const authoringIds = new Set([casterId]);
1341
+ addShadowRuntimeEvidenceSceneDescendants(authoringIds, resolved.document, casterId);
1342
+ const ids = new Set();
1343
+ for (const id of authoringIds) {
1344
+ ids.add(id);
1345
+ ids.add(projectionContext.resolveProjectionId(id));
1346
+ }
1347
+ return ids;
1348
+ }
1349
+ function addShadowRuntimeEvidenceSceneDescendants(ids, document, parentId) {
1350
+ for (const gameObject of document.scene.gameObjects) {
1351
+ const candidateParentId = readShadowSceneGameObjectParentId(gameObject);
1352
+ if (candidateParentId !== parentId || ids.has(gameObject.id))
1353
+ continue;
1354
+ ids.add(gameObject.id);
1355
+ addShadowRuntimeEvidenceSceneDescendants(ids, document, gameObject.id);
1356
+ }
1357
+ }
1358
+ function readShadowSceneGameObjectParentId(gameObject) {
1359
+ const parentId = gameObject.parentId;
1360
+ return typeof parentId === 'string' && parentId.length > 0 ? parentId : null;
1361
+ }
1362
+ function collectPlanarShadowCasterSourceNodeIds(caster) {
1363
+ return uniqueStrings([
1364
+ ...(caster.sourceNodeId ? [caster.sourceNodeId] : []),
1365
+ ...(caster.sourceNodeIds ?? []),
1366
+ ]);
1367
+ }
1368
+ function isPlanarShadowCasterEvidenceForTarget(sourceNodeIds, casterIds) {
1369
+ for (const sourceNodeId of sourceNodeIds) {
1370
+ if (casterIds.has(sourceNodeId))
1371
+ return true;
1372
+ for (const casterId of casterIds) {
1373
+ if (sourceNodeId.startsWith(`${casterId}::`))
1374
+ return true;
1375
+ }
1376
+ }
1377
+ return false;
1378
+ }
1379
+ function summarizePlanarShadowDebugStrategy(casters) {
1380
+ if (casters.length === 0)
1381
+ return undefined;
1382
+ const hasProjected = casters.some(caster => caster.projectedMeshCount > 0);
1383
+ const hasHull = casters.some(caster => caster.convexHullMeshCount > 0);
1384
+ if (hasProjected && hasHull)
1385
+ return 'auto';
1386
+ if (hasProjected)
1387
+ return 'projected-mesh';
1388
+ if (hasHull)
1389
+ return 'convex-hull';
1390
+ return undefined;
1391
+ }
1392
+ function uniqueStrings(values) {
1393
+ return [...new Set(values.filter(value => value.length > 0))];
1394
+ }
1395
+ function uniqueNumbers(values) {
1396
+ return [...new Set(values.filter(value => Number.isFinite(value)))];
1397
+ }
1398
+ function mapShadowPlan(plan) {
1399
+ return {
1400
+ casterId: plan.casterId,
1401
+ receiverIds: [...plan.receiverIds],
1402
+ ...(plan.lightId ? { lightId: plan.lightId } : {}),
1403
+ backend: plan.backend,
1404
+ mode: plan.mode,
1405
+ quality: plan.quality,
1406
+ params: { ...plan.params },
1407
+ ...(plan.stale === true ? { stale: true } : {}),
1408
+ diagnostics: mapShadowDiagnostics(plan.diagnostics),
1409
+ };
1410
+ }
1411
+ function mapShadowReceivers(receivers, state, context = {}) {
1412
+ const projectionContext = context.projectionContext ?? createIdentityShadowProjectionContext();
1413
+ const casterBounds = context.casterId
1414
+ ? readShadowProjectionBounds(state, context.casterId, projectionContext)
1415
+ : undefined;
1416
+ return receivers.map((receiver) => {
1417
+ const bounds = readShadowProjectionBounds(state, receiver.receiverId, projectionContext);
1418
+ const diagnostics = mapShadowDiagnostics(receiver.diagnostics ?? []);
1419
+ if (!bounds) {
1420
+ diagnostics.push({
1421
+ severity: 'warning',
1422
+ source: 'editor',
1423
+ code: 'shadow.receiverBoundsUnavailable',
1424
+ message: `Projection bounds are unavailable for receiver "${receiver.receiverId}".`,
1425
+ details: { receiverId: receiver.receiverId },
1426
+ });
1427
+ }
1428
+ const authoredActive = receiver.active !== false;
1429
+ const authoredVisible = authoredActive && receiver.visible !== false;
1430
+ const effectiveVisible = readShadowPreviewEffectiveVisible(state, receiver.receiverId, projectionContext, authoredVisible);
1431
+ const suitability = createShadowReceiverSuitability(receiver, casterBounds, bounds, context.lightId);
1432
+ return {
1433
+ receiverId: receiver.receiverId,
1434
+ source: receiver.source,
1435
+ score: receiver.score,
1436
+ ...(bounds ? { bounds, boundsCenter: bounds.center } : {}),
1437
+ active: authoredActive,
1438
+ visible: effectiveVisible,
1439
+ ...(receiver.receive ? { receive: receiver.receive } : {}),
1440
+ ...(suitability ? { suitability } : {}),
1441
+ ...(diagnostics.length ? { diagnostics } : {}),
1442
+ };
1443
+ });
1444
+ }
1445
+ function createShadowReceiverSuitability(receiver, casterBounds, receiverBounds, lightId) {
1446
+ const reasons = [...(receiver.suitability?.reasons ?? [])];
1447
+ if (receiverBounds)
1448
+ reasons.push('receiver bounds available');
1449
+ else
1450
+ reasons.push('receiver bounds unavailable');
1451
+ if (casterBounds)
1452
+ reasons.push('caster bounds available');
1453
+ if (lightId)
1454
+ reasons.push(`light ${lightId}`);
1455
+ const distance = casterBounds && receiverBounds ? distance3(casterBounds.center, receiverBounds.center) : undefined;
1456
+ const overlap = casterBounds && receiverBounds ? overlapRatioXZ(casterBounds, receiverBounds) : undefined;
1457
+ return {
1458
+ score: receiver.suitability?.score ?? receiver.score,
1459
+ ...(overlap !== undefined ? { overlap } : {}),
1460
+ ...(distance !== undefined ? { distance } : {}),
1461
+ ...(receiver.suitability?.material ? { material: receiver.suitability.material } : {}),
1462
+ ...(lightId ? { light: lightId } : receiver.suitability?.light ? { light: receiver.suitability.light } : {}),
1463
+ reasons,
1464
+ };
1465
+ }
1466
+ function createShadowDebugTargetSummary(target, state, projectionContext = createIdentityShadowProjectionContext()) {
1467
+ const id = getResolvedTargetCasterId(target);
1468
+ const projectionId = projectionContext.resolveProjectionId(id);
1469
+ const bounds = readShadowProjectionBounds(state, id, projectionContext);
1470
+ const transform = editorTransformSnapshotToAgentTransform(state.projection?.readNodeTransform(projectionId));
1471
+ if (target.kind === 'scene') {
1472
+ const active = target.gameObject.active !== false;
1473
+ return {
1474
+ objectId: target.objectId,
1475
+ label: target.gameObject.name ?? target.objectId,
1476
+ kind: target.gameObject.kind ?? 'transform',
1477
+ active,
1478
+ visible: readShadowPreviewEffectiveVisible(state, id, projectionContext, active),
1479
+ ...(bounds ? { bounds } : {}),
1480
+ ...(transform ? { transform } : {}),
1481
+ ...(!bounds ? {
1482
+ diagnostics: [{
1483
+ severity: 'warning',
1484
+ source: 'editor',
1485
+ code: 'shadow.casterBoundsUnavailable',
1486
+ message: `Projection bounds are unavailable for caster "${target.objectId}".`,
1487
+ }],
1488
+ } : {}),
1489
+ };
1490
+ }
1491
+ return {
1492
+ nodeId: target.nodeId,
1493
+ label: target.node.label,
1494
+ kind: target.node.kind,
1495
+ active: readBoolean(target.node.defaults?.active, true),
1496
+ visible: readShadowPreviewEffectiveVisible(state, id, projectionContext, readBoolean(target.node.defaults?.active, true)),
1497
+ ...(bounds ? { bounds } : {}),
1498
+ ...(transform ? { transform } : {}),
1499
+ ...(!bounds ? {
1500
+ diagnostics: [{
1501
+ severity: 'warning',
1502
+ source: 'editor',
1503
+ code: 'shadow.casterBoundsUnavailable',
1504
+ message: `Projection bounds are unavailable for prefab node "${target.nodeId}".`,
1505
+ }],
1506
+ } : {}),
1507
+ };
1508
+ }
1509
+ function createShadowLightSummary(document, lightId) {
1510
+ if (!lightId)
1511
+ return undefined;
1512
+ const light = findShadowGameObject(document, lightId);
1513
+ if (!light?.light) {
1514
+ return {
1515
+ lightId,
1516
+ diagnostics: [{
1517
+ severity: 'warning',
1518
+ source: 'editor',
1519
+ code: 'shadow.lightNotFound',
1520
+ message: `Resolved shadow light "${lightId}" was not found in the preview document.`,
1521
+ }],
1522
+ };
1523
+ }
1524
+ const diagnostics = [];
1525
+ let direction;
1526
+ let directionSource;
1527
+ const orientationDiagnostics = [];
1528
+ if (light.light.type === 'directional') {
1529
+ direction = normalizeEditorSceneLightDirectionVector(light.light.direction);
1530
+ directionSource = 'light.direction';
1531
+ const transform = findEditorSceneTransform(light);
1532
+ const rotation = transform && 'rotation' in transform ? transform.rotation : undefined;
1533
+ const drift = detectEditorSceneDirectionalLightOrientationDrift({
1534
+ direction: light.light.direction,
1535
+ rotation,
1536
+ });
1537
+ if (drift.hasDrift) {
1538
+ orientationDiagnostics.push({
1539
+ severity: 'warning',
1540
+ source: 'editor',
1541
+ code: 'shadow.lightOrientationDrift',
1542
+ message: 'Directional Light transform.rotation and light.direction are out of sync. Runtime shadows use light.direction until the light orientation is edited again.',
1543
+ details: {
1544
+ expectedDirectionFromTransform: cloneShadowVec3Json(drift.expectedDirection),
1545
+ actualDirection: cloneShadowVec3Json(drift.actualDirection),
1546
+ delta: drift.delta,
1547
+ tolerance: drift.tolerance,
1548
+ },
1549
+ });
1550
+ diagnostics.push(...orientationDiagnostics);
1551
+ }
1552
+ }
1553
+ return {
1554
+ lightId,
1555
+ label: light.name ?? light.id,
1556
+ type: light.light.type,
1557
+ ...(light.shadow?.light?.mode ? { mode: light.shadow.light.mode } : {}),
1558
+ ...(direction ? { direction } : {}),
1559
+ ...(directionSource ? { directionSource } : {}),
1560
+ ...(orientationDiagnostics.length ? { orientationDiagnostics } : {}),
1561
+ ...(typeof light.light.intensity === 'number' ? { intensity: light.light.intensity } : {}),
1562
+ ...(diagnostics.length ? { diagnostics } : {}),
1563
+ };
1564
+ }
1565
+ function cloneShadowVec3(value) {
1566
+ return { x: value.x, y: value.y, z: value.z };
1567
+ }
1568
+ function cloneShadowVec3Json(value) {
1569
+ return { x: value.x, y: value.y, z: value.z };
1570
+ }
1571
+ function createShadowFootprintSummary(plan, receivers, state, projectionContext = createIdentityShadowProjectionContext(), light) {
1572
+ if (plan.backend === 'none' || plan.receiverIds.length === 0) {
1573
+ return {
1574
+ kind: 'none',
1575
+ confidence: plan.backend === 'none' ? 1 : 0,
1576
+ diagnostics: plan.backend === 'none'
1577
+ ? [{
1578
+ severity: 'info',
1579
+ source: 'editor',
1580
+ code: 'shadow.footprintNone',
1581
+ message: 'Shadow backend is none, so no footprint is expected.',
1582
+ }]
1583
+ : [{
1584
+ severity: 'warning',
1585
+ source: 'editor',
1586
+ code: 'shadow.receiverNotFound',
1587
+ message: 'No receiver is available for an estimated shadow footprint.',
1588
+ }],
1589
+ };
1590
+ }
1591
+ const receiver = selectShadowFootprintReceiver(plan, receivers);
1592
+ if (!receiver) {
1593
+ return {
1594
+ kind: 'unknown',
1595
+ receiverId: plan.receiverIds[0],
1596
+ confidence: 0.1,
1597
+ diagnostics: [{
1598
+ severity: 'warning',
1599
+ source: 'editor',
1600
+ code: 'shadow.footprintReceiverUnavailable',
1601
+ message: 'Resolved shadow plan has receiver ids, but no receiver summaries are available for footprint selection.',
1602
+ details: { receiverIds: plan.receiverIds },
1603
+ }],
1604
+ };
1605
+ }
1606
+ const receiverBounds = receiver?.bounds;
1607
+ const casterBounds = readShadowProjectionBounds(state, plan.casterId, projectionContext);
1608
+ if (!receiverBounds || !casterBounds) {
1609
+ return {
1610
+ kind: 'unknown',
1611
+ receiverId: receiver?.receiverId ?? plan.receiverIds[0],
1612
+ confidence: 0.25,
1613
+ diagnostics: [{
1614
+ severity: 'warning',
1615
+ source: 'editor',
1616
+ code: 'shadow.footprintBoundsUnavailable',
1617
+ message: 'Caster or receiver bounds are unavailable, so the footprint can only be reported structurally.',
1618
+ }],
1619
+ };
1620
+ }
1621
+ const footprintHeight = 0.02;
1622
+ const direction = normalizeShadowDirection(light?.direction);
1623
+ const projectedBounds = direction
1624
+ ? projectCasterBoundsToReceiver(casterBounds, receiverBounds, direction)
1625
+ : null;
1626
+ const size = projectedBounds
1627
+ ? {
1628
+ x: Math.min(receiverBounds.size.x, Math.max(projectedBounds.size.x, 0.01)),
1629
+ y: footprintHeight,
1630
+ z: Math.min(receiverBounds.size.z, Math.max(projectedBounds.size.z, 0.01)),
1631
+ }
1632
+ : {
1633
+ x: Math.min(receiverBounds.size.x, Math.max(casterBounds.size.x, 0.01)),
1634
+ y: footprintHeight,
1635
+ z: Math.min(receiverBounds.size.z, Math.max(casterBounds.size.z, 0.01)),
1636
+ };
1637
+ const center = projectedBounds?.center ?? casterBounds.center;
1638
+ const contactTolerance = Math.max(0.025, casterBounds.size.y * 0.04);
1639
+ const contactsReceiver = Math.abs(casterBounds.min.y - receiverBounds.max.y) <= contactTolerance
1640
+ || casterBounds.min.y < receiverBounds.max.y;
1641
+ const diagnostics = [
1642
+ ...(!direction && light?.type === 'directional' ? [{
1643
+ severity: 'warning',
1644
+ source: 'editor',
1645
+ code: 'shadow.footprintDirectionUnavailable',
1646
+ message: 'Directional shadow light is missing a direction, so the footprint falls back to caster bounds.',
1647
+ details: { lightId: light.lightId },
1648
+ }] : []),
1649
+ ...(contactsReceiver ? [{
1650
+ severity: 'info',
1651
+ source: 'editor',
1652
+ code: 'shadow.casterContactsReceiver',
1653
+ message: 'Caster bounds touch or intersect the receiver plane. A real screenshot may show only the outside portions of the shadow because the caster itself occludes the contact footprint.',
1654
+ details: {
1655
+ casterMinY: casterBounds.min.y,
1656
+ receiverMaxY: receiverBounds.max.y,
1657
+ contactTolerance,
1658
+ },
1659
+ }] : []),
1660
+ ];
1661
+ return {
1662
+ kind: plan.backend === 'static-baked' ? 'artifact' : 'estimated',
1663
+ receiverId: receiver.receiverId,
1664
+ center: {
1665
+ x: center.x,
1666
+ y: receiverBounds.max.y + footprintHeight / 2 + 0.002,
1667
+ z: center.z,
1668
+ },
1669
+ size,
1670
+ normal: { x: 0, y: 1, z: 0 },
1671
+ ...(direction ? { direction } : {}),
1672
+ area: Math.max(0, size.x) * Math.max(0, size.z),
1673
+ confidence: receiver.suitability?.overlap !== undefined ? Math.min(1, Math.max(0.35, receiver.suitability.overlap)) : 0.6,
1674
+ ...(diagnostics.length ? { diagnostics } : {}),
1675
+ };
1676
+ }
1677
+ function selectShadowFootprintReceiver(plan, receivers) {
1678
+ const planOrder = new Map(plan.receiverIds.map((receiverId, index) => [receiverId, index]));
1679
+ const candidates = receivers.filter(receiver => planOrder.has(receiver.receiverId));
1680
+ const ranked = candidates.length > 0 ? candidates : receivers;
1681
+ return [...ranked].sort((left, right) => compareShadowReceiverForFootprint(left, right, planOrder))[0];
1682
+ }
1683
+ function compareShadowReceiverForFootprint(left, right, planOrder) {
1684
+ const leftVisible = left.active !== false && left.visible !== false ? 1 : 0;
1685
+ const rightVisible = right.active !== false && right.visible !== false ? 1 : 0;
1686
+ if (leftVisible !== rightVisible)
1687
+ return rightVisible - leftVisible;
1688
+ const leftHasBounds = left.bounds ? 1 : 0;
1689
+ const rightHasBounds = right.bounds ? 1 : 0;
1690
+ if (leftHasBounds !== rightHasBounds)
1691
+ return rightHasBounds - leftHasBounds;
1692
+ const leftOverlap = typeof left.suitability?.overlap === 'number' ? left.suitability.overlap : -1;
1693
+ const rightOverlap = typeof right.suitability?.overlap === 'number' ? right.suitability.overlap : -1;
1694
+ if (leftOverlap !== rightOverlap)
1695
+ return rightOverlap - leftOverlap;
1696
+ const leftDistance = typeof left.suitability?.distance === 'number' ? left.suitability.distance : Number.POSITIVE_INFINITY;
1697
+ const rightDistance = typeof right.suitability?.distance === 'number' ? right.suitability.distance : Number.POSITIVE_INFINITY;
1698
+ if (leftDistance !== rightDistance)
1699
+ return leftDistance - rightDistance;
1700
+ const leftScore = typeof left.suitability?.score === 'number' ? left.suitability.score : left.score ?? 0;
1701
+ const rightScore = typeof right.suitability?.score === 'number' ? right.suitability.score : right.score ?? 0;
1702
+ if (leftScore !== rightScore)
1703
+ return rightScore - leftScore;
1704
+ const leftOrder = planOrder.get(left.receiverId) ?? Number.MAX_SAFE_INTEGER;
1705
+ const rightOrder = planOrder.get(right.receiverId) ?? Number.MAX_SAFE_INTEGER;
1706
+ return leftOrder - rightOrder;
1707
+ }
1708
+ function normalizeShadowDirection(direction) {
1709
+ if (!direction)
1710
+ return null;
1711
+ const length = Math.hypot(direction.x, direction.y, direction.z);
1712
+ if (!Number.isFinite(length) || length <= 1e-6)
1713
+ return null;
1714
+ return {
1715
+ x: direction.x / length,
1716
+ y: direction.y / length,
1717
+ z: direction.z / length,
1718
+ };
1719
+ }
1720
+ function projectCasterBoundsToReceiver(casterBounds, receiverBounds, direction) {
1721
+ if (Math.abs(direction.y) <= 1e-5)
1722
+ return null;
1723
+ const receiverY = receiverBounds.max.y;
1724
+ const points = [];
1725
+ for (const x of [casterBounds.min.x, casterBounds.max.x]) {
1726
+ for (const y of [casterBounds.min.y, casterBounds.max.y]) {
1727
+ for (const z of [casterBounds.min.z, casterBounds.max.z]) {
1728
+ const t = (receiverY - y) / direction.y;
1729
+ if (!Number.isFinite(t))
1730
+ continue;
1731
+ if (t < 0) {
1732
+ points.push({ x, y: receiverY, z });
1733
+ continue;
1734
+ }
1735
+ points.push({
1736
+ x: x + direction.x * t,
1737
+ y: receiverY,
1738
+ z: z + direction.z * t,
1739
+ });
1740
+ }
1741
+ }
1742
+ }
1743
+ if (points.length === 0)
1744
+ return null;
1745
+ const min = {
1746
+ x: Math.min(...points.map(point => point.x)),
1747
+ y: receiverY,
1748
+ z: Math.min(...points.map(point => point.z)),
1749
+ };
1750
+ const max = {
1751
+ x: Math.max(...points.map(point => point.x)),
1752
+ y: receiverY,
1753
+ z: Math.max(...points.map(point => point.z)),
1754
+ };
1755
+ return {
1756
+ center: {
1757
+ x: (min.x + max.x) / 2,
1758
+ y: receiverY,
1759
+ z: (min.z + max.z) / 2,
1760
+ },
1761
+ size: {
1762
+ x: Math.max(0, max.x - min.x),
1763
+ y: 0,
1764
+ z: Math.max(0, max.z - min.z),
1765
+ },
1766
+ };
1767
+ }
1768
+ function readShadowProjectionBounds(state, targetId, projectionContext) {
1769
+ const projectionId = projectionContext.resolveProjectionId(targetId);
1770
+ return createAgentBridgeBounds(state.projection?.getSelectionBounds([projectionId]) ?? null);
1771
+ }
1772
+ function readShadowPreviewEffectiveVisible(state, targetId, projectionContext, authoredVisible) {
1773
+ const projectionId = projectionContext.resolveProjectionId(targetId);
1774
+ const projectionEntry = state.projection?.getPreviewVisibilityOverrides?.()
1775
+ ?.find(entry => entry.nodeId === projectionId || entry.nodeId === targetId);
1776
+ if (projectionEntry)
1777
+ return projectionEntry.effectiveVisible;
1778
+ const overrides = state.previewVisibility?.overrides ?? {};
1779
+ const override = overrides[projectionId] ?? overrides[targetId];
1780
+ return authoredVisible && override !== false;
1781
+ }
1782
+ function createAgentBridgeBounds(bounds) {
1783
+ if (!bounds)
1784
+ return undefined;
1785
+ const half = {
1786
+ x: bounds.size.x / 2,
1787
+ y: bounds.size.y / 2,
1788
+ z: bounds.size.z / 2,
1789
+ };
1790
+ return {
1791
+ center: { ...bounds.center },
1792
+ size: { ...bounds.size },
1793
+ min: {
1794
+ x: bounds.center.x - half.x,
1795
+ y: bounds.center.y - half.y,
1796
+ z: bounds.center.z - half.z,
1797
+ },
1798
+ max: {
1799
+ x: bounds.center.x + half.x,
1800
+ y: bounds.center.y + half.y,
1801
+ z: bounds.center.z + half.z,
1802
+ },
1803
+ };
1804
+ }
1805
+ function distance3(a, b) {
1806
+ return Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z);
1807
+ }
1808
+ function overlapRatioXZ(a, b) {
1809
+ const overlapX = Math.max(0, Math.min(a.max.x, b.max.x) - Math.max(a.min.x, b.min.x));
1810
+ const overlapZ = Math.max(0, Math.min(a.max.z, b.max.z) - Math.max(a.min.z, b.min.z));
1811
+ const intersection = overlapX * overlapZ;
1812
+ const casterArea = Math.max(0.0001, a.size.x * a.size.z);
1813
+ return Math.max(0, Math.min(1, intersection / casterArea));
1814
+ }
1815
+ function mapShadowDiagnostics(diagnostics) {
1816
+ return diagnostics.map(diagnostic => ({
1817
+ severity: diagnostic.severity,
1818
+ source: 'editor',
1819
+ code: diagnostic.code,
1820
+ message: diagnostic.message,
1821
+ ...(diagnostic.casterId ? { objectId: diagnostic.casterId } : {}),
1822
+ details: {
1823
+ ...(diagnostic.details ?? {}),
1824
+ ...(diagnostic.casterId ? { casterId: diagnostic.casterId } : {}),
1825
+ ...(diagnostic.receiverId ? { receiverId: diagnostic.receiverId } : {}),
1826
+ ...(diagnostic.lightId ? { lightId: diagnostic.lightId } : {}),
1827
+ },
1828
+ }));
1829
+ }
1830
+ function createShadowTargetDiagnostics(resolved) {
1831
+ if (resolved.kind !== 'prefab-stage')
1832
+ return [];
1833
+ return [{
1834
+ severity: 'info',
1835
+ source: 'editor',
1836
+ code: 'shadow.prefabStagePreview',
1837
+ message: 'Prefab stage shadow resolution uses editable prefab nodes as a preview scene; runtime scene receiver/light binding is finalized by the scene compiler.',
1838
+ details: { assetId: resolved.details.stage.assetId, nodeId: resolved.nodeId },
1839
+ }];
1840
+ }
1841
+ function getResolvedTargetCasterId(target) {
1842
+ return target.kind === 'scene' ? target.objectId : target.nodeId;
1843
+ }
1844
+ function asEditorSceneDocument(value) {
1845
+ if (!isRecord(value))
1846
+ return null;
1847
+ const scene = value.scene;
1848
+ if (!isRecord(scene) || !Array.isArray(scene.gameObjects))
1849
+ return null;
1850
+ if (!Array.isArray(value.assets))
1851
+ return null;
1852
+ return value;
1853
+ }
1854
+ function findShadowGameObject(document, objectId) {
1855
+ return document.scene.gameObjects.find(gameObject => gameObject.id === objectId) ?? null;
1856
+ }
1857
+ function findPrefabRootNodeId(details) {
1858
+ const nodes = listPrefabShadowNodes(details);
1859
+ return nodes.find(node => node.kind === 'root')?.id
1860
+ ?? nodes.find(node => !node.parentId)?.id
1861
+ ?? 'prefab-root';
1862
+ }
1863
+ function normalizePrefabNodeId(value) {
1864
+ const id = normalizeAgentBridgeString(value);
1865
+ return id.startsWith(PREFAB_STAGE_ITEM_PREFIX) ? id.slice(PREFAB_STAGE_ITEM_PREFIX.length) : id;
1866
+ }
1867
+ function getSelectedPrefabNodeId(itemId) {
1868
+ return normalizePrefabNodeId(itemId);
1869
+ }
1870
+ function readBoolean(value, fallback) {
1871
+ return typeof value === 'boolean' ? value : fallback;
1872
+ }
1873
+ function isRecord(value) {
1874
+ return !!value && typeof value === 'object' && !Array.isArray(value);
1875
+ }
1876
+ //# sourceMappingURL=shadows.js.map