@fps-games/editor 0.1.4-beta.4 → 0.1.5-beta.1

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 (288) hide show
  1. package/dist/build-info.json +45 -0
  2. package/dist/local-editor-harness.d.ts +25 -5
  3. package/dist/local-editor-harness.d.ts.map +1 -1
  4. package/dist/local-editor-harness.js +518 -90
  5. package/dist/local-editor-harness.js.map +1 -1
  6. package/dist/local-editor-performance-stats.d.ts +12 -0
  7. package/dist/local-editor-performance-stats.d.ts.map +1 -0
  8. package/dist/local-editor-performance-stats.js +46 -0
  9. package/dist/local-editor-performance-stats.js.map +1 -0
  10. package/dist/playable-babylon-facade.d.ts +4 -4
  11. package/dist/playable-babylon-facade.d.ts.map +1 -1
  12. package/dist/playable-babylon-facade.js +2 -2
  13. package/dist/playable-babylon-facade.js.map +1 -1
  14. package/dist/playable-babylon-rendering.d.ts +66 -9
  15. package/dist/playable-babylon-rendering.d.ts.map +1 -1
  16. package/dist/playable-babylon-rendering.js +567 -13
  17. package/dist/playable-babylon-rendering.js.map +1 -1
  18. package/dist/playable-local-editor-host.d.ts +12 -9
  19. package/dist/playable-local-editor-host.d.ts.map +1 -1
  20. package/dist/playable-local-editor-host.js.map +1 -1
  21. package/dist/playable-sdk-vite.d.ts +2 -0
  22. package/dist/playable-sdk-vite.d.ts.map +1 -0
  23. package/dist/playable-sdk-vite.js +2 -0
  24. package/dist/playable-sdk-vite.js.map +1 -0
  25. package/dist/playable-sdk.d.ts +6 -4
  26. package/dist/playable-sdk.d.ts.map +1 -1
  27. package/dist/playable-sdk.js +3 -2
  28. package/dist/playable-sdk.js.map +1 -1
  29. package/dist/static-shadow-cpu-worker.d.ts +7 -0
  30. package/dist/static-shadow-cpu-worker.d.ts.map +1 -0
  31. package/dist/static-shadow-cpu-worker.js +221 -0
  32. package/dist/static-shadow-cpu-worker.js.map +1 -0
  33. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts +5 -0
  34. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts.map +1 -1
  35. package/node_modules/@fps-games/babylon-renderer/dist/index.js +5 -0
  36. package/node_modules/@fps-games/babylon-renderer/dist/index.js.map +1 -1
  37. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.d.ts +5 -0
  38. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.d.ts.map +1 -0
  39. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.js +46 -0
  40. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.js.map +1 -0
  41. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.d.ts +5 -0
  42. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.d.ts.map +1 -0
  43. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js +398 -0
  44. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js.map +1 -0
  45. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts +4 -0
  46. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -0
  47. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +584 -0
  48. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -0
  49. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts +61 -0
  50. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts.map +1 -0
  51. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js +382 -0
  52. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js.map +1 -0
  53. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts +47 -0
  54. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts.map +1 -0
  55. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js +285 -0
  56. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js.map +1 -0
  57. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts +88 -0
  58. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts.map +1 -0
  59. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +813 -0
  60. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -0
  61. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts +27 -0
  62. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts.map +1 -0
  63. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js +220 -0
  64. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js.map +1 -0
  65. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts +38 -0
  66. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts.map +1 -0
  67. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js +173 -0
  68. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js.map +1 -0
  69. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +286 -0
  70. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
  71. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +82 -0
  72. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
  73. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  74. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +3 -0
  75. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
  76. package/node_modules/@fps-games/editor-babylon/dist/index.js +3 -0
  77. package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
  78. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts +34 -0
  79. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts.map +1 -0
  80. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js +272 -0
  81. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js.map +1 -0
  82. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts +49 -0
  83. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts.map +1 -0
  84. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js +141 -0
  85. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js.map +1 -0
  86. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +11 -0
  87. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  88. package/node_modules/@fps-games/editor-babylon/dist/projection.js +137 -6
  89. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  90. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts +19 -0
  91. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts.map +1 -0
  92. package/node_modules/@fps-games/editor-babylon/dist/rendering.js +66 -0
  93. package/node_modules/@fps-games/editor-babylon/dist/rendering.js.map +1 -0
  94. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +17 -3
  95. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
  96. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +256 -8
  97. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
  98. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
  99. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +19 -2
  100. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
  101. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  102. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +1 -1
  103. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  104. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  105. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts +8 -0
  106. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts.map +1 -0
  107. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js +14 -0
  108. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js.map +1 -0
  109. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  110. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +10 -2
  111. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  112. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  113. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  114. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +17 -0
  115. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  116. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  117. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +494 -43
  118. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  119. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +72 -5
  120. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  121. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
  122. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  123. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +595 -5
  124. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  125. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  126. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +14 -1
  127. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
  128. package/node_modules/@fps-games/editor-core/dist/editor-session.js +34 -10
  129. package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
  130. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts +2 -1
  131. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts.map +1 -1
  132. package/node_modules/@fps-games/editor-core/dist/inspector.js +11 -1
  133. package/node_modules/@fps-games/editor-core/dist/inspector.js.map +1 -1
  134. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts +7 -0
  135. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts.map +1 -1
  136. package/node_modules/@fps-games/editor-core/dist/serialized-object.js +1 -0
  137. package/node_modules/@fps-games/editor-core/dist/serialized-object.js.map +1 -1
  138. package/node_modules/@fps-games/editor-core/package.json +2 -2
  139. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  140. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  141. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +10 -5
  142. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  143. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
  144. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +3 -1
  145. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
  146. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +4 -1
  147. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  148. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +29 -0
  149. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  150. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +12 -0
  151. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  152. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts +1 -1
  153. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts.map +1 -1
  154. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js +1 -1
  155. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js.map +1 -1
  156. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  157. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +5 -1
  158. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  159. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts +1 -0
  160. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts.map +1 -1
  161. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js +8 -0
  162. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js.map +1 -1
  163. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +1 -0
  164. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
  165. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +1 -0
  166. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
  167. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +34 -2
  168. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
  169. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +272 -0
  170. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
  171. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
  172. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
  173. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
  174. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
  175. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts.map +1 -1
  176. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js +0 -4
  177. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js.map +1 -1
  178. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts +12 -1
  179. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  180. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +161 -1
  181. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  182. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts +4 -2
  183. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts.map +1 -1
  184. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js +2 -1
  185. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js.map +1 -1
  186. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
  187. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
  188. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
  189. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts +19 -0
  190. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts.map +1 -0
  191. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js +57 -0
  192. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js.map +1 -0
  193. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts +7 -1
  194. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts.map +1 -1
  195. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.d.ts +1 -1
  196. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.d.ts.map +1 -1
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.js +5 -0
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.js.map +1 -1
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +1003 -7
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts +12 -3
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts.map +1 -1
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js +521 -6
  205. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js.map +1 -1
  206. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts +217 -3
  207. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts.map +1 -1
  208. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  209. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +26 -0
  210. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  211. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +3 -1
  212. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  213. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
  214. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +4 -0
  215. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
  216. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts +9 -1
  217. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts.map +1 -1
  218. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js +12 -1
  219. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js.map +1 -1
  220. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +2 -0
  221. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
  222. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
  223. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  224. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +75 -0
  225. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  226. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts +1 -0
  227. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts.map +1 -1
  228. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js +1 -0
  229. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js.map +1 -1
  230. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts +17 -0
  231. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -0
  232. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +262 -0
  233. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -0
  234. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
  235. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -3
  236. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
  237. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts +6 -0
  238. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts.map +1 -1
  239. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js +31 -0
  240. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js.map +1 -1
  241. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts +2 -1
  242. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts.map +1 -1
  243. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js +1 -1
  244. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js.map +1 -1
  245. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.d.ts.map +1 -1
  246. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js +21 -9
  247. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js.map +1 -1
  248. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +151 -0
  249. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -0
  250. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +445 -0
  251. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -0
  252. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts +2 -0
  253. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts.map +1 -0
  254. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js +2 -0
  255. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js.map +1 -0
  256. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.d.ts +1 -1
  257. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.d.ts.map +1 -1
  258. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.js +1 -1
  259. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.js.map +1 -1
  260. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.d.ts +2 -1
  261. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.d.ts.map +1 -1
  262. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js +37 -0
  263. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js.map +1 -1
  264. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/types.d.ts +15 -0
  265. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/types.d.ts.map +1 -1
  266. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.d.ts +36 -0
  267. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.d.ts.map +1 -0
  268. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.js +65 -0
  269. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.js.map +1 -0
  270. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.d.ts +4 -0
  271. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.d.ts.map +1 -0
  272. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.js +87 -0
  273. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.js.map +1 -0
  274. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts +5 -0
  275. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts.map +1 -0
  276. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js +5 -0
  277. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js.map +1 -0
  278. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts +8 -0
  279. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts.map +1 -0
  280. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js +226 -0
  281. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js.map +1 -0
  282. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts +64 -0
  283. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts.map +1 -0
  284. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js +2 -0
  285. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js.map +1 -0
  286. package/node_modules/@fps-games/editor-playable-sdk/package.json +7 -3
  287. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  288. package/package.json +12 -8
