@fps-games/editor 0.1.4-beta.5 → 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 (227) hide show
  1. package/dist/build-info.json +16 -16
  2. package/dist/local-editor-harness.d.ts +24 -5
  3. package/dist/local-editor-harness.d.ts.map +1 -1
  4. package/dist/local-editor-harness.js +456 -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 +2 -2
  11. package/dist/playable-babylon-facade.d.ts.map +1 -1
  12. package/dist/playable-babylon-facade.js +1 -1
  13. package/dist/playable-babylon-facade.js.map +1 -1
  14. package/dist/playable-babylon-rendering.d.ts +57 -12
  15. package/dist/playable-babylon-rendering.d.ts.map +1 -1
  16. package/dist/playable-babylon-rendering.js +529 -20
  17. package/dist/playable-babylon-rendering.js.map +1 -1
  18. package/dist/playable-local-editor-host.d.ts +10 -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.d.ts +5 -3
  22. package/dist/playable-sdk.d.ts.map +1 -1
  23. package/dist/playable-sdk.js +3 -2
  24. package/dist/playable-sdk.js.map +1 -1
  25. package/dist/static-shadow-cpu-worker.d.ts +7 -0
  26. package/dist/static-shadow-cpu-worker.d.ts.map +1 -0
  27. package/dist/static-shadow-cpu-worker.js +221 -0
  28. package/dist/static-shadow-cpu-worker.js.map +1 -0
  29. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts +3 -1
  30. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts.map +1 -1
  31. package/node_modules/@fps-games/babylon-renderer/dist/index.js +3 -1
  32. package/node_modules/@fps-games/babylon-renderer/dist/index.js.map +1 -1
  33. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts +4 -0
  34. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -0
  35. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +584 -0
  36. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -0
  37. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts +61 -0
  38. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts.map +1 -0
  39. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js +382 -0
  40. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js.map +1 -0
  41. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts +47 -0
  42. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts.map +1 -0
  43. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js +285 -0
  44. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js.map +1 -0
  45. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts +88 -0
  46. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts.map +1 -0
  47. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +813 -0
  48. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -0
  49. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts +27 -0
  50. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts.map +1 -0
  51. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js +220 -0
  52. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js.map +1 -0
  53. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts +35 -3
  54. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts.map +1 -1
  55. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js +65 -609
  56. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js.map +1 -1
  57. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +169 -14
  58. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
  59. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +9 -3
  60. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
  61. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  62. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +2 -0
  63. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
  64. package/node_modules/@fps-games/editor-babylon/dist/index.js +2 -0
  65. package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
  66. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts +34 -0
  67. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts.map +1 -0
  68. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js +272 -0
  69. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js.map +1 -0
  70. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +6 -0
  71. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  72. package/node_modules/@fps-games/editor-babylon/dist/projection.js +65 -1
  73. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  74. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts +19 -0
  75. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts.map +1 -0
  76. package/node_modules/@fps-games/editor-babylon/dist/rendering.js +66 -0
  77. package/node_modules/@fps-games/editor-babylon/dist/rendering.js.map +1 -0
  78. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +5 -2
  79. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
  80. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +65 -32
  81. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
  82. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
  83. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +19 -2
  84. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
  85. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  86. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +1 -1
  87. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  88. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  89. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts +8 -0
  90. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts.map +1 -0
  91. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js +14 -0
  92. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js.map +1 -0
  93. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  94. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +10 -2
  95. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  96. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  97. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  98. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +17 -0
  99. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  100. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  101. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +466 -42
  102. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  103. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +70 -5
  104. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  105. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
  106. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  107. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +595 -5
  108. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  109. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  110. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +14 -1
  111. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
  112. package/node_modules/@fps-games/editor-core/dist/editor-session.js +34 -10
  113. package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
  114. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts +2 -1
  115. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts.map +1 -1
  116. package/node_modules/@fps-games/editor-core/dist/inspector.js +11 -1
  117. package/node_modules/@fps-games/editor-core/dist/inspector.js.map +1 -1
  118. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts +7 -0
  119. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts.map +1 -1
  120. package/node_modules/@fps-games/editor-core/dist/serialized-object.js +1 -0
  121. package/node_modules/@fps-games/editor-core/dist/serialized-object.js.map +1 -1
  122. package/node_modules/@fps-games/editor-core/package.json +2 -2
  123. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  124. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  125. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +10 -5
  126. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  127. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
  128. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +3 -1
  129. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
  130. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +4 -1
  131. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  132. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +29 -0
  133. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  134. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +10 -0
  135. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  136. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  137. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +3 -0
  138. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  139. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +1 -0
  140. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
  141. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +1 -0
  142. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
  143. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +33 -2
  144. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
  145. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +232 -16
  146. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
  147. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
  148. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
  149. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
  150. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
  151. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts +12 -1
  152. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  153. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +153 -0
  154. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  155. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts +4 -2
  156. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts.map +1 -1
  157. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js +2 -1
  158. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js.map +1 -1
  159. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
  160. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
  161. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
  162. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts +19 -0
  163. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts.map +1 -0
  164. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js +57 -0
  165. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js.map +1 -0
  166. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts +7 -1
  167. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts.map +1 -1
  168. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
  169. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +620 -36
  170. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
  171. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts +8 -3
  172. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts.map +1 -1
  173. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js +258 -10
  174. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js.map +1 -1
  175. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts +110 -3
  176. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts.map +1 -1
  177. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  178. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +25 -0
  179. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  180. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +2 -1
  181. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  182. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
  183. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +4 -0
  184. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
  185. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts +9 -1
  186. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts.map +1 -1
  187. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js +12 -1
  188. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js.map +1 -1
  189. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +2 -0
  190. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
  191. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
  192. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  193. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +75 -0
  194. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  195. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts +1 -0
  196. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts.map +1 -1
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js +1 -0
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js.map +1 -1
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts +17 -0
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -0
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +262 -0
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -0
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -3
  205. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
  206. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts +6 -0
  207. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts.map +1 -1
  208. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js +31 -0
  209. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js.map +1 -1
  210. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts +2 -1
  211. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts.map +1 -1
  212. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js +1 -1
  213. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js.map +1 -1
  214. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.d.ts.map +1 -1
  215. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js +21 -9
  216. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js.map +1 -1
  217. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +151 -0
  218. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -0
  219. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +445 -0
  220. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -0
  221. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts +2 -0
  222. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts.map +1 -0
  223. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js +2 -0
  224. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js.map +1 -0
  225. package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
  226. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  227. package/package.json +8 -8