@@ -1,12 +1,18 @@
1
1
  import { createEditorSession, createInspectorRegistry, DEFAULT_EDITOR_TRANSFORM_OPERATION_SETTINGS, DEFAULT_EDITOR_VIEWPORT_TOOL_STATE, createEmptyEditorViewportSpatialOverlayState, cloneEditorViewportToolState, cloneEditorViewportSpatialOverlayState, aggregateInspectorObjectsToMultiObject, createInspectorEditPayload, compareInspectorSections, computeEditorTransformActionTargets, mergeInspectorSections, normalizeEditorTransformConstraint, resolveEditorSelectionCommand, serializedMultiObjectToInspectorObject, serializedObjectToInspectorObject, validateSceneGraphDelete, validateSceneGraphDrop, validateSceneGraphGroupSelection, validateSceneGraphMove, validateSceneGraphRename, } from '@fps-games/editor-core';
2
2
  import { createLocalEditorBrowserUi, toTransformOperationPolicyStatusLabel, } from '@fps-games/editor-browser';
3
3
  import { createBabylonEnvironmentTextureController, createBabylonDefaultPostProcessPipelineController, } from '@fps-games/babylon-renderer';
4
- import { createBabylonEditorProjection, createBabylonEditorWorld, createBabylonProjectionSelectionController, createBabylonSceneCameraPreviewController, createBabylonSceneViewCameraController, createBabylonSceneViewInputController, createBabylonSceneViewMeasurementController, createBabylonSceneViewSpatialOverlayController, createBabylonEditorShadowPreviewController, createBabylonTransformGizmoController, focusEditorViewportSelection, } from '@fps-games/editor-babylon';
4
+ import { createBabylonEditorProjection, createBabylonEditorWorld, createBabylonProjectionSelectionController, createBabylonSceneCameraPreviewController, createBabylonSceneViewCameraController, createBabylonSceneViewInputController, createBabylonSceneViewMeasurementController, createBabylonSceneViewSpatialOverlayController, createBabylonEditorShadowPreviewController, createBabylonTransformGizmoController, createBabylonEditorPerformanceMonitor, focusEditorViewportSelection, } from '@fps-games/editor-babylon';
5
5
  import { createLocalEditorSceneRenderScheduler, } from './local-editor-scene-render-scheduler.js';
6
6
  import { createPlayableBabylonOutlineInspectorSection, createPlayableBabylonOutlineInspectorSeedPatchValue, isPlayableBabylonOutlineInspectorPatchPath, } from './playable-babylon-outline-inspector.js';
7
7
  import { createLocalEditorViewportRenderCoordinator, } from './local-editor-viewport-render-coordinator.js';
8
8
  import { createLocalEditorSceneViewInteractionRuntime, } from './local-editor-scene-view-interaction-runtime.js';
9
+ import { cloneLocalEditorPerformanceStats, countLocalEditorAuthoredObjects, createLocalEditorPerformanceStats, LOCAL_EDITOR_PERFORMANCE_MONITOR_REASON, } from './local-editor-performance-stats.js';
9
10
  const BATCH_EDIT_REQUIRES_MULTI_PATCH_REASON = 'Batch edit requires multi-property patch support.';