@@ -1,7 +1,7 @@
1
1
  import { createLocalEditorIcon, isLocalEditorIconName, } from './local-editor-ui-icons.js';
2
2
  import { createBadge, createAssetList, createDockTab, createEditorInputStyle, createEmptyState, createListItemBlock, createPanelHeader, createPropertyRow, createToolbarButton, createTreeView, createTreeViewItem, } from './local-editor-ui-primitives.js';
3
3
  import { configureLocalEditorDockPanelContent, createLocalEditorDockPanelViewport, renderLocalEditorDockTabStrip, } from './local-editor-ui-dock-panel.js';
4
- import { clearElement, toTitle } from './local-editor-ui-shared.js';
4
+ import { clearElement, createButton, toTitle } from './local-editor-ui-shared.js';
5
5
  import { createLocalEditorBrowserInspectorVectorCopyPayload, } from './local-editor-inspector-clipboard.js';
6
6
  import { resolveLocalEditorBrowserInspectorVectorGroupPathFromProperties, } from './local-editor-inspector-groups.js';
7
7
  const BOTTOM_DOCK_TAB_ICONS = {
@@ -219,18 +219,50 @@ export function renderRenderingPanel(doc, panel, state) {
219
219
  panel.appendChild(viewport);
220
220
  }
221
221
  function createRenderingPanelActions(doc, rendering) {
222
- return (rendering?.actions ?? []).map(action => {
223
- const icon = action.icon && isLocalEditorIconName(action.icon) ? action.icon : 'world';
224
- const button = createToolbarButton(doc, action.label, icon);
225
- button.type = 'button';
226
- button.dataset.editorRenderingAction = action.id;
227
- button.disabled = action.disabled === true;
228
- button.title = action.tooltip ?? action.label;
229
- button.dataset.editorTooltip = button.title;
222
+ return (rendering?.actions ?? []).map(action => createRenderingActionButton(doc, action, {
223
+ buttonKind: 'toolbar',
224
+ }));
225
+ }
226
+ function createRenderingActionButton(doc, action, context = {}) {
227
+ const icon = action.icon && isLocalEditorIconName(action.icon) ? action.icon : 'world';
228
+ const button = context.buttonKind === 'icon'
229
+ ? createButton(doc, action.label, {
230
+ icon,
231
+ labelMode: 'icon-only',
232
+ tooltip: action.tooltip ?? action.label,
233
+ ariaLabel: action.label,
234
+ variant: 'toolbar-icon',
235
+ })
236
+ : createToolbarButton(doc, action.label, icon);
237
+ button.type = 'button';
238
+ button.dataset.editorRenderingAction = action.id;
239
+ if (context.sectionId)
240
+ button.dataset.renderingSectionId = context.sectionId;
241
+ if (context.systemId)
242
+ button.dataset.renderingSystemId = context.systemId;
243
+ if (context.path)
244
+ button.dataset.renderingPath = context.path;
245
+ if (action.params)
246
+ button.dataset.renderingActionParams = JSON.stringify(action.params);
247
+ button.disabled = action.disabled === true;
248
+ button.title = action.tooltip ?? action.label;
249
+ button.dataset.editorTooltip = button.title;
250
+ if (context.buttonKind === 'toolbar') {
230
251
  button.style.padding = '3px 7px';
231
252
  button.style.fontSize = '11px';
232
- return button;
233
- });
253
+ }
254
+ else if (context.buttonKind === 'compact') {
255
+ button.style.padding = '2px 6px';
256
+ button.style.height = '22px';
257
+ button.style.fontSize = '11px';
258
+ }
259
+ else {
260
+ button.style.width = '24px';
261
+ button.style.minWidth = '24px';
262
+ button.style.height = '24px';
263
+ button.style.flexBasis = '24px';
264
+ }
265
+ return button;
234
266
  }
235
267
  function tabHeaderButtonStyle(button) {
236
268
  button.style.borderTop = '0';
@@ -240,8 +272,11 @@ function tabHeaderButtonStyle(button) {
240
272
  }
241
273
  function createRenderingSectionBlock(doc, section) {
242
274
  const isListLayout = section.layout === 'list';
243
- const block = doc.createElement('section');
275
+ const systemGroups = groupRenderingSystems(section.systems);
276
+ const hasSystemGroups = systemGroups.some(group => group.group);
277
+ const block = doc.createElement('details');
244
278
  block.dataset.editorRenderingSection = section.id;
279
+ block.open = section.collapsedByDefault !== true;
245
280
  block.style.cssText = [
246
281
  'margin:0 0 10px',
247
282
  `padding:${isListLayout ? '6px' : '8px'}`,
@@ -249,8 +284,19 @@ function createRenderingSectionBlock(doc, section) {
249
284
  'border-radius:3px',
250
285
  'background:var(--fps-editor-panel-soft)',
251
286
  ].join(';');
252
- const header = doc.createElement('div');
253
- header.style.cssText = 'display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin:0 0 8px';
287
+ const header = doc.createElement('summary');
288
+ header.style.cssText = [
289
+ 'display:flex',
290
+ 'align-items:flex-start',
291
+ 'justify-content:space-between',
292
+ 'gap:8px',
293
+ 'cursor:pointer',
294
+ 'list-style:none',
295
+ 'margin:0',
296
+ ].join(';');
297
+ const titleGroup = doc.createElement('div');
298
+ titleGroup.style.cssText = 'display:flex;align-items:flex-start;gap:6px;min-width:0';
299
+ const disclosure = createRenderingDisclosureIcon(doc, block, section.id, 'editorRenderingSectionDisclosure');
254
300
  const title = doc.createElement('div');
255
301
  title.style.cssText = 'min-width:0';
256
302
  const heading = doc.createElement('h3');
@@ -263,32 +309,145 @@ function createRenderingSectionBlock(doc, section) {
263
309
  summary.style.cssText = 'margin-top:3px;color:var(--fps-editor-muted);font-size:11px;line-height:1.35';
264
310
  title.appendChild(summary);
265
311
  }
266
- header.appendChild(title);
312
+ titleGroup.appendChild(disclosure);
313
+ titleGroup.appendChild(title);
314
+ header.appendChild(titleGroup);
267
315
  header.appendChild(createBadge(doc, `${section.systems.length}`, { compact: true }));
268
316
  block.appendChild(header);
317
+ const content = doc.createElement('div');
318
+ content.dataset.editorRenderingSectionContent = section.id;
319
+ content.style.cssText = 'margin-top:8px';
269
320
  const list = doc.createElement('div');
270
321
  list.style.cssText = [
271
322
  'display:flex',
272
323
  'flex-direction:column',
273
- `gap:${isListLayout ? '0' : '8px'}`,
274
- ...(isListLayout ? [
324
+ `gap:${hasSystemGroups ? '8px' : isListLayout ? '0' : '8px'}`,
325
+ ...(isListLayout && !hasSystemGroups ? [
275
326
  'border:1px solid var(--fps-editor-border)',
276
327
  'border-radius:3px',
277
328
  'overflow:hidden',
278
329
  'background:rgba(0,0,0,0.08)',
279
330
  ] : []),
280
331
  ].join(';');
281
- for (const system of section.systems) {
282
- list.appendChild(createRenderingSystemBlock(doc, section.id, system, section.layout));
332
+ for (const group of systemGroups) {
333
+ if (group.group) {
334
+ list.appendChild(createRenderingSystemGroupBlock(doc, section.id, group.group, group.systems, section.layout, section.systemsCollapsible === true));
335
+ continue;
336
+ }
337
+ for (const system of group.systems) {
338
+ list.appendChild(createRenderingSystemBlock(doc, section.id, system, section.layout, section.systemsCollapsible === true));
339
+ }
283
340
  }
284
- block.appendChild(list);
341
+ content.appendChild(list);
342
+ block.appendChild(content);
285
343
  return block;
286
344
  }
287
- function createRenderingSystemBlock(doc, sectionId, system, layout = 'cards') {
345
+ function groupRenderingSystems(systems) {
346
+ const groups = [];
347
+ for (const system of systems) {
348
+ const group = system.group ?? null;
349
+ const key = group?.id ?? `system:${system.id}`;
350
+ const activeGroup = groups[groups.length - 1];
351
+ if (activeGroup?.key === key) {
352
+ activeGroup.systems.push(system);
353
+ continue;
354
+ }
355
+ groups.push({ key, group, systems: [system] });
356
+ }
357
+ return groups;
358
+ }
359
+ function createRenderingSystemGroupBlock(doc, sectionId, group, systems, layout = 'cards', systemsCollapsible = false) {
288
360
  const isListLayout = layout === 'list';
289
- const block = createListItemBlock(doc);
361
+ const block = doc.createElement('section');
362
+ block.dataset.editorRenderingSystemGroup = group.id;
363
+ block.style.cssText = [
364
+ 'min-width:0',
365
+ 'border:1px solid var(--fps-editor-border)',
366
+ `border-left:3px solid ${getRenderingSystemGroupAccent(group.id)}`,
367
+ 'border-radius:3px',
368
+ 'background:rgba(0,0,0,0.08)',
369
+ 'overflow:hidden',
370
+ ].join(';');
371
+ const header = doc.createElement('div');
372
+ header.style.cssText = [
373
+ 'display:flex',
374
+ 'align-items:flex-start',
375
+ 'justify-content:space-between',
376
+ 'gap:8px',
377
+ 'padding:8px',
378
+ 'border-bottom:1px solid var(--fps-editor-divider)',
379
+ 'background:rgba(255,255,255,0.025)',
380
+ ].join(';');
381
+ const title = doc.createElement('div');
382
+ title.style.cssText = 'min-width:0;display:flex;flex-direction:column;gap:3px';
383
+ const label = doc.createElement('div');
384
+ label.textContent = group.label;
385
+ label.style.cssText = [
386
+ 'color:var(--fps-editor-text-strong)',
387
+ 'font-size:12px',
388
+ 'font-weight:900',
389
+ 'line-height:1.25',
390
+ 'min-width:0',
391
+ 'overflow:hidden',
392
+ 'text-overflow:ellipsis',
393
+ 'white-space:nowrap',
394
+ ].join(';');
395
+ title.appendChild(label);
396
+ if (group.summary) {
397
+ const summary = doc.createElement('div');
398
+ summary.textContent = group.summary;
399
+ summary.style.cssText = [
400
+ 'color:var(--fps-editor-muted)',
401
+ 'font-size:10px',
402
+ 'font-weight:700',
403
+ 'line-height:1.35',
404
+ 'overflow-wrap:anywhere',
405
+ ].join(';');
406
+ title.appendChild(summary);
407
+ }
408
+ header.appendChild(title);
409
+ header.appendChild(createBadge(doc, `${systems.length}`, { compact: true }));
410
+ block.appendChild(header);
411
+ const body = doc.createElement('div');
412
+ body.style.cssText = [
413
+ 'display:flex',
414
+ 'flex-direction:column',
415
+ `gap:${isListLayout ? '0' : '8px'}`,
416
+ isListLayout ? '' : 'padding:8px',
417
+ ].filter(Boolean).join(';');
418
+ systems.forEach((system, index) => {
419
+ const systemBlock = createRenderingSystemBlock(doc, sectionId, system, layout, systemsCollapsible);
420
+ if (isListLayout && index === systems.length - 1)
421
+ systemBlock.style.borderBottom = '0';
422
+ body.appendChild(systemBlock);
423
+ });
424
+ block.appendChild(body);
425
+ return block;
426
+ }
427
+ function getRenderingSystemGroupAccent(groupId) {
428
+ if (groupId.includes('moving'))
429
+ return 'var(--fps-editor-accent)';
430
+ if (groupId.includes('static'))
431
+ return 'var(--fps-editor-success)';
432
+ if (groupId.includes('planar'))
433
+ return 'var(--fps-editor-warn)';
434
+ return 'var(--fps-editor-muted)';
435
+ }
436
+ function createRenderingSystemBlock(doc, sectionId, system, layout = 'cards', collapsible = false) {
437
+ const isListLayout = layout === 'list';
438
+ const block = collapsible ? doc.createElement('details') : createListItemBlock(doc);
290
439
  block.dataset.editorRenderingSystem = system.id;
291
440
  block.dataset.editorRenderingSystemKind = system.kind;
441
+ if (collapsible) {
442
+ const details = block;
443
+ details.open = system.collapsedByDefault !== true;
444
+ details.style.cssText = [
445
+ 'padding:7px 8px',
446
+ 'border:1px solid var(--fps-editor-border-soft)',
447
+ 'border-radius:3px',
448
+ 'background:var(--fps-editor-panel-soft)',
449
+ ].join(';');
450
+ }
292
451
  if (isListLayout) {
293
452
  block.style.margin = '0';
294
453
  block.style.border = '0';
@@ -297,36 +456,81 @@ function createRenderingSystemBlock(doc, sectionId, system, layout = 'cards') {
297
456
  block.style.background = 'transparent';
298
457
  block.style.padding = '8px';
299
458
  }
300
- const header = doc.createElement('div');
301
- header.style.cssText = `display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin:0 0 ${isListLayout ? '6px' : '8px'}`;
459
+ const header = doc.createElement(collapsible ? 'summary' : 'div');
460
+ header.style.cssText = [
461
+ 'display:flex',
462
+ 'align-items:flex-start',
463
+ 'justify-content:space-between',
464
+ 'gap:8px',
465
+ 'min-width:0',
466
+ `margin:${collapsible ? '0' : `0 0 ${isListLayout ? '6px' : '8px'}`}`,
467
+ ...(collapsible ? [
468
+ 'cursor:pointer',
469
+ 'list-style:none',
470
+ ] : []),
471
+ ].join(';');
472
+ const titleGroup = doc.createElement('div');
473
+ titleGroup.style.cssText = collapsible
474
+ ? 'display:flex;align-items:flex-start;gap:6px;min-width:0'
475
+ : 'min-width:0';
302
476
  const title = doc.createElement('div');
303
- title.style.cssText = 'min-width:0';
477
+ title.style.cssText = 'min-width:0;flex:1 1 auto;display:flex;flex-direction:column;gap:3px';
304
478
  const label = doc.createElement('div');
305
479
  label.textContent = system.label;
306
- label.style.cssText = 'color:var(--fps-editor-text-strong);font-size:12px;font-weight:900;line-height:1.25';
480
+ label.style.cssText = [
481
+ 'color:var(--fps-editor-text-strong)',
482
+ 'font-size:12px',
483
+ 'font-weight:900',
484
+ 'line-height:1.25',
485
+ 'min-width:0',
486
+ 'overflow:hidden',
487
+ 'text-overflow:ellipsis',
488
+ 'white-space:nowrap',
489
+ ].join(';');
307
490
  title.appendChild(label);
308
491
  if (system.summary) {
309
492
  const summary = doc.createElement('div');
310
493
  summary.textContent = system.summary;
311
- summary.style.cssText = 'margin-top:3px;color:var(--fps-editor-muted);font-size:11px;line-height:1.35';
494
+ summary.style.cssText = 'color:var(--fps-editor-muted);font-size:11px;line-height:1.35';
312
495
  title.appendChild(summary);
313
496
  }
314
- header.appendChild(title);
497
+ if (collapsible) {
498
+ titleGroup.appendChild(createRenderingDisclosureIcon(doc, block, system.id, 'editorRenderingSystemDisclosure'));
499
+ }
500
+ titleGroup.appendChild(title);
501
+ header.appendChild(titleGroup);
315
502
  const badges = doc.createElement('div');
316
- badges.style.cssText = 'display:flex;align-items:center;gap:4px;flex:0 0 auto';
503
+ badges.style.cssText = 'display:flex;align-items:center;justify-content:flex-end;gap:4px;flex:0 0 auto;max-width:55%;flex-wrap:wrap';
317
504
  if (system.active != null)
318
505
  badges.appendChild(createBadge(doc, system.active ? 'ON' : 'OFF', { compact: true, tone: system.active ? 'success' : 'default' }));
319
506
  if (system.readOnly)
320
507
  badges.appendChild(createBadge(doc, 'READONLY', { compact: true }));
321
508
  if (system.status)
322
509
  badges.appendChild(createBadge(doc, system.status, { compact: true, tone: system.active === false ? 'warning' : 'default' }));
510
+ for (const action of system.actions ?? []) {
511
+ badges.appendChild(createRenderingActionButton(doc, action, {
512
+ sectionId,
513
+ systemId: system.id,
514
+ buttonKind: 'compact',
515
+ }));
516
+ }
323
517
  header.appendChild(badges);
324
518
  block.appendChild(header);
519
+ if (system.progress) {
520
+ block.appendChild(createRenderingProgressBlock(doc, system.progress));
521
+ }
522
+ if (system.details?.length) {
523
+ block.appendChild(createRenderingDetailsBlock(doc, system.details));
524
+ }
325
525
  const propertyGrid = doc.createElement('div');
526
+ propertyGrid.dataset.editorRenderingSystemContent = system.id;
326
527
  propertyGrid.style.cssText = [
327
528
  'display:flex',
328
529
  'flex-direction:column',
329
530
  `gap:${isListLayout ? '5px' : '6px'}`,
531
+ ...(collapsible ? [
532
+ `margin-top:${isListLayout ? '6px' : '8px'}`,
533
+ ] : []),
330
534
  ...(isListLayout ? [
331
535
  'padding-left:0',
332
536
  ] : []),
@@ -337,9 +541,143 @@ function createRenderingSystemBlock(doc, sectionId, system, layout = 'cards') {
337
541
  block.appendChild(propertyGrid);
338
542
  return block;
339
543
  }
544
+ function createRenderingProgressBlock(doc, progress) {
545
+ const value = typeof progress.value === 'number' && Number.isFinite(progress.value)
546
+ ? Math.max(0, Math.min(1, progress.value))
547
+ : progress.indeterminate ? 0.42 : 0;
548
+ const block = doc.createElement('div');
549
+ block.dataset.editorRenderingProgress = 'true';
550
+ block.style.cssText = [
551
+ 'display:flex',
552
+ 'flex-direction:column',
553
+ 'gap:4px',
554
+ 'margin:0 0 8px',
555
+ ].join(';');
556
+ const label = doc.createElement('div');
557
+ label.textContent = progress.label;
558
+ label.style.cssText = [
559
+ 'color:var(--fps-editor-muted)',
560
+ 'font-size:10px',
561
+ 'font-weight:800',
562
+ 'line-height:1.2',
563
+ 'overflow:hidden',
564
+ 'text-overflow:ellipsis',
565
+ 'white-space:nowrap',
566
+ ].join(';');
567
+ const track = doc.createElement('div');
568
+ track.style.cssText = [
569
+ 'height:6px',
570
+ 'border-radius:999px',
571
+ 'border:1px solid var(--fps-editor-border)',
572
+ 'background:rgba(0,0,0,0.22)',
573
+ 'overflow:hidden',
574
+ ].join(';');
575
+ const fill = doc.createElement('div');
576
+ fill.style.cssText = [
577
+ `width:${Math.round(value * 100)}%`,
578
+ 'height:100%',
579
+ 'border-radius:999px',
580
+ 'background:linear-gradient(90deg, var(--fps-editor-accent), var(--fps-editor-accent-strong))',
581
+ 'transition:width 120ms linear',
582
+ ].join(';');
583
+ if (progress.indeterminate && progress.value == null) {
584
+ fill.style.background = 'linear-gradient(90deg, transparent, var(--fps-editor-accent), transparent)';
585
+ }
586
+ track.appendChild(fill);
587
+ block.appendChild(label);
588
+ block.appendChild(track);
589
+ return block;
590
+ }
591
+ function createRenderingDetailsBlock(doc, details) {
592
+ const block = doc.createElement('div');
593
+ block.dataset.editorRenderingDetails = 'true';
594
+ block.style.cssText = [
595
+ 'display:grid',
596
+ 'grid-template-columns:repeat(2,minmax(0,1fr))',
597
+ 'gap:4px',
598
+ 'margin:0 0 8px',
599
+ ].join(';');
600
+ for (const detail of details) {
601
+ const item = doc.createElement('div');
602
+ item.style.cssText = [
603
+ 'min-width:0',
604
+ 'padding:5px 6px',
605
+ 'border:1px solid var(--fps-editor-border)',
606
+ 'border-radius:3px',
607
+ 'background:rgba(0,0,0,0.12)',
608
+ ].join(';');
609
+ const label = doc.createElement('div');
610
+ label.textContent = detail.label;
611
+ label.style.cssText = [
612
+ 'color:var(--fps-editor-muted)',
613
+ 'font-size:9px',
614
+ 'font-weight:800',
615
+ 'line-height:1.1',
616
+ 'overflow:hidden',
617
+ 'text-overflow:ellipsis',
618
+ 'white-space:nowrap',
619
+ ].join(';');
620
+ const value = doc.createElement('div');
621
+ value.textContent = detail.value;
622
+ value.style.cssText = [
623
+ `color:${detail.tone === 'warning' ? 'var(--fps-editor-warn)' : detail.tone === 'error' ? 'var(--fps-editor-danger-text)' : detail.tone === 'success' ? 'var(--fps-editor-success)' : 'var(--fps-editor-text-strong)'}`,
624
+ 'font-size:11px',
625
+ 'font-weight:900',
626
+ 'line-height:1.25',
627
+ 'margin-top:2px',
628
+ 'overflow:hidden',
629
+ 'text-overflow:ellipsis',
630
+ 'white-space:nowrap',
631
+ ].join(';');
632
+ item.appendChild(label);
633
+ item.appendChild(value);
634
+ block.appendChild(item);
635
+ }
636
+ return block;
637
+ }
638
+ function createRenderingDisclosureIcon(doc, block, id, datasetKey) {
639
+ const disclosure = doc.createElement('span');
640
+ disclosure.dataset[datasetKey] = id;
641
+ disclosure.style.cssText = [
642
+ 'display:inline-flex',
643
+ 'align-items:center',
644
+ 'justify-content:center',
645
+ 'width:14px',
646
+ 'height:14px',
647
+ 'margin-top:1px',
648
+ 'flex:0 0 auto',
649
+ 'color:var(--fps-editor-muted)',
650
+ ].join(';');
651
+ const syncDisclosureIcon = () => {
652
+ clearElement(disclosure);
653
+ disclosure.appendChild(createLocalEditorIcon(doc, block.open ? 'chevron-down' : 'chevron-right', {
654
+ size: 14,
655
+ strokeWidth: 2.4,
656
+ }));
657
+ };
658
+ block.addEventListener('toggle', syncDisclosureIcon);
659
+ syncDisclosureIcon();
660
+ return disclosure;
661
+ }
340
662
  function createRenderingPropertyRow(doc, sectionId, systemId, property, systemReadOnly) {
341
663
  const inspectorProperty = createInspectorPropertyFromRenderingProperty(property, systemReadOnly);
342
- const control = createRenderingPropertyControl(doc, sectionId, systemId, property, inspectorProperty);
664
+ let control = createRenderingPropertyControl(doc, sectionId, systemId, property, inspectorProperty);
665
+ if (property.actions?.length) {
666
+ const controlWithActions = doc.createElement('div');
667
+ controlWithActions.style.cssText = 'display:flex;align-items:center;gap:5px;min-width:0';
668
+ control.style.minWidth = '0';
669
+ control.style.flex = '1 1 auto';
670
+ controlWithActions.appendChild(control);
671
+ for (const action of property.actions) {
672
+ controlWithActions.appendChild(createRenderingActionButton(doc, action, {
673
+ sectionId,
674
+ systemId,
675
+ path: property.path,
676
+ buttonKind: 'icon',
677
+ }));
678
+ }
679
+ control = controlWithActions;
680
+ }
343
681
  const access = getInspectorPropertyAccess(inspectorProperty);
344
682
  const effect = getInspectorPropertyEffect(inspectorProperty);
345
683
  const row = createPropertyRow(doc, inspectorProperty.label, control);
@@ -1245,6 +1583,13 @@ const builtinInspectorControlRegistrations = [
1245
1583
  customControl: 'open-right-dock-tab',
1246
1584
  render: ({ doc, property }) => createInspectorOpenRightDockTabControl(doc, property),
1247
1585
  },
1586
+ {
1587
+ id: 'builtin.rendering-action-button',
1588
+ order: 92,
1589
+ control: 'custom',
1590
+ customControl: 'rendering-action-button',
1591
+ render: ({ doc, property }) => createInspectorRenderingActionButtonControl(doc, property),
1592
+ },
1248
1593
  {
1249
1594
  id: 'builtin.asset-picker-card',
1250
1595
  order: 95,
@@ -1327,23 +1672,24 @@ function compareInspectorControlRegistrations(left, right) {
1327
1672
  return (left.order ?? 0) - (right.order ?? 0) || left.id.localeCompare(right.id);
1328
1673
  }
1329
1674
  function renderInspectorControl(doc, registrations, target, property) {
1330
- const canRenderCustomAction = property.control === 'custom' && !!property.customControl;
1331
- if (!isInspectorPropertyEditable(property) && !canRenderCustomAction)
1332
- return createInspectorReadonlyControl(doc, target, property);
1675
+ const normalizedProperty = normalizeInspectorRenderingActionProperty(property);
1676
+ const canRenderCustomAction = normalizedProperty.control === 'custom' && !!normalizedProperty.customControl;
1677
+ if (!isInspectorPropertyEditable(normalizedProperty) && !canRenderCustomAction)
1678
+ return createInspectorReadonlyControl(doc, target, normalizedProperty);
1333
1679
  const context = {
1334
1680
  doc,
1335
1681
  target,
1336
- property,
1682
+ property: normalizedProperty,
1337
1683
  bindInput(element, options) {
1338
- applyLocalEditorBrowserInspectorControlBinding(element, target, property, options);
1684
+ applyLocalEditorBrowserInspectorControlBinding(element, target, normalizedProperty, options);
1339
1685
  },
1340
1686
  };
1341
1687
  const registration = resolveLocalEditorBrowserInspectorControlRegistration(registrations, context);
1342
1688
  if (registration)
1343
1689
  return registration.render(context);
1344
- if (!isInspectorPropertyEditable(property))
1345
- return createInspectorReadonlyControl(doc, target, property);
1346
- return createInspectorReadonlyControl(doc, target, property);
1690
+ if (!isInspectorPropertyEditable(normalizedProperty))
1691
+ return createInspectorReadonlyControl(doc, target, normalizedProperty);
1692
+ return createInspectorReadonlyControl(doc, target, normalizedProperty);
1347
1693
  }
1348
1694
  export function resolveLocalEditorBrowserInspectorControlRegistration(registrations, context) {
1349
1695
  for (const registration of registrations) {
@@ -1353,12 +1699,48 @@ export function resolveLocalEditorBrowserInspectorControlRegistration(registrati
1353
1699
  return null;
1354
1700
  }
1355
1701
  function localEditorBrowserInspectorControlSupports(registration, context) {
1356
- if (registration.control && registration.control !== context.property.control)
1357
- return false;
1358
- if (registration.customControl && registration.customControl !== context.property.customControl)
1702
+ const renderingActionFallback = registration.customControl === 'rendering-action-button'
1703
+ && !!readInspectorRenderingActionId(context.property);
1704
+ if (registration.control && registration.control !== context.property.control && !renderingActionFallback)
1359
1705
  return false;
1706
+ if (registration.customControl && registration.customControl !== context.property.customControl) {
1707
+ if (!isInspectorCustomControlFallback(registration.customControl, context.property))
1708
+ return false;
1709
+ }
1360
1710
  return registration.supports?.(context) ?? true;
1361
1711
  }
1712
+ function normalizeInspectorRenderingActionProperty(property) {
1713
+ const actionId = readInspectorRenderingActionId(property);
1714
+ if (!actionId)
1715
+ return property;
1716
+ return {
1717
+ ...property,
1718
+ control: 'custom',
1719
+ customControl: 'rendering-action-button',
1720
+ controlOptions: {
1721
+ ...property.controlOptions,
1722
+ actionId,
1723
+ label: readInspectorControlOptionString(property, 'label') || property.label,
1724
+ icon: readInspectorControlOptionString(property, 'icon') || 'save',
1725
+ },
1726
+ readOnly: false,
1727
+ persistence: property.persistence === 'runtime' ? 'runtime' : 'document',
1728
+ };
1729
+ }
1730
+ function readInspectorRenderingActionId(property) {
1731
+ const explicit = readInspectorControlOptionString(property, 'actionId');
1732
+ if (explicit)
1733
+ return explicit;
1734
+ if (typeof property.value !== 'string')
1735
+ return '';
1736
+ const value = property.value.trim();
1737
+ return value && property.path.startsWith('actions.') ? value : '';
1738
+ }
1739
+ function isInspectorCustomControlFallback(customControl, property) {
1740
+ if (customControl !== 'rendering-action-button')
1741
+ return false;
1742
+ return !!readInspectorRenderingActionId(property);
1743
+ }
1362
1744
  function appendInspectorVectorInputs(doc, parent, inspectorObject, label, properties, layout = 'block', options = {}) {
1363
1745
  const wrapper = doc.createElement('div');
1364
1746
  wrapper.style.cssText = 'margin:8px 0';
@@ -1703,6 +2085,31 @@ function createInspectorOpenRightDockTabControl(doc, property) {
1703
2085
  ].filter(Boolean).join(';');
1704
2086
  return button;
1705
2087
  }
2088
+ function createInspectorRenderingActionButtonControl(doc, property) {
2089
+ const actionId = readInspectorControlOptionString(property, 'actionId')
2090
+ || (typeof property.value === 'string' ? property.value : '');
2091
+ const iconName = readInspectorControlOptionString(property, 'icon');
2092
+ const icon = isLocalEditorIconName(iconName) ? iconName : 'save';
2093
+ const label = readInspectorControlOptionString(property, 'label')
2094
+ || (typeof property.value === 'string' ? property.value : property.label);
2095
+ const button = createToolbarButton(doc, label, icon);
2096
+ button.type = 'button';
2097
+ if (actionId)
2098
+ button.dataset.editorRenderingAction = actionId;
2099
+ button.disabled = property.readOnly === true
2100
+ || property.effect === 'unsupported'
2101
+ || property.controlOptions?.disabled === true
2102
+ || !actionId;
2103
+ button.title = property.tooltip ?? label;
2104
+ button.dataset.editorTooltip = button.title;
2105
+ button.style.cssText = [
2106
+ button.style.cssText,
2107
+ 'width:100%',
2108
+ 'justify-content:center',
2109
+ 'height:28px',
2110
+ ].filter(Boolean).join(';');
2111
+ return button;
2112
+ }
1706
2113
  function createInspectorMaterialSlotListControl(doc, property) {
1707
2114
  const wrapper = doc.createElement('div');
1708
2115
  wrapper.dataset.editorInspectorMaterialSlotList = 'true';
@@ -2111,11 +2518,22 @@ function createLegacyInspectorSections(properties) {
2111
2518
  for (const [index, property] of properties.entries()) {
2112
2519
  const id = property.path.split('.')[0] || 'properties';
2113
2520
  const section = sections.get(id) ?? { order: sections.size, properties: [] };
2521
+ const renderingActionId = readLegacyRenderingActionId(property);
2114
2522
  section.properties.push({
2115
2523
  path: property.path,
2116
2524
  label: property.label,
2117
2525
  valueType: property.valueType,
2118
- control: inferLegacyInspectorControl(property),
2526
+ control: renderingActionId ? 'custom' : inferLegacyInspectorControl(property),
2527
+ ...(renderingActionId
2528
+ ? {
2529
+ customControl: 'rendering-action-button',
2530
+ controlOptions: {
2531
+ actionId: renderingActionId,
2532
+ label: property.label,
2533
+ icon: 'save',
2534
+ },
2535
+ }
2536
+ : {}),
2119
2537
  value: property.value,
2120
2538
  mixed: property.mixed,
2121
2539
  readOnly: property.readOnly === true,
@@ -2135,6 +2553,12 @@ function createLegacyInspectorSections(properties) {
2135
2553
  properties: section.properties,
2136
2554
  }));
2137
2555
  }
2556
+ function readLegacyRenderingActionId(property) {
2557
+ if (typeof property.value !== 'string')
2558
+ return '';
2559
+ const value = property.value.trim();
2560
+ return value && property.path.startsWith('actions.') ? value : '';
2561
+ }
2138
2562
  function createSelectionSummaryInspectorObject(state) {
2139
2563
  const targetIds = state.selectedIds;
2140
2564
  if (targetIds.length === 0)