11
+ const LARGE_SELECTION_THRESHOLD = 200;
12
+ const LARGE_SHADOW_MODE_BATCH_THRESHOLD = 200;
13
+ const EDITOR_PROJECTION_IDLE_BEFORE_RUN_GAME_TIMEOUT_MS = 1500;
14
+ const EDITOR_WORLD_DISPOSE_BOUNDARY_DELAY_MS = 500;
15
+ const RENDERING_ACTION_PROGRESS_MIN_VISIBLE_MS = 1000;
10
16
  export function createLocalEditorHarness(options) {
11
17
  const root = options.root ?? document.body;
12
18
  const state = {
@@ -29,6 +35,7 @@ export function createLocalEditorHarness(options) {
29
35
  environmentTexture: null,
30
36
  postProcess: null,
31
37
  projectionShadowPreviewRebuildFrame: null,
38
+ projectionShadowPreviewRefreshFrame: null,
32
39
  gizmo: null,
33
40
  sceneCameraPreview: null,
34
41
  sceneCameraPreviewEnabled: false,
@@ -41,6 +48,10 @@ export function createLocalEditorHarness(options) {
41
48
  sceneRenderScheduler: null,
42
49
  viewportRenderCoordinator: null,
43
50
  sceneFrameStats: null,
51
+ performanceMonitor: null,
52
+ performanceMonitorOpen: false,
53
+ performanceObjectCount: null,
54
+ performanceStats: null,
44
55
  worldAppearanceKey: '',
45
56
  worldRenderingKey: '',
46
57
  boxSelection: null,
@@ -59,6 +70,7 @@ export function createLocalEditorHarness(options) {
59
70
  statusTone: 'default',
60
71
  statusToneStatus: 'Game running',
61
72
  statusDetails: '',
73
+ renderingAction: null,
62
74
  summary: '',
63
75
  };
64
76
  let harness;
@@ -178,10 +190,11 @@ export function createLocalEditorHarness(options) {
178
190
  : undefined,
179
191
  onRenderingAction: options.documentAdapter.onRenderingAction
180
192
  ? (input) => {
181
- void applyRenderingAction(state, options, input)
193
+ return applyRenderingAction(state, options, input, harness.render)
182
194
  .then((changed) => {
183
195
  if (changed)
184
196
  harness.render();
197
+ return changed;
185
198
  });
186
199
  }
187
200
  : undefined,
@@ -282,6 +295,10 @@ export function createLocalEditorHarness(options) {
282
295
  if (setGridVisible(state, visible))
283
296
  harness.render();
284
297
  },
298
+ onPerformanceMonitorOpenChange: (open) => {
299
+ setLocalEditorPerformanceMonitorOpen(state, open);
300
+ updateLocalEditorPerformanceStats(state, stats => ui.updatePerformanceStats?.(stats));
301
+ },
285
302
  onFocusSelection: () => {
286
303
  if (focusSelectedProjection(state))
287
304
  harness.render();
@@ -298,7 +315,9 @@ export function createLocalEditorHarness(options) {
298
315
  });
299
316
  const runGameFromEditor = async (reason) => {
300
317
  cancelActiveOperation(state);
318
+ await waitForEditorProjectionIdleBeforeRunGame(state);
301
319
  disposeEditorWorld(state);
320
+ await waitForEditorWorldDisposeBoundary();
302
321
  state.mode = 'game';
303
322
  state.session = null;
304
323
  state.source = null;
@@ -404,7 +423,7 @@ export function createLocalEditorHarness(options) {
404
423
  ui.updatePreview(previewState);
405
424
  else
406
425
  ui.update(createUiState(state, options));
407
- }, stats => ui.updateSceneFrameStats?.(stats));
426
+ }, stats => ui.updateSceneFrameStats?.(stats), stats => ui.updatePerformanceStats?.(stats));
408
427
  state.mode = 'editor';
409
428
  state.summary = loadedSource?.summary ?? summarizeDocument(options, preparedDocument, source);
410
429
  state.status = `GameWorld disposed; EditorWorld active; assets=${assets.length}`;
@@ -784,7 +803,7 @@ function validateTransformActionSelection(state, action) {
784
803
  ? { ok: true }
785
804
  : { ok: false, message: 'Distribute needs at least 3 selected objects' };
786
805
  }
787
- async function createEditorWorld(state, options, renderUi, renderPreviewUi, updateSceneFrameStats) {
806
+ async function createEditorWorld(state, options, renderUi, renderPreviewUi, updateSceneFrameStats, updatePerformanceStats) {
788
807
  disposeEditorWorld(state);
789
808
  const render = (reason = 'editor-world-update') => {
790
809
  renderUi();
@@ -814,6 +833,7 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
814
833
  useRightHandedSystem: options.world?.useRightHandedSystem,
815
834
  enableDefaultCameraControls: false,
816
835
  });
836
+ const performanceMonitor = createBabylonEditorPerformanceMonitor(world.scene);
817
837
  const sceneRenderScheduler = createLocalEditorSceneRenderScheduler((frame) => {
818
838
  state.sceneViewInteraction?.updateFrame(frame);
819
839
  world.render();
@@ -821,6 +841,7 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
821
841
  onStatsChange(stats) {
822
842
  state.sceneFrameStats = stats;
823
843
  updateSceneFrameStats(stats);
844
+ updateLocalEditorPerformanceStats(state, updatePerformanceStats);
824
845
  },
825
846
  });
826
847
  const viewportRenderCoordinator = createLocalEditorViewportRenderCoordinator({
@@ -845,6 +866,7 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
845
866
  scene: world.scene,
846
867
  importModel: options.worldAdapter.importProjectionModel,
847
868
  resolveTextureUrl: options.worldAdapter.resolveMaterialTextureUrl,
869
+ selectionEdgesPrewarm: options.world?.selectionEdgesPrewarm,
848
870
  logger: console,
849
871
  onProjectionReady(event) {
850
872
  syncCurrentSelectionToSceneArtifacts(state, `projection-${event.nodeId}-ready-selection`);
@@ -1075,6 +1097,9 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
1075
1097
  scene: world.scene,
1076
1098
  projection,
1077
1099
  options: initialRendering.shadowPreview,
1100
+ onStaticProjectedShadowTextureReady(event) {
1101
+ viewportRenderCoordinator.invalidateScene(`static-shadow-texture-ready-${event.chunkId}`);
1102
+ },
1078
1103
  });
1079
1104
  const environmentTexture = createBabylonEnvironmentTextureController(world.scene, initialRendering.environment ?? null);
1080
1105
  const postProcess = createBabylonDefaultPostProcessPipelineController(world.scene, [world.camera], initialRendering.postProcess ?? null, { name: 'editorDefaultPostProcessPipeline' });
@@ -1101,11 +1126,14 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
1101
1126
  state.sceneRenderScheduler = sceneRenderScheduler;
1102
1127
  state.viewportRenderCoordinator = viewportRenderCoordinator;
1103
1128
  state.sceneFrameStats = sceneRenderScheduler.getStats();
1129
+ state.performanceMonitor = performanceMonitor;
1130
+ updateLocalEditorPerformanceStats(state, updatePerformanceStats);
1104
1131
  state.worldAppearanceKey = initialAppearanceKey;
1105
1132
  state.worldRenderingKey = initialRenderingKey;
1106
1133
  state.resizeHandler = resize;
1107
1134
  if (document) {
1108
1135
  projection.projectNodes(options.documentAdapter.getProjectionNodes(document));
1136
+ scheduleProjectionShadowPreviewRebuild(state, 'editor-world-initial-projection-shadow');
1109
1137
  }
1110
1138
  syncCurrentSelectionToSceneArtifacts(state, 'editor-world-initial-selection');
1111
1139
  viewportRenderCoordinator.requestFrame('editor-world-created');
@@ -1131,6 +1159,14 @@ function disposeEditorWorld(state) {
1131
1159
  state.sceneViewInput = null;
1132
1160
  state.selectionController?.dispose();
1133
1161
  state.selectionController = null;
1162
+ if (state.performanceMonitorOpen) {
1163
+ state.viewportRenderCoordinator?.endContinuous(LOCAL_EDITOR_PERFORMANCE_MONITOR_REASON);
1164
+ }
1165
+ state.performanceMonitorOpen = false;
1166
+ state.performanceMonitor?.dispose();
1167
+ state.performanceMonitor = null;
1168
+ state.performanceStats = null;
1169
+ state.performanceObjectCount = null;
1134
1170
  state.viewportRenderCoordinator?.dispose();
1135
1171
  state.viewportRenderCoordinator = null;
1136
1172
  state.sceneRenderScheduler?.dispose();
@@ -1149,6 +1185,10 @@ function disposeEditorWorld(state) {
1149
1185
  window.cancelAnimationFrame(state.projectionShadowPreviewRebuildFrame);
1150
1186
  state.projectionShadowPreviewRebuildFrame = null;
1151
1187
  }
1188
+ if (state.projectionShadowPreviewRefreshFrame !== null) {
1189
+ window.cancelAnimationFrame(state.projectionShadowPreviewRefreshFrame);
1190
+ state.projectionShadowPreviewRefreshFrame = null;
1191
+ }
1152
1192
  state.shadowPreview?.dispose();
1153
1193
  state.shadowPreview = null;
1154
1194
  state.environmentTexture?.dispose();
@@ -1166,6 +1206,63 @@ function disposeEditorWorld(state) {
1166
1206
  state.world = null;
1167
1207
  state.engine = null;
1168
1208
  }
1209
+ async function waitForEditorProjectionIdleBeforeRunGame(state) {
1210
+ const projection = state.projection;
1211
+ if (!projection)
1212
+ return;
1213
+ const timeout = createTimeoutPromise(EDITOR_PROJECTION_IDLE_BEFORE_RUN_GAME_TIMEOUT_MS);
1214
+ try {
1215
+ await Promise.race([
1216
+ projection.waitForIdle().catch(() => null),
1217
+ timeout.promise,
1218
+ ]);
1219
+ }
1220
+ finally {
1221
+ timeout.cancel();
1222
+ }
1223
+ }
1224
+ async function waitForEditorWorldDisposeBoundary() {
1225
+ await waitForEditorAnimationFrame();
1226
+ await waitForEditorAnimationFrame();
1227
+ await waitForEditorTimeout(EDITOR_WORLD_DISPOSE_BOUNDARY_DELAY_MS);
1228
+ }
1229
+ function waitForEditorAnimationFrame() {
1230
+ if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function') {
1231
+ return Promise.resolve();
1232
+ }
1233
+ return new Promise(resolve => {
1234
+ window.requestAnimationFrame(() => resolve());
1235
+ });
1236
+ }
1237
+ function waitForEditorTimeout(milliseconds) {
1238
+ if (typeof window === 'undefined' || typeof window.setTimeout !== 'function') {
1239
+ return Promise.resolve();
1240
+ }
1241
+ return new Promise(resolve => {
1242
+ window.setTimeout(() => resolve(), milliseconds);
1243
+ });
1244
+ }
1245
+ function createTimeoutPromise(milliseconds) {
1246
+ if (typeof window === 'undefined' || typeof window.setTimeout !== 'function') {
1247
+ return { promise: new Promise(() => undefined), cancel: () => undefined };
1248
+ }
1249
+ let timeoutId = null;
1250
+ const promise = new Promise(resolve => {
1251
+ timeoutId = window.setTimeout(() => {
1252
+ timeoutId = null;
1253
+ resolve();
1254
+ }, milliseconds);
1255
+ });
1256
+ return {
1257
+ promise,
1258
+ cancel() {
1259
+ if (timeoutId === null)
1260
+ return;
1261
+ window.clearTimeout(timeoutId);
1262
+ timeoutId = null;
1263
+ },
1264
+ };
1265
+ }
1169
1266
  function requestEditorSceneFrame(state, reason) {
1170
1267
  state.viewportRenderCoordinator?.requestFrame(reason);
1171
1268
  }
@@ -1203,6 +1300,21 @@ function scheduleProjectionShadowPreviewRebuild(state, reason) {
1203
1300
  state.viewportRenderCoordinator?.invalidateScene(reason);
1204
1301
  });
1205
1302
  }
1303
+ function scheduleProjectionShadowPreviewRefresh(state, reason) {
1304
+ if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function') {
1305
+ state.shadowPreview?.refresh();
1306
+ state.viewportRenderCoordinator?.invalidateScene(reason);
1307
+ return;
1308
+ }
1309
+ if (state.projectionShadowPreviewRefreshFrame !== null) {
1310
+ window.cancelAnimationFrame(state.projectionShadowPreviewRefreshFrame);
1311
+ }
1312
+ state.projectionShadowPreviewRefreshFrame = window.requestAnimationFrame(() => {
1313
+ state.projectionShadowPreviewRefreshFrame = null;
1314
+ state.shadowPreview?.refresh();
1315
+ state.viewportRenderCoordinator?.invalidateScene(reason);
1316
+ });
1317
+ }
1206
1318
  async function runExclusive(state, render, action) {
1207
1319
  if (state.busy)
1208
1320
  return;
@@ -1228,7 +1340,7 @@ function selectItem(state, options, input, renderUi) {
1228
1340
  return false;
1229
1341
  if (!isDocumentNodeSelectable(state, options, input.id))
1230
1342
  return false;
1231
- const selection = state.session?.getState().selection ?? { selectedIds: [], activeId: null };
1343
+ const selection = state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null };
1232
1344
  const command = resolveEditorSelectionCommand({
1233
1345
  selection,
1234
1346
  targetIds: [input.id],
@@ -1328,7 +1440,7 @@ function handleContextAction(state, options, action) {
1328
1440
  return runHierarchyCustomContextAction(state, options, action);
1329
1441
  if (action.action === 'focus') {
1330
1442
  const activeId = action.activeId ?? action.targetIds[action.targetIds.length - 1] ?? null;
1331
- const selectionChanged = activeId && !state.session?.getState().selection.selectedIds.includes(activeId)
1443
+ const selectionChanged = activeId && !state.session?.getState({ cloneDocuments: false }).selection.selectedIds.includes(activeId)
1332
1444
  ? dispatchSelectionCommand(state, options, {
1333
1445
  type: 'selection.replace',
1334
1446
  selectedIds: [activeId],
@@ -1571,15 +1683,13 @@ function duplicateSceneGraphNodes(state, options, intent) {
1571
1683
  state.status = 'Duplicate rejected';
1572
1684
  return true;
1573
1685
  }
1686
+ const projectionImpact = resolveProjectionImpact(patch, createDuplicateProjectionImpact(patch));
1574
1687
  const result = state.session.dispatch({
1575
1688
  type: 'document.patch',
1576
1689
  label: patch.label ?? `Duplicate ${targetIds.length} object(s)`,
1577
1690
  patch: patch.patch,
1578
1691
  targetId: patch.activeId ?? patch.createdIds[patch.createdIds.length - 1] ?? undefined,
1579
- ...withProjectionImpact(resolveProjectionImpact(patch, createCreatedReprojectProjectionImpact({
1580
- createdNodeIds: patch.createdIds,
1581
- reprojectIds: patch.reprojectIds,
1582
- }))),
1692
+ ...withProjectionImpact(projectionImpact),
1583
1693
  });
1584
1694
  if (!result.documentChanged) {
1585
1695
  state.status = 'Duplicate unchanged';
@@ -1597,11 +1707,14 @@ function duplicateSceneGraphNodes(state, options, intent) {
1597
1707
  label: 'Select Duplicated Nodes',
1598
1708
  }).selection
1599
1709
  : sanitizeSelection(state, options, result.workingDocument, result.selection) ?? result.selection;
1600
- rebuildProjectionFromDocument(state, options, result.workingDocument, selection);
1601
- if (patch.reprojectIds?.length)
1602
- reprojectProjectionForChangedIds(state, options, result.workingDocument, patch.reprojectIds);
1603
- else
1604
- syncProjectionForChangedIds(state, options, result.workingDocument, patch.changedIds ?? createdIds);
1710
+ if (!applyProjectionImpactToDocument(state, options, {
1711
+ document: result.workingDocument,
1712
+ selection,
1713
+ impact: projectionImpact,
1714
+ reason: 'duplicate-impact',
1715
+ })) {
1716
+ rebuildProjectionFromDocument(state, options, result.workingDocument, selection);
1717
+ }
1605
1718
  state.summary = summarizeDocument(options, result.workingDocument, state.session.getSource());
1606
1719
  state.status = patch.label ?? `Duplicated ${createdIds.length} object(s)`;
1607
1720
  return true;
@@ -1765,7 +1878,7 @@ function commitEditorStateChange(state, renderUi, reason, mutate, options = {})
1765
1878
  renderUi();
1766
1879
  if (options.syncSelectionArtifacts) {
1767
1880
  const selection = typeof options.syncSelectionArtifacts === 'boolean'
1768
- ? state.session?.getState().selection ?? { selectedIds: [], activeId: null }
1881
+ ? state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null }
1769
1882
  : options.syncSelectionArtifacts;
1770
1883
  syncSelectionToProjection(state, selection, reason, revision);
1771
1884
  }
@@ -1785,7 +1898,7 @@ function syncSelectionToProjection(state, selection, reason = 'projection-select
1785
1898
  syncTransformGizmoToSceneArtifacts(state, reason, revision, false);
1786
1899
  }
1787
1900
  function syncCurrentSelectionToSceneArtifacts(state, reason = 'projection-selection-current', revision = state.editorStateRevision) {
1788
- syncSelectionToProjection(state, state.session?.getState().selection ?? { selectedIds: [], activeId: null }, reason, revision);
1901
+ syncSelectionToProjection(state, state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null }, reason, revision);
1789
1902
  }
1790
1903
  function syncTransformGizmoToSceneArtifacts(state, reason, revision = state.editorStateRevision, beginSync = true) {
1791
1904
  if (beginSync && !beginSceneArtifactSync(state, reason, revision))
@@ -2237,7 +2350,8 @@ function patchSerializedProperty(state, options, input) {
2237
2350
  cancelActiveOperation(state);
2238
2351
  if (!state.session)
2239
2352
  return false;
2240
- const document = state.session.getState().workingDocument;
2353
+ const sessionState = state.session.getState({ cloneDocuments: false });
2354
+ const document = sessionState.workingDocument;
2241
2355
  const targetIds = input.targetIds && input.targetIds.length > 0 ? input.targetIds : [input.targetId];
2242
2356
  const transaction = createInspectorEditTransaction(state, options, document, input, targetIds);
2243
2357
  if (!transaction.ok) {
@@ -2250,7 +2364,7 @@ function patchSerializedProperty(state, options, input) {
2250
2364
  const patch = options.documentAdapter.createSerializedMultiPropertyPatch?.({
2251
2365
  document,
2252
2366
  targetIds,
2253
- activeId: state.session.getState().selection.activeId,
2367
+ activeId: sessionState.selection.activeId,
2254
2368
  path: payload.path,
2255
2369
  value: payload.value,
2256
2370
  control: payload.control,
@@ -2262,11 +2376,15 @@ function patchSerializedProperty(state, options, input) {
2262
2376
  if (!patch)
2263
2377
  return false;
2264
2378
  const changedIds = patch.changedIds ?? targetIds;
2379
+ const projectionMetadataPatch = isSerializedProjectionMetadataPath(payload.path);
2380
+ const largeProjectionMetadataPatch = projectionMetadataPatch
2381
+ && changedIds.length >= LARGE_SHADOW_MODE_BATCH_THRESHOLD;
2382
+ const invalidateStaticShadowArtifact = projectionMetadataPatch && payload.path === 'shadowMode';
2265
2383
  const result = state.session.dispatch({
2266
2384
  type: 'document.patch',
2267
2385
  label: patch.label ?? `Patch ${payload.path} on ${targetIds.length} objects`,
2268
2386
  patch: patch.patch,
2269
- targetId: state.session.getState().selection.activeId ?? undefined,
2387
+ targetId: sessionState.selection.activeId ?? undefined,
2270
2388
  ...withProjectionImpact(resolveProjectionImpact(patch, patch.reprojectIds?.length
2271
2389
  ? createReprojectProjectionImpact(patch.reprojectIds)
2272
2390
  : shouldReprojectInspectorEdit
@@ -2274,7 +2392,14 @@ function patchSerializedProperty(state, options, input) {
2274
2392
  : isSerializedTransformPath(payload.path)
2275
2393
  ? createTransformProjectionImpact(targetIds)
2276
2394
  : undefined)),
2277
- });
2395
+ }, largeProjectionMetadataPatch
2396
+ ? {
2397
+ assumeDocumentChanged: true,
2398
+ assumeDirty: true,
2399
+ clonePatchInput: false,
2400
+ cloneResultDocument: false,
2401
+ }
2402
+ : undefined);
2278
2403
  if (!result.documentChanged)
2279
2404
  return false;
2280
2405
  const projectionSyncIds = isSerializedTransformPath(payload.path) ? targetIds : changedIds;
@@ -2283,6 +2408,12 @@ function patchSerializedProperty(state, options, input) {
2283
2408
  reprojectProjectionForChangedIds(state, options, workingDocument, patch.reprojectIds);
2284
2409
  else if (shouldReprojectInspectorEdit)
2285
2410
  reprojectProjectionForChangedIds(state, options, workingDocument, changedIds);
2411
+ else if (isSerializedProjectionMetadataPath(payload.path)) {
2412
+ syncProjectionMetadataForChangedIds(state, options, workingDocument, projectionSyncIds, {
2413
+ deferShadowPreviewRefresh: largeProjectionMetadataPatch,
2414
+ invalidateStaticShadowArtifact,
2415
+ });
2416
+ }
2286
2417
  else
2287
2418
  syncProjectionForChangedIds(state, options, workingDocument, projectionSyncIds);
2288
2419
  state.summary = summarizeDocument(options, workingDocument, state.session.getSource());
@@ -2320,6 +2451,11 @@ function patchSerializedProperty(state, options, input) {
2320
2451
  else if (shouldReprojectInspectorEdit) {
2321
2452
  reprojectProjectionForChangedIds(state, options, result.workingDocument, patch.changedIds ?? [patch.changedId ?? payload.targetId]);
2322
2453
  }
2454
+ else if (isSerializedProjectionMetadataPath(payload.path)) {
2455
+ syncProjectionMetadataForChangedIds(state, options, result.workingDocument, [patch.changedId ?? payload.targetId], {
2456
+ invalidateStaticShadowArtifact: payload.path === 'shadowMode',
2457
+ });
2458
+ }
2323
2459
  else if (isSerializedTransformPath(payload.path))
2324
2460
  syncProjectionForChangedIds(state, options, result.workingDocument, [patch.changedId ?? payload.targetId]);
2325
2461
  else if (patch.changedIds)
@@ -2361,13 +2497,26 @@ async function applyRenderingPropertyChange(state, options, input) {
2361
2497
  source: input.source,
2362
2498
  });
2363
2499
  const resultObject = typeof result === 'object' && result != null ? result : null;
2364
- const changed = result === true || resultObject?.changed === true || resultObject?.refreshWorldRendering === true;
2500
+ const documentPatchResult = resultObject?.documentPatch
2501
+ ? applyRenderingDocumentPatch(state, options, document, resultObject.documentPatch, `Rendering document update: ${input.path}`)
2502
+ : null;
2503
+ const syncDocument = documentPatchResult?.workingDocument ?? document;
2504
+ const changed = result === true
2505
+ || resultObject?.changed === true
2506
+ || resultObject?.refreshWorldRendering === true
2507
+ || documentPatchResult?.changed === true;
2365
2508
  if (resultObject?.status) {
2366
2509
  state.status = resultObject.status;
2367
2510
  state.statusTone = resultObject.statusTone ?? 'default';
2368
2511
  state.statusToneStatus = state.status;
2369
2512
  state.statusDetails = resultObject.statusDetails ?? '';
2370
2513
  }
2514
+ else if (documentPatchResult?.changed) {
2515
+ state.status = documentPatchResult.label;
2516
+ state.statusTone = 'success';
2517
+ state.statusToneStatus = state.status;
2518
+ state.statusDetails = '';
2519
+ }
2371
2520
  else if (changed) {
2372
2521
  state.status = `Updated rendering: ${input.path}`;
2373
2522
  state.statusTone = 'success';
@@ -2375,7 +2524,7 @@ async function applyRenderingPropertyChange(state, options, input) {
2375
2524
  state.statusDetails = '';
2376
2525
  }
2377
2526
  if (changed) {
2378
- syncEditorWorldRenderingFromDocument(state, options, document, 'rendering-panel-change', true);
2527
+ syncEditorWorldRenderingFromDocument(state, options, syncDocument, 'rendering-panel-change', true);
2379
2528
  requestEditorSceneFrame(state, 'rendering-panel-change');
2380
2529
  }
2381
2530
  return changed || !!resultObject?.status;
@@ -2389,25 +2538,78 @@ async function applyRenderingPropertyChange(state, options, input) {
2389
2538
  return true;
2390
2539
  }
2391
2540
  }
2392
- async function applyRenderingAction(state, options, input) {
2541
+ async function applyRenderingAction(state, options, input, render) {
2393
2542
  if (state.mode !== 'editor')
2394
2543
  return false;
2395
2544
  if (!state.session || !options.documentAdapter.onRenderingAction)
2396
2545
  return false;
2546
+ if (state.renderingAction) {
2547
+ state.status = state.renderingAction.status ?? `Rendering action already running: ${state.renderingAction.actionId}`;
2548
+ state.statusTone = state.renderingAction.statusTone ?? 'default';
2549
+ state.statusToneStatus = state.status;
2550
+ state.statusDetails = state.renderingAction.statusDetails ?? '';
2551
+ render();
2552
+ return true;
2553
+ }
2397
2554
  const document = state.session.getState().workingDocument;
2555
+ const progressStartedAt = Date.now();
2556
+ state.renderingAction = {
2557
+ actionId: input.actionId,
2558
+ label: input.actionId === 'bake-static-shadows' ? 'Baking static shadows' : input.actionId,
2559
+ status: input.actionId === 'bake-static-shadows' ? 'Baking static shadows...' : `Rendering action: ${input.actionId}`,
2560
+ statusTone: 'default',
2561
+ indeterminate: true,
2562
+ };
2563
+ state.status = state.renderingAction.status ?? state.status;
2564
+ state.statusTone = state.renderingAction.statusTone ?? 'default';
2565
+ state.statusToneStatus = state.status;
2566
+ state.statusDetails = '';
2567
+ render();
2398
2568
  try {
2569
+ await state.projection?.waitForIdle?.();
2399
2570
  const result = await options.documentAdapter.onRenderingAction({
2571
+ ...input,
2400
2572
  document,
2401
2573
  actionId: input.actionId,
2574
+ scene: state.world?.scene ?? null,
2575
+ projection: state.projection,
2576
+ reportProgress: async (progress) => {
2577
+ state.renderingAction = {
2578
+ ...state.renderingAction,
2579
+ ...progress,
2580
+ actionId: progress.actionId ?? state.renderingAction?.actionId ?? input.actionId,
2581
+ };
2582
+ if (progress.status) {
2583
+ state.status = progress.status;
2584
+ state.statusTone = progress.statusTone ?? 'default';
2585
+ state.statusToneStatus = state.status;
2586
+ state.statusDetails = progress.statusDetails ?? '';
2587
+ }
2588
+ render();
2589
+ await waitForRenderingProgressFrame();
2590
+ },
2402
2591
  });
2403
2592
  const resultObject = typeof result === 'object' && result != null ? result : null;
2404
- const changed = result === true || resultObject?.changed === true || resultObject?.refreshWorldRendering === true;
2593
+ const documentPatchResult = resultObject?.documentPatch
2594
+ ? applyRenderingDocumentPatch(state, options, document, resultObject.documentPatch, `Rendering action document update: ${input.actionId}`)
2595
+ : null;
2596
+ const syncDocument = documentPatchResult?.workingDocument ?? document;
2597
+ const changed = result === true
2598
+ || resultObject?.changed === true
2599
+ || resultObject?.refreshWorldRendering === true
2600
+ || documentPatchResult?.changed === true;
2405
2601
  if (resultObject?.status) {
2406
2602
  state.status = resultObject.status;
2407
2603
  state.statusTone = resultObject.statusTone ?? 'default';
2408
2604
  state.statusToneStatus = state.status;
2409
2605
  state.statusDetails = resultObject.statusDetails ?? '';
2410
2606
  }
2607
+ else if (documentPatchResult?.changed) {
2608
+ state.status = documentPatchResult.label;
2609
+ state.statusTone = 'success';
2610
+ state.statusToneStatus = state.status;
2611
+ state.statusDetails = '';
2612
+ }
2411
2613
  else if (changed) {
2412
2614
  state.status = `Rendering action: ${input.actionId}`;
2413
2615
  state.statusTone = 'success';
@@ -2415,12 +2617,14 @@ async function applyRenderingAction(state, options, input) {
2415
2617
  state.statusDetails = '';
2416
2618
  }
2417
2619
  if (changed) {
2418
- syncEditorWorldRenderingFromDocument(state, options, document, 'rendering-panel-action', true);
2419
- requestEditorSceneFrame(state, 'rendering-panel-action');
2620
+ syncEditorWorldRenderingFromDocument(state, options, syncDocument, 'rendering-panel-action', true);
2621
+ invalidateEditorScene(state, 'rendering-panel-action', options);
2420
2622
  }
2623
+ clearRenderingActionAfterMinimumDuration(state, progressStartedAt, input.actionId, render);
2421
2624
  return changed || !!resultObject?.status;
2422
2625
  }
2423
2626
  catch (error) {
2627
+ state.renderingAction = null;
2424
2628
  state.status = error instanceof Error ? error.message : String(error);
2425
2629
  state.statusTone = 'error';
2426
2630
  state.statusToneStatus = state.status;
@@ -2429,6 +2633,70 @@ async function applyRenderingAction(state, options, input) {
2429
2633
  return true;
2430
2634
  }
2431
2635
  }
2636
+ function clearRenderingActionAfterMinimumDuration(state, startedAt, actionId, render) {
2637
+ void waitForRenderingProgressMinimumDuration(startedAt).then(() => {
2638
+ if (state.renderingAction?.actionId !== actionId)
2639
+ return;
2640
+ state.renderingAction = null;
2641
+ render();
2642
+ });
2643
+ }
2644
+ function waitForRenderingProgressFrame() {
2645
+ return new Promise(resolve => {
2646
+ if (typeof requestAnimationFrame === 'function') {
2647
+ requestAnimationFrame(() => resolve());
2648
+ }
2649
+ else {
2650
+ setTimeout(resolve, 0);
2651
+ }
2652
+ });
2653
+ }
2654
+ function waitForRenderingProgressMinimumDuration(startedAt) {
2655
+ const elapsed = Date.now() - startedAt;
2656
+ const remaining = RENDERING_ACTION_PROGRESS_MIN_VISIBLE_MS - elapsed;
2657
+ if (remaining <= 0)
2658
+ return Promise.resolve();
2659
+ return new Promise(resolve => setTimeout(resolve, remaining));
2660
+ }
2661
+ function applyRenderingDocumentPatch(state, options, document, patch, fallbackLabel) {
2662
+ if (state.mode !== 'editor' || !state.session) {
2663
+ return { changed: false, workingDocument: document, label: patch.label ?? fallbackLabel };
2664
+ }
2665
+ const label = patch.label ?? fallbackLabel;
2666
+ const defaultImpact = patch.reprojectIds?.length
2667
+ ? createReprojectProjectionImpact(patch.reprojectIds)
2668
+ : patch.changedIds?.length
2669
+ ? createReprojectProjectionImpact(patch.changedIds)
2670
+ : patch.changedId
2671
+ ? createReprojectProjectionImpact([patch.changedId])
2672
+ : undefined;
2673
+ const projectionImpact = resolveProjectionImpact(patch, defaultImpact);
2674
+ const result = state.session.dispatch({
2675
+ type: 'document.patch',
2676
+ label,
2677
+ patch: patch.patch,
2678
+ targetId: patch.changedId,
2679
+ ...withProjectionImpact(projectionImpact),
2680
+ });
2681
+ if (!result.documentChanged) {
2682
+ return { changed: false, workingDocument: result.workingDocument, label };
2683
+ }
2684
+ if (projectionImpact) {
2685
+ const applied = applyProjectionImpactToDocument(state, options, {
2686
+ document: result.workingDocument,
2687
+ selection: result.selection,
2688
+ impact: projectionImpact,
2689
+ reason: 'rendering-document-patch-impact',
2690
+ });
2691
+ if (!applied)
2692
+ rebuildProjectionFromDocument(state, options, result.workingDocument, result.selection);
2693
+ }
2694
+ else {
2695
+ syncProjectionForDispatchResult(state, options, result, patch.changedId);
2696
+ }
2697
+ state.summary = summarizeDocument(options, result.workingDocument, state.session.getSource());
2698
+ return { changed: true, workingDocument: result.workingDocument, label };
2699
+ }
2432
2700
  function createInspectorEditTransaction(state, options, document, input, targetIds) {
2433
2701
  const property = findInspectorPropertyForEdit(state, options, document, input, targetIds);
2434
2702
  if (!property) {
@@ -2516,6 +2784,9 @@ function isSerializedTransformPath(path) {
2516
2784
  || path.startsWith('transform.rotation.')
2517
2785
  || path.startsWith('transform.scale.');
2518
2786
  }
2787
+ function isSerializedProjectionMetadataPath(path) {
2788
+ return path === 'shadowMode';
2789
+ }
2519
2790
  function beginDuplicateDrag(state, options, input) {
2520
2791
  if (state.mode !== 'editor' || !state.session)
2521
2792
  return null;
@@ -2533,15 +2804,13 @@ function beginDuplicateDrag(state, options, input) {
2533
2804
  return null;
2534
2805
  }
2535
2806
  const originalSelection = state.session.getSelection();
2807
+ const projectionImpact = resolveProjectionImpact(patch, createDuplicateProjectionImpact(patch));
2536
2808
  const result = state.session.dispatch({
2537
2809
  type: 'document.patch',
2538
2810
  label: patch.label ?? `Duplicate ${input.targetIds.length} object(s)`,
2539
2811
  patch: patch.patch,
2540
2812
  targetId: patch.activeId ?? patch.createdIds[patch.createdIds.length - 1] ?? undefined,
2541
- ...withProjectionImpact(resolveProjectionImpact(patch, createCreatedReprojectProjectionImpact({
2542
- createdNodeIds: patch.createdIds,
2543
- reprojectIds: patch.reprojectIds,
2544
- }))),
2813
+ ...withProjectionImpact(projectionImpact),
2545
2814
  });
2546
2815
  if (!result.documentChanged) {
2547
2816
  state.status = 'Duplicate drag unchanged';
@@ -2569,11 +2838,14 @@ function beginDuplicateDrag(state, options, input) {
2569
2838
  createdIds,
2570
2839
  activeId,
2571
2840
  };
2572
- rebuildProjectionFromDocument(state, options, result.workingDocument, selectionResult.selection);
2573
- if (patch.reprojectIds?.length)
2574
- reprojectProjectionForChangedIds(state, options, result.workingDocument, patch.reprojectIds);
2575
- else
2576
- syncProjectionForChangedIds(state, options, result.workingDocument, patch.changedIds ?? createdIds);
2841
+ if (!applyProjectionImpactToDocument(state, options, {
2842
+ document: result.workingDocument,
2843
+ selection: selectionResult.selection,
2844
+ impact: projectionImpact,
2845
+ reason: 'duplicate-drag-impact',
2846
+ })) {
2847
+ rebuildProjectionFromDocument(state, options, result.workingDocument, selectionResult.selection);
2848
+ }
2577
2849
  state.summary = summarizeDocument(options, result.workingDocument, state.session.getSource());
2578
2850
  state.status = patch.label ?? `Duplicated ${createdIds.length} object(s)`;
2579
2851
  return {
@@ -2800,6 +3072,19 @@ function createKnownCreatedReprojectProjectionImpact(input) {
2800
3072
  reprojectIds: input.reprojectIds,
2801
3073
  });
2802
3074
  }
3075
+ function createDuplicateProjectionImpact(patch) {
3076
+ const createdNodeIds = uniqueProjectionIds(patch.createdIds);
3077
+ const reprojectIds = uniqueProjectionIds(patch.reprojectIds);
3078
+ const createdNodeIdSet = new Set(createdNodeIds);
3079
+ const reprojectIdSet = new Set(reprojectIds);
3080
+ const syncTransformIds = uniqueProjectionIds(patch.changedIds)
3081
+ .filter(id => !createdNodeIdSet.has(id) && !reprojectIdSet.has(id));
3082
+ return createIncrementalProjectionImpact({
3083
+ createdNodeIds,
3084
+ reprojectIds,
3085
+ syncTransformIds,
3086
+ });
3087
+ }
2803
3088
  function createIncrementalProjectionImpact(input) {
2804
3089
  const syncTransformIds = uniqueProjectionIds(input.syncTransformIds);
2805
3090
  const reprojectIds = uniqueProjectionIds(input.reprojectIds);
@@ -2903,56 +3188,85 @@ function applyHistoryProjectionImpact(state, options, result, operation) {
2903
3188
  if (!applied)
2904
3189
  rebuildProjection(state, options, result);
2905
3190
  }
3191
+ function applyProjectionImpactToDocument(state, options, input) {
3192
+ if (!input.impact || input.impact.type === 'rebuild')
3193
+ return false;
3194
+ return applyIncrementalProjectionImpactToDocument(state, options, {
3195
+ document: input.document,
3196
+ selection: input.selection,
3197
+ syncTransformIds: input.impact.syncTransformIds,
3198
+ reprojectIds: input.impact.reprojectIds,
3199
+ projectNodeIds: input.impact.createdNodeIds,
3200
+ removeNodeIds: input.impact.deletedNodeIds,
3201
+ reason: input.reason,
3202
+ });
3203
+ }
2906
3204
  function rebuildProjection(state, options, result) {
2907
3205
  rebuildProjectionFromDocument(state, options, result.workingDocument, result.selection);
2908
3206
  }
2909
3207
  function applyIncrementalHistoryProjectionImpact(state, options, result, operation, impact) {
2910
- if (!state.projection)
2911
- return false;
2912
- const syncTransformIds = uniqueProjectionIds(impact.syncTransformIds);
2913
- const reprojectIds = uniqueProjectionIds(impact.reprojectIds);
2914
3208
  const projectNodeIds = operation === 'redo'
2915
3209
  ? uniqueProjectionIds(impact.createdNodeIds)
2916
3210
  : uniqueProjectionIds(impact.deletedNodeIds);
2917
3211
  const removeNodeIds = operation === 'redo'
2918
3212
  ? uniqueProjectionIds(impact.deletedNodeIds)
2919
3213
  : uniqueProjectionIds(impact.createdNodeIds);
3214
+ return applyIncrementalProjectionImpactToDocument(state, options, {
3215
+ document: result.workingDocument,
3216
+ selection: result.selection,
3217
+ syncTransformIds: impact.syncTransformIds,
3218
+ reprojectIds: impact.reprojectIds,
3219
+ projectNodeIds,
3220
+ removeNodeIds,
3221
+ reason: 'history-impact',
3222
+ });
3223
+ }
3224
+ function applyIncrementalProjectionImpactToDocument(state, options, input) {
3225
+ if (!state.projection)
3226
+ return false;
3227
+ const syncTransformIds = uniqueProjectionIds(input.syncTransformIds);
3228
+ const reprojectIds = uniqueProjectionIds(input.reprojectIds);
3229
+ const projectNodeIds = uniqueProjectionIds(input.projectNodeIds);
3230
+ const removeNodeIds = uniqueProjectionIds(input.removeNodeIds);
2920
3231
  const touched = syncTransformIds.length > 0
2921
3232
  || reprojectIds.length > 0
2922
3233
  || projectNodeIds.length > 0
2923
3234
  || removeNodeIds.length > 0;
2924
3235
  if (!touched)
2925
3236
  return false;
3237
+ const projectNodes = resolveProjectionNodes(options, input.document, projectNodeIds);
3238
+ const reprojectNodes = resolveProjectionNodes(options, input.document, reprojectIds);
3239
+ const syncTransformNodes = resolveProjectionNodes(options, input.document, syncTransformIds);
3240
+ if (!projectNodes || !reprojectNodes || !syncTransformNodes)
3241
+ return false;
2926
3242
  for (const nodeId of removeNodeIds) {
2927
3243
  state.projection.removeNode(nodeId);
2928
3244
  }
2929
- for (const nodeId of projectNodeIds) {
2930
- const projectedNode = options.documentAdapter.getProjectionNode(result.workingDocument, nodeId);
2931
- if (!projectedNode)
2932
- return false;
3245
+ for (const projectedNode of projectNodes) {
2933
3246
  state.projection.projectNode(projectedNode);
2934
3247
  }
2935
- for (const nodeId of reprojectIds) {
2936
- const projectedNode = options.documentAdapter.getProjectionNode(result.workingDocument, nodeId);
2937
- if (!projectedNode)
2938
- return false;
3248
+ for (const projectedNode of reprojectNodes) {
2939
3249
  state.projection.projectNode(projectedNode);
2940
3250
  }
2941
- for (const nodeId of syncTransformIds) {
2942
- const projectedNode = options.documentAdapter.getProjectionNode(result.workingDocument, nodeId);
2943
- if (!projectedNode)
2944
- return false;
3251
+ for (const projectedNode of syncTransformNodes) {
2945
3252
  state.projection.syncNodeTransform(projectedNode);
2946
3253
  }
2947
- syncProjectionAfterHistoryIncrementalImpact(state, options, result.workingDocument, result.selection);
3254
+ const sanitized = sanitizeSelection(state, options, input.document, input.selection);
3255
+ syncSelectionToProjection(state, sanitized ?? input.selection);
3256
+ syncEditorWorldAppearanceFromDocument(state, options, input.document, `world-appearance-${input.reason}`);
3257
+ syncEditorWorldRenderingFromDocument(state, options, input.document, `world-rendering-${input.reason}`, true);
3258
+ invalidateEditorScene(state, `projection-${input.reason}`, options);
2948
3259
  return true;
2949
3260
  }
2950
- function syncProjectionAfterHistoryIncrementalImpact(state, options, document, selection) {
2951
- const sanitized = sanitizeSelection(state, options, document, selection);
2952
- syncSelectionToProjection(state, sanitized ?? selection);
2953
- syncEditorWorldAppearanceFromDocument(state, options, document, 'world-appearance-history-impact');
2954
- syncEditorWorldRenderingFromDocument(state, options, document, 'world-rendering-history-impact', true);
2955
- invalidateEditorScene(state, 'projection-history-impact', options);
3261
+ function resolveProjectionNodes(options, document, ids) {
3262
+ const projectedNodes = [];
3263
+ for (const id of ids) {
3264
+ const projectedNode = options.documentAdapter.getProjectionNode(document, id);
3265
+ if (!projectedNode)
3266
+ return null;
3267
+ projectedNodes.push(projectedNode);
3268
+ }
3269
+ return projectedNodes;
2956
3270
  }
2957
3271
  function rebuildProjectionFromDocument(state, options, document, selection) {
2958
3272
  state.projection?.rebuild(options.documentAdapter.getProjectionNodes(document));
@@ -2972,7 +3286,7 @@ function syncProjectionForDispatchResult(state, options, result, changedId) {
2972
3286
  syncSelectionToProjection(state, result.selection ?? { selectedIds: [], activeId: null });
2973
3287
  }
2974
3288
  else if (result.documentChanged) {
2975
- const selection = state.session?.getState().selection ?? { selectedIds: [], activeId: null };
3289
+ const selection = state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null };
2976
3290
  const sanitized = result.workingDocument ? sanitizeSelection(state, options, result.workingDocument, selection) : null;
2977
3291
  syncSelectionToProjection(state, sanitized ?? selection);
2978
3292
  }
@@ -2990,12 +3304,36 @@ function syncProjectionForChangedIds(state, options, document, changedIds) {
2990
3304
  if (projectedNode)
2991
3305
  state.projection?.syncNodeTransform(projectedNode);
2992
3306
  }
2993
- const selection = state.session?.getState().selection ?? { selectedIds: [], activeId: null };
3307
+ const selection = state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null };
2994
3308
  syncSelectionToProjection(state, selection);
2995
3309
  syncEditorWorldAppearanceFromDocument(state, options, document, 'world-appearance-sync-changed-ids');
2996
3310
  syncEditorWorldRenderingFromDocument(state, options, document, 'world-rendering-sync-changed-ids', true);
2997
3311
  invalidateEditorScene(state, 'projection-sync-changed-ids');
2998
3312
  }
3313
+ function syncProjectionMetadataForChangedIds(state, options, document, changedIds, syncOptions = {}) {
3314
+ for (const changedId of changedIds) {
3315
+ const projectedNode = options.documentAdapter.getProjectionNode(document, changedId);
3316
+ if (projectedNode) {
3317
+ state.projection?.syncNodeMetadata?.(projectedNode);
3318
+ }
3319
+ }
3320
+ const selection = state.session?.getState({ cloneDocuments: false }).selection ?? { selectedIds: [], activeId: null };
3321
+ syncSelectionToProjection(state, selection);
3322
+ syncEditorWorldAppearanceFromDocument(state, options, document, 'world-appearance-sync-metadata-ids');
3323
+ if (syncOptions.invalidateStaticShadowArtifact) {
3324
+ state.shadowPreview?.invalidateStaticProjectedArtifact?.();
3325
+ }
3326
+ else {
3327
+ syncEditorWorldRenderingFromDocument(state, options, document, 'world-rendering-sync-metadata-ids', true);
3328
+ }
3329
+ if (syncOptions.deferShadowPreviewRefresh) {
3330
+ scheduleProjectionShadowPreviewRefresh(state, 'projection-sync-metadata-ids-shadow-preview');
3331
+ }
3332
+ else {
3333
+ state.shadowPreview?.refresh();
3334
+ }
3335
+ invalidateEditorScene(state, 'projection-sync-metadata-ids');
3336
+ }
2999
3337
  function reprojectProjectionForChangedIds(state, options, document, changedIds) {
3000
3338
  for (const changedId of changedIds) {
3001
3339
  const projectedNode = options.documentAdapter.getProjectionNode(document, changedId);
@@ -3172,21 +3510,24 @@ function radiansToInspectorDegrees(value) {
3172
3510
  return (value * 180) / Math.PI;
3173
3511
  }
3174
3512
  function createUiState(state, options) {
3175
- const sessionState = state.session?.getState();
3513
+ const sessionState = state.session?.getState({ cloneDocuments: false });
3176
3514
  const document = sessionState?.workingDocument ?? null;
3177
3515
  const selectedIds = sessionState?.selection.selectedIds ?? [];
3178
3516
  const activeId = sessionState?.selection.activeId ?? null;
3517
+ const largeSelection = isLargeSelection(selectedIds);
3179
3518
  const serializedObject = document && activeId && selectedIds.length === 1
3180
3519
  ? options.documentAdapter.getSerializedObject(document, activeId)
3181
3520
  : null;
3182
- const serializedMultiObject = document && selectedIds.length > 1
3521
+ const serializedMultiObject = document && selectedIds.length > 1 && !largeSelection
3183
3522
  ? options.documentAdapter.getSerializedMultiObject?.(document, selectedIds, activeId) ?? null
3184
3523
  : null;
3185
3524
  const inspectorObjectBase = document && activeId && selectedIds.length === 1
3186
3525
  ? options.documentAdapter.getInspectorObject?.(document, activeId) ?? (serializedObject ? serializedObjectToInspectorObject(serializedObject, document) : null)
3187
3526
  : null;
3188
3527
  const inspectorMultiObjectBase = document && selectedIds.length > 1
3189
- ? createInspectorMultiObjectBase(state, options, document, selectedIds, activeId, serializedMultiObject)
3528
+ ? createInspectorMultiObjectBase(state, options, document, selectedIds, activeId, serializedMultiObject, {
3529
+ largeSelection,
3530
+ })
3190
3531
  : null;
3191
3532
  const inspectorObject = document && inspectorObjectBase
3192
3533
  ? withRuntimeInspectorSections(state, options, document, inspectorObjectBase)
@@ -3199,6 +3540,13 @@ function createUiState(state, options) {
3199
3540
  const documentAssetItems = document
3200
3541
  ? options.documentAdapter.getBrowserAssetItems?.(document) ?? []
3201
3542
  : [];
3543
+ const hierarchy = document ? options.documentAdapter.getHierarchyItems(document) : [];
3544
+ state.performanceObjectCount = document ? countLocalEditorAuthoredObjects(hierarchy) : null;
3545
+ state.performanceStats = createLocalEditorPerformanceStats({
3546
+ frameStats: state.sceneFrameStats,
3547
+ runtimeStats: state.performanceMonitor?.readSnapshot() ?? null,
3548
+ objectCount: state.performanceObjectCount,
3549
+ });
3202
3550
  const assets = dedupeLocalEditorBrowserAssetItems([
3203
3551
  ...state.assets.map(asset => toBrowserAssetItem(options, asset)),
3204
3552
  ...documentAssetItems,
@@ -3214,7 +3562,7 @@ function createUiState(state, options) {
3214
3562
  assets,
3215
3563
  selectedAssetId: state.selectedAssetId,
3216
3564
  assetCountLabel: `${assets.length} assets`,
3217
- hierarchy: document ? options.documentAdapter.getHierarchyItems(document) : [],
3565
+ hierarchy,
3218
3566
  selectedIds,
3219
3567
  activeId,
3220
3568
  selectionSummary: {
@@ -3225,7 +3573,13 @@ function createUiState(state, options) {
3225
3573
  serializedMultiObject,
3226
3574
  inspectorObject: previewInspectorObject,
3227
3575
  inspectorMultiObject: previewInspectorMultiObject,
3228
- renderingPanel: document ? options.documentAdapter.getRenderingPanelState?.(document) ?? null : null,
3576
+ renderingPanel: document
3577
+ ? options.documentAdapter.getRenderingPanelState?.(document, {
3578
+ scene: state.world?.scene ?? null,
3579
+ projection: state.projection,
3580
+ renderingAction: state.renderingAction,
3581
+ }) ?? null
3582
+ : null,
3229
3583
  boxSelection: state.boxSelection,
3230
3584
  coordinateAxes: options.world?.coordinateAxes === false
3231
3585
  ? null
@@ -3241,8 +3595,8 @@ function createUiState(state, options) {
3241
3595
  settings: cloneTransformOperationSettings(state.transformOperationSettings),
3242
3596
  selectedCount: selectedIds.length,
3243
3597
  activeId,
3244
- canAlign: selectedIds.length >= 2 && activeId != null,
3245
- canDistribute: selectedIds.length >= 3,
3598
+ canAlign: !largeSelection && selectedIds.length >= 2 && activeId != null,
3599
+ canDistribute: !largeSelection && selectedIds.length >= 3,
3246
3600
  },
3247
3601
  viewportTools: cloneEditorViewportToolState(state.viewportTools),
3248
3602
  viewportMeasurement: cloneViewportMeasurement(state.viewportMeasurement),
@@ -3250,6 +3604,7 @@ function createUiState(state, options) {
3250
3604
  sceneFrameStats: state.sceneFrameStats
3251
3605
  ? { ...state.sceneFrameStats, activeReasons: [...state.sceneFrameStats.activeReasons] }
3252
3606
  : null,
3607
+ performanceStats: cloneLocalEditorPerformanceStats(state.performanceStats),
3253
3608
  sceneCameraPreview: {
3254
3609
  enabled: state.sceneCameraPreviewEnabled,
3255
3610
  available: hasSceneCameraPreviewRig(state, options),
@@ -3270,10 +3625,12 @@ function createUiState(state, options) {
3270
3625
  };
3271
3626
  }
3272
3627
  function createUiPreviewState(state, options) {
3273
- const selection = state.session?.getState().selection;
3274
- const document = state.session?.getState().workingDocument ?? null;
3628
+ const sessionState = state.session?.getState({ cloneDocuments: false });
3629
+ const selection = sessionState?.selection;
3630
+ const document = sessionState?.workingDocument ?? null;
3275
3631
  const selectedIds = selection?.selectedIds ?? [];
3276
3632
  const activeId = selection?.activeId ?? null;
3633
+ const largeSelection = isLargeSelection(selectedIds);
3277
3634
  const shouldPreviewInspector = !!state.activeTransformPreview && document && activeId && selectedIds.length === 1;
3278
3635
  const inspectorObjectBase = shouldPreviewInspector
3279
3636
  ? options.documentAdapter.getInspectorObject?.(document, activeId)
@@ -3305,8 +3662,8 @@ function createUiPreviewState(state, options) {
3305
3662
  settings: cloneTransformOperationSettings(state.transformOperationSettings),
3306
3663
  selectedCount: selectedIds.length,
3307
3664
  activeId,
3308
- canAlign: selectedIds.length >= 2 && activeId != null,
3309
- canDistribute: selectedIds.length >= 3,
3665
+ canAlign: !largeSelection && selectedIds.length >= 2 && activeId != null,
3666
+ canDistribute: !largeSelection && selectedIds.length >= 3,
3310
3667
  },
3311
3668
  viewportTools: cloneEditorViewportToolState(state.viewportTools),
3312
3669
  viewportMeasurement: cloneViewportMeasurement(state.viewportMeasurement),
@@ -3314,8 +3671,28 @@ function createUiPreviewState(state, options) {
3314
3671
  sceneFrameStats: state.sceneFrameStats
3315
3672
  ? { ...state.sceneFrameStats, activeReasons: [...state.sceneFrameStats.activeReasons] }
3316
3673
  : null,
3674
+ performanceStats: cloneLocalEditorPerformanceStats(state.performanceStats),
3317
3675
  };
3318
3676
  }
3677
+ function setLocalEditorPerformanceMonitorOpen(state, open) {
3678
+ if (state.performanceMonitorOpen === open)
3679
+ return;
3680
+ state.performanceMonitorOpen = open;
3681
+ if (open) {
3682
+ state.viewportRenderCoordinator?.beginContinuous(LOCAL_EDITOR_PERFORMANCE_MONITOR_REASON);
3683
+ }
3684
+ else {
3685
+ state.viewportRenderCoordinator?.endContinuous(LOCAL_EDITOR_PERFORMANCE_MONITOR_REASON);
3686
+ }
3687
+ }
3688
+ function updateLocalEditorPerformanceStats(state, updatePerformanceStats) {
3689
+ state.performanceStats = createLocalEditorPerformanceStats({
3690
+ frameStats: state.sceneFrameStats,
3691
+ runtimeStats: state.performanceMonitor?.readSnapshot() ?? null,
3692
+ objectCount: state.performanceObjectCount,
3693
+ });
3694
+ updatePerformanceStats(cloneLocalEditorPerformanceStats(state.performanceStats));
3695
+ }
3319
3696
  function createSceneViewCoordinateAxesState(state) {
3320
3697
  if (state.mode !== 'editor')
3321
3698
  return null;
@@ -3409,36 +3786,84 @@ function clampNumber(value, min, max) {
3409
3786
  return min;
3410
3787
  return Math.min(max, Math.max(min, value));
3411
3788
  }
3412
- function createInspectorMultiObjectBase(state, options, document, selectedIds, activeId, serializedMultiObject) {
3789
+ function isLargeSelection(selectedIds) {
3790
+ return selectedIds.length > LARGE_SELECTION_THRESHOLD;
3791
+ }
3792
+ function createInspectorMultiObjectBase(state, options, document, selectedIds, activeId, serializedMultiObject, multiOptions = {}) {
3413
3793
  const targetIds = [...selectedIds];
3414
3794
  if (targetIds.length <= 1)
3415
3795
  return null;
3416
3796
  const adapterMultiObject = options.documentAdapter.getInspectorMultiObject?.(document, targetIds, activeId) ?? null;
3797
+ if (multiOptions.largeSelection) {
3798
+ return applyMultiInspectorBatchCapabilityGate(options, document, adapterMultiObject ?? createLargeSelectionInspectorObject(document, targetIds, activeId));
3799
+ }
3417
3800
  const serializedMulti = serializedMultiObject !== undefined
3418
3801
  ? serializedMultiObject
3419
3802
  : options.documentAdapter.getSerializedMultiObject?.(document, targetIds, activeId) ?? null;
3420
3803
  const serializedInspector = serializedMulti ? serializedMultiObjectToInspectorObject(serializedMulti, document) : null;
3421
3804
  const baseInspector = adapterMultiObject ?? serializedInspector;
3422
3805
  const aggregatedInspector = createAggregatedInspectorMultiObjectBase(state, options, document, targetIds, activeId);
3423
- if (!baseInspector)
3424
- return aggregatedInspector;
3425
- if (!aggregatedInspector)
3426
- return baseInspector;
3806
+ let inspectorObject = baseInspector ?? aggregatedInspector;
3807
+ if (baseInspector && aggregatedInspector) {
3808
+ inspectorObject = {
3809
+ ...baseInspector,
3810
+ targetIds,
3811
+ activeId,
3812
+ label: baseInspector.label ?? aggregatedInspector.label,
3813
+ document,
3814
+ selection: {
3815
+ ...baseInspector.selection,
3816
+ targetIds,
3817
+ activeId,
3818
+ document,
3819
+ },
3820
+ sections: mergeInspectorSections(baseInspector.sections, aggregatedInspector.sections, {
3821
+ propertyConflict: 'ignore',
3822
+ }),
3823
+ };
3824
+ }
3825
+ return applyMultiInspectorBatchCapabilityGate(options, document, inspectorObject);
3826
+ }
3827
+ function createLargeSelectionInspectorObject(document, targetIds, activeId) {
3427
3828
  return {
3428
- ...baseInspector,
3429
- targetIds,
3829
+ targetIds: [...targetIds],
3430
3830
  activeId,
3431
- label: baseInspector.label ?? aggregatedInspector.label,
3831
+ label: `${targetIds.length} objects`,
3432
3832
  document,
3433
3833
  selection: {
3434
- ...baseInspector.selection,
3435
- targetIds,
3834
+ targetIds: [...targetIds],
3436
3835
  activeId,
3437
3836
  document,
3438
3837
  },
3439
- sections: mergeInspectorSections(baseInspector.sections, aggregatedInspector.sections, {
3440
- propertyConflict: 'ignore',
3441
- }),
3838
+ sections: [{
3839
+ id: 'large-selection',
3840
+ title: 'Large Selection',
3841
+ order: 10,
3842
+ placement: 'body',
3843
+ persistence: 'readonly',
3844
+ properties: [
3845
+ {
3846
+ path: 'selection.count',
3847
+ label: 'Selected',
3848
+ valueType: 'number',
3849
+ control: 'readonly',
3850
+ value: targetIds.length,
3851
+ readOnly: true,
3852
+ persistence: 'readonly',
3853
+ commitMode: 'immediate',
3854
+ },
3855
+ {
3856
+ path: 'selection.activeId',
3857
+ label: 'Active ID',
3858
+ valueType: 'string',
3859
+ control: 'readonly',
3860
+ value: activeId ?? 'None',
3861
+ readOnly: true,
3862
+ persistence: 'readonly',
3863
+ commitMode: 'immediate',
3864
+ },
3865
+ ],
3866
+ }],
3442
3867
  };
3443
3868
  }
3444
3869
  function createAggregatedInspectorMultiObjectBase(_state, options, document, selectedIds, activeId) {
@@ -3452,9 +3877,7 @@ function createAggregatedInspectorMultiObjectBase(_state, options, document, sel
3452
3877
  label: `${selectedIds.length} objects`,
3453
3878
  document,
3454
3879
  });
3455
- return options.documentAdapter.createSerializedMultiPropertyPatch
3456
- ? applyAggregatedBatchInspectorCapabilityGate(options, document, aggregatedInspector)
3457
- : disableAggregatedBatchInspectorObject(aggregatedInspector);
3880
+ return aggregatedInspector;
3458
3881
  }
3459
3882
  function createSingleInspectorObjectBase(options, document, targetId) {
3460
3883
  const inspectorObject = options.documentAdapter.getInspectorObject?.(document, targetId) ?? null;
@@ -3463,6 +3886,11 @@ function createSingleInspectorObjectBase(options, document, targetId) {
3463
3886
  const serializedObject = options.documentAdapter.getSerializedObject(document, targetId);
3464
3887
  return serializedObject ? serializedObjectToInspectorObject(serializedObject, document) : null;
3465
3888
  }
3889
+ function applyMultiInspectorBatchCapabilityGate(options, document, inspectorObject) {
3890
+ return options.documentAdapter.createSerializedMultiPropertyPatch
3891
+ ? applyAggregatedBatchInspectorCapabilityGate(options, document, inspectorObject)
3892
+ : disableAggregatedBatchInspectorObject(inspectorObject);
3893
+ }
3466
3894
  function disableAggregatedBatchInspectorObject(inspectorObject) {
3467
3895
  if (!inspectorObject)
3468
3896
  return null;
@@ -3774,13 +4202,13 @@ async function saveDocumentFallback(options, document) {
3774
4202
  return options.persistenceAdapter.saveDocument(document);
3775
4203
  }
3776
4204
  function isDocumentNodeSelectable(state, options, id) {
3777
- const document = state.session?.getState().workingDocument;
4205
+ const document = state.session?.getState({ cloneDocuments: false }).workingDocument;
3778
4206
  if (!document)
3779
4207
  return false;
3780
4208
  return isNodeSelectableInDocument(options, document, id);
3781
4209
  }
3782
4210
  function isDocumentNodeLocked(state, options, id) {
3783
- const document = state.session?.getState().workingDocument;
4211
+ const document = state.session?.getState({ cloneDocuments: false }).workingDocument;
3784
4212
  if (!document)
3785
4213
  return false;
3786
4214
  return options.documentAdapter.isLocked?.(document, id) ?? false;