@fps-games/editor 0.2.1-beta.3 → 0.2.1-beta.4
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.
- package/dist/build-info.json +44 -44
- package/dist/editor-commands/capabilities/assets.d.ts +8 -0
- package/dist/editor-commands/capabilities/assets.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/assets.js +41 -41
- package/dist/editor-commands/capabilities/assets.js.map +1 -0
- package/dist/editor-commands/capabilities/editor-state.d.ts +5 -0
- package/dist/editor-commands/capabilities/editor-state.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/editor-state.js +22 -22
- package/dist/editor-commands/capabilities/editor-state.js.map +1 -0
- package/dist/editor-commands/capabilities/hierarchy.d.ts +4 -0
- package/dist/editor-commands/capabilities/hierarchy.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/hierarchy.js +5 -5
- package/dist/editor-commands/capabilities/hierarchy.js.map +1 -0
- package/dist/editor-commands/capabilities/host-lifecycle.d.ts +11 -0
- package/dist/editor-commands/capabilities/host-lifecycle.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/host-lifecycle.js +149 -0
- package/dist/editor-commands/capabilities/host-lifecycle.js.map +1 -0
- package/dist/editor-commands/capabilities/prefabs.d.ts +5 -0
- package/dist/editor-commands/capabilities/prefabs.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/prefabs.js +93 -93
- package/dist/editor-commands/capabilities/prefabs.js.map +1 -0
- package/dist/editor-commands/capabilities/scene-objects.d.ts +8 -0
- package/dist/editor-commands/capabilities/scene-objects.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/scene-objects.js +480 -0
- package/dist/editor-commands/capabilities/scene-objects.js.map +1 -0
- package/dist/editor-commands/capabilities/selection.d.ts +5 -0
- package/dist/editor-commands/capabilities/selection.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/selection.js +60 -0
- package/dist/editor-commands/capabilities/selection.js.map +1 -0
- package/dist/editor-commands/capabilities/shadows.d.ts +5 -0
- package/dist/editor-commands/capabilities/shadows.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/shadows.js +74 -74
- package/dist/editor-commands/capabilities/shadows.js.map +1 -0
- package/dist/editor-commands/capabilities/transform.d.ts +5 -0
- package/dist/editor-commands/capabilities/transform.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/transform.js +164 -0
- package/dist/editor-commands/capabilities/transform.js.map +1 -0
- package/dist/editor-commands/capabilities/ui-regions.d.ts +4 -0
- package/dist/editor-commands/capabilities/ui-regions.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/ui-regions.js +55 -57
- package/dist/editor-commands/capabilities/ui-regions.js.map +1 -0
- package/dist/editor-commands/capabilities/viewport.d.ts +5 -0
- package/dist/editor-commands/capabilities/viewport.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/viewport.js +100 -100
- package/dist/editor-commands/capabilities/viewport.js.map +1 -0
- package/dist/editor-commands/command-sources.d.ts +7 -0
- package/dist/editor-commands/command-sources.d.ts.map +1 -0
- package/dist/editor-commands/command-sources.js +34 -0
- package/dist/editor-commands/command-sources.js.map +1 -0
- package/dist/editor-commands/diagnostics.d.ts +12 -0
- package/dist/editor-commands/diagnostics.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/diagnostics.js +4 -4
- package/dist/editor-commands/diagnostics.js.map +1 -0
- package/dist/{agent-bridge → editor-commands}/index.d.ts +1 -1
- package/dist/editor-commands/index.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/index.js +1 -1
- package/dist/editor-commands/index.js.map +1 -0
- package/dist/editor-commands/register.d.ts +4 -0
- package/dist/editor-commands/register.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/register.js +323 -286
- package/dist/editor-commands/register.js.map +1 -0
- package/dist/{agent-bridge → editor-commands}/shared.d.ts +80 -80
- package/dist/editor-commands/shared.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/shared.js +29 -29
- package/dist/editor-commands/shared.js.map +1 -0
- package/dist/editor-commands/source-types.d.ts +110 -0
- package/dist/editor-commands/source-types.d.ts.map +1 -0
- package/dist/editor-commands/source-types.js.map +1 -0
- package/dist/editor-plugin-commands.d.ts +4 -0
- package/dist/editor-plugin-commands.d.ts.map +1 -0
- package/dist/editor-plugin-commands.js +18 -0
- package/dist/editor-plugin-commands.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/local-editor-commands.d.ts +2 -0
- package/dist/local-editor-commands.d.ts.map +1 -0
- package/dist/local-editor-commands.js +2 -0
- package/dist/local-editor-commands.js.map +1 -0
- package/dist/local-editor-harness.d.ts +35 -21
- package/dist/local-editor-harness.d.ts.map +1 -1
- package/dist/local-editor-harness.js +1721 -367
- package/dist/local-editor-harness.js.map +1 -1
- package/dist/local-editor-prefab-stage-transaction.d.ts +2 -1
- package/dist/local-editor-prefab-stage-transaction.d.ts.map +1 -1
- package/dist/local-editor-prefab-stage-transaction.js +6 -5
- package/dist/local-editor-prefab-stage-transaction.js.map +1 -1
- package/dist/local-editor-scene-view-interaction-runtime.d.ts.map +1 -1
- package/dist/local-editor-scene-view-interaction-runtime.js +2 -5
- package/dist/local-editor-scene-view-interaction-runtime.js.map +1 -1
- package/dist/playable-local-editor-entry.d.ts +10 -0
- package/dist/playable-local-editor-entry.d.ts.map +1 -1
- package/dist/playable-local-editor-entry.js +10 -2
- package/dist/playable-local-editor-entry.js.map +1 -1
- package/dist/playable-local-editor-host.d.ts +3 -32
- package/dist/playable-local-editor-host.d.ts.map +1 -1
- package/dist/playable-local-editor-host.js +6 -70
- package/dist/playable-local-editor-host.js.map +1 -1
- package/dist/playable-product-local-editor.d.ts +1 -2
- package/dist/playable-product-local-editor.d.ts.map +1 -1
- package/dist/playable-product-local-editor.js +0 -1
- package/dist/playable-product-local-editor.js.map +1 -1
- package/dist/playable-product-projection-preview.d.ts.map +1 -1
- package/dist/playable-product-projection-preview.js +1 -1
- package/dist/playable-product-projection-preview.js.map +1 -1
- package/dist/playable-product-scene-capabilities.d.ts +0 -2
- package/dist/playable-product-scene-capabilities.d.ts.map +1 -1
- package/dist/playable-product-scene-capabilities.js +33 -6
- package/dist/playable-product-scene-capabilities.js.map +1 -1
- package/dist/playable-runtime-babylon.d.ts +4 -0
- package/dist/playable-runtime-babylon.d.ts.map +1 -1
- package/dist/playable-runtime-babylon.js +4 -0
- package/dist/playable-runtime-babylon.js.map +1 -1
- package/dist/playable-sdk.d.ts +1 -1
- package/dist/playable-sdk.d.ts.map +1 -1
- package/dist/playable-sdk.js.map +1 -1
- package/dist/playable-standard-project.d.ts +0 -2
- package/dist/playable-standard-project.d.ts.map +1 -1
- package/dist/playable-standard-project.js +1 -2
- package/dist/playable-standard-project.js.map +1 -1
- package/dist/project-service-projection.d.ts +16 -0
- package/dist/project-service-projection.d.ts.map +1 -0
- package/dist/project-service-projection.js +67 -0
- package/dist/project-service-projection.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.d.ts +18 -0
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.d.ts.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.js +54 -18
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/package.json +9 -9
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.js +127 -13
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +66 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/package.json +6 -6
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.d.ts +32 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.js +254 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts +3 -1
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/index.js +2 -0
- package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.d.ts +68 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.js +650 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.d.ts +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.js +22 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts +8 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +117 -6
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts +14 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js +100 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts +8 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +75 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +37 -12
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +25 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +332 -107
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/package.json +7 -7
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.d.ts +107 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.js +1211 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.d.ts +34 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.js +260 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.d.ts +9 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.js +14 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.d.ts +18 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.js +113 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.d.ts +82 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.js +1098 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.d.ts +6 -7
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.js +62 -103
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.d.ts +30 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.js +540 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.d.ts +9 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.js +61 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +55 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-session.js +247 -6
- package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/index.d.ts +6 -2
- package/node_modules/@fps-games/editor-core/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/index.js +6 -2
- package/node_modules/@fps-games/editor-core/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-core/package.json +6 -6
- package/node_modules/@fps-games/editor-forge-play/dist/index.d.ts +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.js +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/bridge-command/protocol.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/bridge-command/protocol.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +41 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.d.ts +27 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js +214 -7
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.js +11 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.d.ts +2 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.js +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js +77 -31
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.d.ts +8 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.d.ts +21 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.js +90 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts +27 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js +161 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.d.ts +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.js +5 -92
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.d.ts +7 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.js +26 -9
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.d.ts +9 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.js +19 -8
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.d.ts +5 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.js +16 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.d.ts +9 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.js +12 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.d.ts +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.js +10 -5
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.js +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.d.ts +17 -82
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.js +53 -57
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.js +3 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.d.ts +10 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.js +256 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.js +7 -5
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +8 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js +134 -12
- package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.js +47 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.d.ts +27 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.js +592 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts +3 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js +61 -6
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.d.ts +0 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.js +1 -10
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.js +21 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.d.ts +13 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.js +18 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.d.ts +28 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.js +863 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/package.json +6 -6
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.d.ts +1626 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/{agent-bridge.js → editor-command-capabilities.js} +766 -620
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.d.ts +69 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.js +22 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.d.ts +136 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.js +2 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.d.ts +225 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.js +4 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts +6 -3
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/index.js +6 -3
- package/node_modules/@fps-games/editor-protocol/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-protocol/package.json +2 -2
- package/node_modules/@fps-games/editor-tooling/package.json +3 -3
- package/node_modules/@fps-games/editor-ui/package.json +1 -1
- package/node_modules/@fps-games/playable-assets/package.json +1 -1
- package/node_modules/@fps-games/playable-contracts/package.json +1 -1
- package/node_modules/@fps-games/playable-rendering/package.json +2 -2
- package/node_modules/@fps-games/playable-runtime/package.json +12 -12
- package/node_modules/@fps-games/playable-runtime-data/package.json +4 -4
- package/node_modules/@fps-games/playable-scene/package.json +2 -2
- package/node_modules/@fps-games/plugin-api/package.json +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-assets/package.json +6 -6
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.d.ts +1 -0
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.d.ts.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.js +78 -4
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.js.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/package.json +5 -5
- package/node_modules/@fps-games/plugin-host/package.json +2 -2
- package/node_modules/@fps-games/plugin-markers/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-markers/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-markers/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-markers/package.json +5 -5
- package/node_modules/@fps-games/plugin-materials/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-materials/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-materials/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-materials/package.json +5 -5
- package/node_modules/@fps-games/plugin-rendering/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-rendering/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-rendering/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-rendering/package.json +5 -5
- package/node_modules/@fps-games/plugin-scene/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-scene/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-scene/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-scene/package.json +5 -5
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/package.json +5 -5
- package/node_modules/@fps-games/plugin-shadows/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-shadows/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-shadows/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-shadows/package.json +7 -7
- package/package.json +23 -23
- package/dist/agent-bridge/capabilities/assets.d.ts +0 -8
- package/dist/agent-bridge/capabilities/assets.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/assets.js.map +0 -1
- package/dist/agent-bridge/capabilities/editor-state.d.ts +0 -5
- package/dist/agent-bridge/capabilities/editor-state.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/editor-state.js.map +0 -1
- package/dist/agent-bridge/capabilities/hierarchy.d.ts +0 -4
- package/dist/agent-bridge/capabilities/hierarchy.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/hierarchy.js.map +0 -1
- package/dist/agent-bridge/capabilities/host-lifecycle.d.ts +0 -11
- package/dist/agent-bridge/capabilities/host-lifecycle.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/host-lifecycle.js +0 -149
- package/dist/agent-bridge/capabilities/host-lifecycle.js.map +0 -1
- package/dist/agent-bridge/capabilities/prefabs.d.ts +0 -5
- package/dist/agent-bridge/capabilities/prefabs.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/prefabs.js.map +0 -1
- package/dist/agent-bridge/capabilities/scene-objects.d.ts +0 -8
- package/dist/agent-bridge/capabilities/scene-objects.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/scene-objects.js +0 -480
- package/dist/agent-bridge/capabilities/scene-objects.js.map +0 -1
- package/dist/agent-bridge/capabilities/selection.d.ts +0 -5
- package/dist/agent-bridge/capabilities/selection.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/selection.js +0 -60
- package/dist/agent-bridge/capabilities/selection.js.map +0 -1
- package/dist/agent-bridge/capabilities/shadows.d.ts +0 -5
- package/dist/agent-bridge/capabilities/shadows.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/shadows.js.map +0 -1
- package/dist/agent-bridge/capabilities/transform.d.ts +0 -5
- package/dist/agent-bridge/capabilities/transform.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/transform.js +0 -164
- package/dist/agent-bridge/capabilities/transform.js.map +0 -1
- package/dist/agent-bridge/capabilities/ui-regions.d.ts +0 -4
- package/dist/agent-bridge/capabilities/ui-regions.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/ui-regions.js.map +0 -1
- package/dist/agent-bridge/capabilities/viewport.d.ts +0 -5
- package/dist/agent-bridge/capabilities/viewport.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/viewport.js.map +0 -1
- package/dist/agent-bridge/capability-sources.d.ts +0 -7
- package/dist/agent-bridge/capability-sources.d.ts.map +0 -1
- package/dist/agent-bridge/capability-sources.js +0 -34
- package/dist/agent-bridge/capability-sources.js.map +0 -1
- package/dist/agent-bridge/diagnostics.d.ts +0 -12
- package/dist/agent-bridge/diagnostics.d.ts.map +0 -1
- package/dist/agent-bridge/diagnostics.js.map +0 -1
- package/dist/agent-bridge/index.d.ts.map +0 -1
- package/dist/agent-bridge/index.js.map +0 -1
- package/dist/agent-bridge/register.d.ts +0 -4
- package/dist/agent-bridge/register.d.ts.map +0 -1
- package/dist/agent-bridge/register.js.map +0 -1
- package/dist/agent-bridge/shared.d.ts.map +0 -1
- package/dist/agent-bridge/shared.js.map +0 -1
- package/dist/agent-bridge/source-types.d.ts +0 -110
- package/dist/agent-bridge/source-types.d.ts.map +0 -1
- package/dist/agent-bridge/source-types.js.map +0 -1
- package/dist/editor-plugin-agent-capabilities.d.ts +0 -4
- package/dist/editor-plugin-agent-capabilities.d.ts.map +0 -1
- package/dist/editor-plugin-agent-capabilities.js +0 -64
- package/dist/editor-plugin-agent-capabilities.js.map +0 -1
- package/dist/local-editor-agent-actions.d.ts +0 -43
- package/dist/local-editor-agent-actions.d.ts.map +0 -1
- package/dist/local-editor-agent-actions.js +0 -321
- package/dist/local-editor-agent-actions.js.map +0 -1
- package/dist/local-editor-agent-bridge-transport.d.ts +0 -129
- package/dist/local-editor-agent-bridge-transport.d.ts.map +0 -1
- package/dist/local-editor-agent-bridge-transport.js +0 -403
- package/dist/local-editor-agent-bridge-transport.js.map +0 -1
- package/dist/local-editor-agent-bridge.d.ts +0 -2
- package/dist/local-editor-agent-bridge.d.ts.map +0 -1
- package/dist/local-editor-agent-bridge.js +0 -2
- package/dist/local-editor-agent-bridge.js.map +0 -1
- package/dist/local-editor-agent-context.d.ts +0 -68
- package/dist/local-editor-agent-context.d.ts.map +0 -1
- package/dist/local-editor-agent-context.js +0 -716
- package/dist/local-editor-agent-context.js.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts +0 -22
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.js +0 -106
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.js.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.d.ts +0 -17
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.js +0 -14
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.js.map +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.d.ts +0 -23
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.js +0 -47
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.js.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.d.ts +0 -112
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.js +0 -159
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.js.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.d.ts +0 -15
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.js +0 -76
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts +0 -1622
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts +0 -68
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js +0 -23
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts +0 -187
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent.js +0 -5
- package/node_modules/@fps-games/editor-protocol/dist/agent.js.map +0 -1
- /package/dist/{agent-bridge → editor-commands}/source-types.js +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { createEditorSession, FPS_EDITOR_ACTIVE_TOOL_CHANGED, FPS_EDITOR_DOCUMENT_CHANGED, FPS_EDITOR_HISTORY_CHANGED, FPS_EDITOR_SELECTION_CHANGED,
|
|
1
|
+
import { createEditorAuthoringHost, createEditorSession, FPS_EDITOR_ACTIVE_TOOL_CHANGED, FPS_EDITOR_DOCUMENT_CHANGED, FPS_EDITOR_HISTORY_CHANGED, FPS_EDITOR_SELECTION_CHANGED, createEditorCommandCapabilityAdapter, createEditorCommandSystem, createInspectorRegistry, DEFAULT_EDITOR_TRANSFORM_OPERATION_SETTINGS, DEFAULT_EDITOR_VIEWPORT_TOOL_STATE, createEmptyEditorViewportSpatialOverlayState, callWithEditorAuthoringSerializedAccess, createEditorAuthoringSerializedSessionView, cloneEditorTransformSnapshot as cloneCoreEditorTransformSnapshot, composeEditorTransformMatrix, editorTransformMatricesAlmostEqual, cloneEditorViewportToolState, cloneEditorViewportSpatialOverlayState, aggregateInspectorObjectsToMultiObject, createInspectorEditPayload, compareInspectorSections, computeEditorTransformActionTargets, mergeInspectorSections, isEditorTransformTrsSnapshot, normalizeEditorTransformConstraint, readEditorTransformPosition, resolveEditorSelectionCommand, validateSceneGraphDelete, validateSceneGraphDrop, validateSceneGraphGroupSelection, validateSceneGraphMove, validateSceneGraphRename, } from '@fps-games/editor-core';
|
|
2
2
|
import { createEditorToolManager, createEditorToolRegistry, resolveEditingContextProvider, } from '@fps-games/editor-core/tools';
|
|
3
3
|
import { createEditorDiagnosticStore, normalizeEditorDiagnostic, normalizeEditorDiagnosticDetails, } from '@fps-games/editor-core/diagnostics';
|
|
4
|
-
import {} from '@fps-games/editor-protocol';
|
|
5
|
-
import { createLocalEditorBrowserUi, resolveLocalEditorBrowserAssetKind, resolveLocalEditorStatusDiagnosticLocator, toTransformOperationPolicyStatusLabel, } from '@fps-games/editor-browser';
|
|
4
|
+
import { EDITOR_COMMAND_ID, } from '@fps-games/editor-protocol';
|
|
5
|
+
import { createLocalEditorBrowserUi, createLocalEditorCommandServiceClient, resolveLocalEditorBrowserAssetKind, resolveLocalEditorStatusDiagnosticLocator, toTransformOperationPolicyStatusLabel, } from '@fps-games/editor-browser';
|
|
6
|
+
import { classifyProjectServiceSnapshot, createProjectServiceProjectionSessionAuthority, shouldReplacePendingProjectServiceSnapshot, waitForProjectServiceOperation, } from './project-service-projection.js';
|
|
6
7
|
import { mountLocalEditorProjectModelPreview, resolveLocalEditorProjectModelThumbnail, } from './internal/project-model-preview.js';
|
|
7
8
|
import { mountLocalEditorMaterialPreview } from './internal/material-preview.js';
|
|
8
9
|
import { bindFpsEditorTools, } from '@fps-games/editor-core/plugin-host';
|
|
@@ -17,14 +18,12 @@ import { createPlayableBabylonOutlineInspectorSection, createPlayableBabylonOutl
|
|
|
17
18
|
import { createLocalEditorViewportRenderCoordinator, } from './local-editor-viewport-render-coordinator.js';
|
|
18
19
|
import { createLocalEditorSceneViewInteractionRuntime, } from './local-editor-scene-view-interaction-runtime.js';
|
|
19
20
|
import { cloneLocalEditorPerformanceStats, countLocalEditorAuthoredObjects, createLocalEditorPerformanceStats, LOCAL_EDITOR_PERFORMANCE_MONITOR_REASON, } from './local-editor-performance-stats.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { registerLocalEditorCommandCapabilities } from './local-editor-commands.js';
|
|
22
|
+
import { registerEditorPluginCommands } from './editor-plugin-commands.js';
|
|
22
23
|
import { createLocalEditorStandardToolRegistrations, LOCAL_EDITOR_SELECTION_CAPABILITY_ID, LOCAL_EDITOR_STANDARD_TOOL_IDS, LOCAL_EDITOR_TRANSFORM_CAPABILITY_ID, resolveLocalEditorTransformTool, } from './local-editor-tools.js';
|
|
23
24
|
import { createHierarchyScopeSnapshot, createHierarchyTreeSnapshot, resolveHierarchyScopeProviders, resolveHierarchySurfaceContribution, } from '@fps-games/plugin-hierarchy';
|
|
24
|
-
import {
|
|
25
|
-
import { createDisabledLocalEditorAgentBridgeTransportStatus, createLocalEditorAgentBridgeWebSocketTransportFromQuery, } from './local-editor-agent-bridge-transport.js';
|
|
25
|
+
import { createLocalEditorCommandCapabilitySources, } from './editor-commands/command-sources.js';
|
|
26
26
|
import { PLAYABLE_LOCAL_EDITOR_APPLICATION_SCOPE_ID, PLAYABLE_LOCAL_EDITOR_MAIN_DOCUMENT_SCOPE_ID, PLAYABLE_LOCAL_EDITOR_MAIN_PREVIEW_SCOPE_ID, PLAYABLE_LOCAL_EDITOR_MAIN_SESSION_SCOPE_ID, PLAYABLE_LOCAL_EDITOR_PROJECT_SCOPE_ID, } from '@fps-games/editor-playable-sdk/internal/local-harness';
|
|
27
|
-
import { FPS_EDITOR_LIFECYCLE_TRANSITION_TYPES } from '@fps-games/editor-core/lifecycle';
|
|
28
27
|
import { createMarkerGraphHierarchyItems, createMarkerGraphInspectorObject, createMarkerGraphRootInspectorObject, createMarkerPanelState, createMarkerRelationCommand, createMarkerRelationCreateManyCommand, createMarkerRelationDeleteConnectedCommand, createMarkerRelationReverseCommand, createMarkerGraphPatchFromInspectorEdit, findSpatialMarkerById, getSpatialMarkerDirectRelations, isMarkerGraphHierarchyId, isMarkerGraphHierarchyRootId, isMarkerGraphHierarchyRootRowId, isSpatialMarkerBackedByHierarchyRow, isSpatialMarkerHierarchyVisible, readMarkerGraphHierarchyMarkerIdForGraph, readSpatialMarkerIdFromHierarchySelection, } from './local-editor-marker-graph.js';
|
|
29
28
|
const BATCH_EDIT_REQUIRES_MULTI_PATCH_REASON = 'Batch edit requires multi-property patch support.';
|
|
30
29
|
const LARGE_SELECTION_THRESHOLD = 200;
|
|
@@ -32,6 +31,7 @@ const LARGE_SHADOW_METADATA_BATCH_THRESHOLD = 200;
|
|
|
32
31
|
const EDITOR_PROJECTION_VALIDATION_TIMEOUT_MS = 10000;
|
|
33
32
|
const EDITOR_WORLD_DISPOSE_BOUNDARY_DELAY_MS = 500;
|
|
34
33
|
const RENDERING_ACTION_PROGRESS_MIN_VISIBLE_MS = 1000;
|
|
34
|
+
const SERIALIZED_HIERARCHY_INVOCATION = Symbol('fps.editor.serialized-hierarchy-invocation');
|
|
35
35
|
const PREFAB_STAGE_CONTEXT_ACTION_IDS = Object.freeze({
|
|
36
36
|
save: 'fps.editor.context.prefab.save',
|
|
37
37
|
discard: 'fps.editor.context.prefab.discard',
|
|
@@ -264,22 +264,36 @@ export function createLocalEditorHarness(options) {
|
|
|
264
264
|
}
|
|
265
265
|
function createLocalEditorHarnessImplementation(options, construction) {
|
|
266
266
|
const root = options.root ?? document.body;
|
|
267
|
+
const projectCommandService = createLocalEditorCommandServiceClient();
|
|
268
|
+
const browserCommandAttachmentId = `browser-command-host-${createLocalEditorAuthoringServiceInstanceId()}`;
|
|
269
|
+
let disposeBrowserCommandAttachment = null;
|
|
270
|
+
let projectedServiceInstanceId = null;
|
|
271
|
+
let projectedServiceRevision = null;
|
|
272
|
+
let projectedBrowserDocumentFingerprint = null;
|
|
273
|
+
let pendingProjectServiceSnapshot = null;
|
|
274
|
+
let stopProjectServiceWatch = null;
|
|
267
275
|
let lifecycleController = null;
|
|
268
276
|
let releaseApplicationAuthorityScopeResource = null;
|
|
269
277
|
let releaseLifecycleRenderScopeResource = null;
|
|
270
278
|
let unsubscribeLifecycleRender = null;
|
|
271
|
-
let
|
|
272
|
-
|
|
279
|
+
let suppressedDocumentMarkDirtyTransitionId = null;
|
|
280
|
+
let lifecyclePresentationOnlyRenderDepth = 0;
|
|
273
281
|
let releaseMainSessionScopeResource = null;
|
|
274
282
|
let releaseMainPreviewScopeResource = null;
|
|
275
283
|
let pendingScheduledLifecycleExit = null;
|
|
276
284
|
let harnessDisposed = false;
|
|
285
|
+
const commandServiceCommandSystem = createEditorCommandSystem();
|
|
286
|
+
const projectionSessionAuthority = createProjectServiceProjectionSessionAuthority();
|
|
287
|
+
const replaceProjectionSessionAuthority = (session) => projectionSessionAuthority.replace(session);
|
|
288
|
+
const runProjectionSessionMutation = (session, mutation) => projectionSessionAuthority.run(session, mutation);
|
|
277
289
|
const state = {
|
|
278
290
|
get mode() {
|
|
291
|
+
if (state.session)
|
|
292
|
+
return 'editor';
|
|
279
293
|
const lifecycleMode = lifecycleController?.lifecycle.getSnapshot().mode;
|
|
280
294
|
if (lifecycleMode)
|
|
281
295
|
return lifecycleMode === 'edit' ? 'editor' : 'game';
|
|
282
|
-
return
|
|
296
|
+
return 'game';
|
|
283
297
|
},
|
|
284
298
|
get lifecycle() {
|
|
285
299
|
return lifecycleController?.lifecycle ?? null;
|
|
@@ -294,6 +308,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
294
308
|
hierarchyItemsCacheSession: null,
|
|
295
309
|
hierarchyItemsCacheRevision: -1,
|
|
296
310
|
hierarchyItemsCache: Object.freeze([]),
|
|
311
|
+
hierarchyPresentationFallbackRevision: 0,
|
|
297
312
|
diagnosticStore: createEditorDiagnosticStore(),
|
|
298
313
|
diagnosticPhase: 'edit',
|
|
299
314
|
reuseDiagnosticSnapshotOnNextRender: false,
|
|
@@ -303,6 +318,17 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
303
318
|
busy: false,
|
|
304
319
|
documentOperationActive: false,
|
|
305
320
|
session: null,
|
|
321
|
+
authoringHost: null,
|
|
322
|
+
projectAuthoringSnapshot: null,
|
|
323
|
+
replaceProjectionSessionAuthority,
|
|
324
|
+
runBrowserAuthoringMutation: async () => {
|
|
325
|
+
throw new Error('Browser authoring authority is unavailable.');
|
|
326
|
+
},
|
|
327
|
+
tryRunBrowserAuthoringMutationImmediately: () => ({
|
|
328
|
+
ok: false,
|
|
329
|
+
reason: 'Browser authoring authority is unavailable.',
|
|
330
|
+
}),
|
|
331
|
+
reconcilePendingProjectServiceSnapshot: async () => { },
|
|
306
332
|
createSessionChangeObserver: () => () => { },
|
|
307
333
|
handleSessionObserverError: () => { },
|
|
308
334
|
source: null,
|
|
@@ -345,8 +371,13 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
345
371
|
sceneViewSpatialOverlay: null,
|
|
346
372
|
selectionController: null,
|
|
347
373
|
selectionInspectorRefreshGeneration: 0,
|
|
348
|
-
selectionInspectorRefreshFrame: null,
|
|
349
374
|
selectionInspectorRefreshTimeout: null,
|
|
375
|
+
suppressDocumentMarkDirtyInspectorRefresh: false,
|
|
376
|
+
suppressedProjectionInspectorRefreshBatchIds: new Set(),
|
|
377
|
+
suppressedProjectionInspectorRefreshNodeBatches: new Map(),
|
|
378
|
+
inspectorPresentationGeneration: 0,
|
|
379
|
+
inspectorPresentationFrame: null,
|
|
380
|
+
inspectorPresentationPatches: null,
|
|
350
381
|
sceneRenderScheduler: null,
|
|
351
382
|
viewportRenderCoordinator: null,
|
|
352
383
|
sceneFrameStats: null,
|
|
@@ -383,10 +414,387 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
383
414
|
statusDetails: '',
|
|
384
415
|
renderingAction: null,
|
|
385
416
|
summary: '',
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
417
|
+
commandService: createEditorCommandCapabilityAdapter({
|
|
418
|
+
commandSystem: commandServiceCommandSystem,
|
|
419
|
+
resolveAuthoringRevision: () => projectCommandService
|
|
420
|
+
? projectedServiceRevision
|
|
421
|
+
: state.authoringHost?.getSnapshot().documentRevision ?? null,
|
|
422
|
+
}),
|
|
423
|
+
unregisterCommandCapabilities: null,
|
|
424
|
+
};
|
|
425
|
+
let browserAuthoringMutationSequence = 0;
|
|
426
|
+
let projectServiceSyncTail = Promise.resolve();
|
|
427
|
+
let projectServiceSyncPending = 0;
|
|
428
|
+
const acquireProjectServiceSync = async () => {
|
|
429
|
+
projectServiceSyncPending += 1;
|
|
430
|
+
const previous = projectServiceSyncTail;
|
|
431
|
+
let releaseCurrent;
|
|
432
|
+
projectServiceSyncTail = new Promise(resolve => { releaseCurrent = resolve; });
|
|
433
|
+
await previous;
|
|
434
|
+
let active = true;
|
|
435
|
+
return () => {
|
|
436
|
+
if (!active)
|
|
437
|
+
return;
|
|
438
|
+
active = false;
|
|
439
|
+
projectServiceSyncPending -= 1;
|
|
440
|
+
releaseCurrent();
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
const tryAcquireProjectServiceSync = () => {
|
|
444
|
+
if (projectServiceSyncPending > 0)
|
|
445
|
+
return null;
|
|
446
|
+
projectServiceSyncPending = 1;
|
|
447
|
+
let releaseCurrent;
|
|
448
|
+
projectServiceSyncTail = new Promise(resolve => { releaseCurrent = resolve; });
|
|
449
|
+
let active = true;
|
|
450
|
+
return () => {
|
|
451
|
+
if (!active)
|
|
452
|
+
return;
|
|
453
|
+
active = false;
|
|
454
|
+
projectServiceSyncPending = 0;
|
|
455
|
+
releaseCurrent();
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
const readProjectServiceSnapshot = async () => {
|
|
459
|
+
if (!projectCommandService)
|
|
460
|
+
return null;
|
|
461
|
+
const response = await projectCommandService.request({ kind: 'authoring.snapshot' });
|
|
462
|
+
if (!response.ok || response.kind !== 'authoring.snapshot'
|
|
463
|
+
|| response.result.kind !== 'snapshot-required')
|
|
464
|
+
return null;
|
|
465
|
+
return response.result.snapshot;
|
|
466
|
+
};
|
|
467
|
+
const commitProjectAuthoringProjection = (snapshot, documentFingerprint = createLocalEditorDocumentFingerprint(snapshot.document)) => {
|
|
468
|
+
state.projectAuthoringSnapshot = {
|
|
469
|
+
serviceInstanceId: snapshot.serviceInstanceId,
|
|
470
|
+
documentRevision: snapshot.documentRevision,
|
|
471
|
+
dirty: snapshot.dirty,
|
|
472
|
+
canUndo: snapshot.canUndo,
|
|
473
|
+
canRedo: snapshot.canRedo,
|
|
474
|
+
history: snapshot.history
|
|
475
|
+
? { entries: snapshot.history.entries.map(entry => ({ ...entry })) }
|
|
476
|
+
: { entries: [] },
|
|
477
|
+
};
|
|
478
|
+
projectedServiceRevision = snapshot.documentRevision;
|
|
479
|
+
projectedServiceInstanceId = snapshot.serviceInstanceId;
|
|
480
|
+
projectedBrowserDocumentFingerprint = documentFingerprint;
|
|
481
|
+
if (pendingProjectServiceSnapshot?.serviceInstanceId === snapshot.serviceInstanceId
|
|
482
|
+
&& pendingProjectServiceSnapshot.documentRevision === snapshot.documentRevision) {
|
|
483
|
+
pendingProjectServiceSnapshot = null;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
const invokeProjectServiceCommand = async (commandId, input = {}, expectedDocumentRevision) => {
|
|
487
|
+
if (!projectCommandService)
|
|
488
|
+
throw new Error('Project Editor Service is unavailable.');
|
|
489
|
+
if (projectedServiceRevision === null || projectedServiceInstanceId === null) {
|
|
490
|
+
const snapshot = await readProjectServiceSnapshot();
|
|
491
|
+
if (snapshot)
|
|
492
|
+
await applyProjectServiceSnapshot(snapshot, true);
|
|
493
|
+
}
|
|
494
|
+
const invocationExpectedRevision = expectedDocumentRevision ?? projectedServiceRevision;
|
|
495
|
+
if (invocationExpectedRevision === null || projectedServiceInstanceId === null) {
|
|
496
|
+
throw new Error('Project Editor Service revision is not ready.');
|
|
497
|
+
}
|
|
498
|
+
const requestId = `browser-project-${++browserAuthoringMutationSequence}`;
|
|
499
|
+
const response = await projectCommandService.request({
|
|
500
|
+
kind: 'command.invoke',
|
|
501
|
+
invocation: {
|
|
502
|
+
commandId,
|
|
503
|
+
input: input,
|
|
504
|
+
requestId,
|
|
505
|
+
idempotencyKey: requestId,
|
|
506
|
+
expectedRevision: {
|
|
507
|
+
serviceInstanceId: projectedServiceInstanceId,
|
|
508
|
+
document: invocationExpectedRevision,
|
|
509
|
+
},
|
|
510
|
+
principal: { type: 'human' },
|
|
511
|
+
source: 'browser-ui',
|
|
512
|
+
clientId: browserCommandAttachmentId,
|
|
513
|
+
},
|
|
514
|
+
timeoutMs: 10000,
|
|
515
|
+
});
|
|
516
|
+
const operation = await waitForProjectServiceOperation(projectCommandService.request, response);
|
|
517
|
+
if (operation?.status !== 'completed') {
|
|
518
|
+
throw new Error(operation?.diagnostics?.map(diagnostic => diagnostic.message).join('; ')
|
|
519
|
+
|| `Project Editor Service rejected ${commandId}.`);
|
|
520
|
+
}
|
|
521
|
+
return operation.output && typeof operation.output === 'object' && !Array.isArray(operation.output)
|
|
522
|
+
? operation.output
|
|
523
|
+
: {};
|
|
524
|
+
};
|
|
525
|
+
const prepareProjectServiceDocumentExport = async () => {
|
|
526
|
+
if (!projectCommandService)
|
|
527
|
+
return null;
|
|
528
|
+
const prepared = await invokeProjectServiceCommand('document.export');
|
|
529
|
+
const transactionId = typeof prepared.transactionId === 'string'
|
|
530
|
+
? prepared.transactionId
|
|
531
|
+
: null;
|
|
532
|
+
if (!transactionId) {
|
|
533
|
+
throw new Error('Project Editor Service did not return an export transaction.');
|
|
534
|
+
}
|
|
535
|
+
const response = await projectCommandService.request({
|
|
536
|
+
kind: 'document.export.get',
|
|
537
|
+
transactionId,
|
|
538
|
+
});
|
|
539
|
+
if (!response.ok || response.kind !== 'document.export' || !response.artifact) {
|
|
540
|
+
throw new Error('Project Editor Service did not return the prepared export artifact.');
|
|
541
|
+
}
|
|
542
|
+
return response.artifact;
|
|
543
|
+
};
|
|
544
|
+
const applyProjectServiceSnapshot = async (snapshot, syncLeaseHeld = false) => {
|
|
545
|
+
if (projectCommandService && !syncLeaseHeld) {
|
|
546
|
+
const release = await acquireProjectServiceSync();
|
|
547
|
+
try {
|
|
548
|
+
return await applyProjectServiceSnapshot(snapshot, true);
|
|
549
|
+
}
|
|
550
|
+
finally {
|
|
551
|
+
release();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const classification = classifyProjectServiceSnapshot(projectedServiceInstanceId, projectedServiceRevision, snapshot);
|
|
555
|
+
if (classification === 'stale')
|
|
556
|
+
return;
|
|
557
|
+
const serviceChanged = classification === 'service-changed';
|
|
558
|
+
if (shouldReplacePendingProjectServiceSnapshot(pendingProjectServiceSnapshot, snapshot)) {
|
|
559
|
+
pendingProjectServiceSnapshot = snapshot;
|
|
560
|
+
}
|
|
561
|
+
const session = state.session;
|
|
562
|
+
if (!session || state.prefabStage)
|
|
563
|
+
return;
|
|
564
|
+
const stateSnapshot = session.getState({ cloneDocuments: false });
|
|
565
|
+
const localDocumentFingerprint = createLocalEditorDocumentFingerprint(stateSnapshot.workingDocument);
|
|
566
|
+
const snapshotDocumentFingerprint = createLocalEditorDocumentFingerprint(snapshot.document);
|
|
567
|
+
if (!serviceChanged
|
|
568
|
+
&& projectedServiceRevision !== null
|
|
569
|
+
&& projectedBrowserDocumentFingerprint !== null
|
|
570
|
+
&& localDocumentFingerprint !== projectedBrowserDocumentFingerprint) {
|
|
571
|
+
throw new Error('The project snapshot cannot replace Browser working state because a newer local authoring transaction is not projected.');
|
|
572
|
+
}
|
|
573
|
+
if (localDocumentFingerprint === snapshotDocumentFingerprint
|
|
574
|
+
&& createLocalEditorDocumentFingerprint(stateSnapshot.persistedDocument)
|
|
575
|
+
=== createLocalEditorDocumentFingerprint(snapshot.savedDocument)) {
|
|
576
|
+
commitProjectAuthoringProjection(snapshot, snapshotDocumentFingerprint);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const rebaseProjection = (activeSession) => {
|
|
580
|
+
if (state.session !== session || state.prefabStage) {
|
|
581
|
+
throw new Error('Browser authoring scope changed before applying the project snapshot.');
|
|
582
|
+
}
|
|
583
|
+
runProjectionSessionMutation(activeSession, () => {
|
|
584
|
+
activeSession.rebaseExternalDocuments({
|
|
585
|
+
persistedDocument: snapshot.savedDocument,
|
|
586
|
+
workingDocument: snapshot.document,
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
};
|
|
590
|
+
const host = state.authoringHost;
|
|
591
|
+
if (host) {
|
|
592
|
+
const sequence = ++browserAuthoringMutationSequence;
|
|
593
|
+
await host.runExternalCommandMutation({
|
|
594
|
+
commandId: 'authoring.snapshot.project',
|
|
595
|
+
requestId: `project-snapshot-${sequence}`,
|
|
596
|
+
idempotencyKey: `project-snapshot-${sequence}`,
|
|
597
|
+
expectedDocumentRevision: stateSnapshot.documentRevision,
|
|
598
|
+
fingerprint: JSON.stringify({ serviceInstanceId: snapshot.serviceInstanceId, documentRevision: snapshot.documentRevision }),
|
|
599
|
+
}, rebaseProjection);
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
rebaseProjection(session);
|
|
603
|
+
}
|
|
604
|
+
commitProjectAuthoringProjection(snapshot, snapshotDocumentFingerprint);
|
|
605
|
+
harness.render();
|
|
606
|
+
};
|
|
607
|
+
const pushBrowserDocumentToProjectService = async (document, commandId, inputFingerprint, expectedServiceInstanceId, expectedServiceRevision, baseDocumentFingerprint, rollbackSession) => {
|
|
608
|
+
if (!projectCommandService)
|
|
609
|
+
return;
|
|
610
|
+
if (!disposeBrowserCommandAttachment || await disposeBrowserCommandAttachment === null) {
|
|
611
|
+
throw new Error('Browser command attachment is unavailable.');
|
|
612
|
+
}
|
|
613
|
+
const requestId = `browser-project-${++browserAuthoringMutationSequence}`;
|
|
614
|
+
const response = await projectCommandService.request({
|
|
615
|
+
kind: 'command.invoke',
|
|
616
|
+
invocation: {
|
|
617
|
+
commandId: 'authoring.proposal.commit',
|
|
618
|
+
intentCommandId: commandId,
|
|
619
|
+
input: { commandId, inputFingerprint, document },
|
|
620
|
+
requestId,
|
|
621
|
+
idempotencyKey: requestId,
|
|
622
|
+
expectedRevision: {
|
|
623
|
+
serviceInstanceId: expectedServiceInstanceId,
|
|
624
|
+
document: expectedServiceRevision,
|
|
625
|
+
},
|
|
626
|
+
principal: { type: 'human' },
|
|
627
|
+
source: 'browser-ui',
|
|
628
|
+
clientId: browserCommandAttachmentId,
|
|
629
|
+
},
|
|
630
|
+
timeoutMs: 10000,
|
|
631
|
+
});
|
|
632
|
+
const operation = await waitForProjectServiceOperation(projectCommandService.request, response);
|
|
633
|
+
if (operation?.status === 'completed') {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
const snapshot = await readProjectServiceSnapshot();
|
|
637
|
+
if (snapshot) {
|
|
638
|
+
if (shouldReplacePendingProjectServiceSnapshot(pendingProjectServiceSnapshot, snapshot)) {
|
|
639
|
+
pendingProjectServiceSnapshot = snapshot;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (snapshot && rollbackSession) {
|
|
643
|
+
runProjectionSessionMutation(rollbackSession, () => {
|
|
644
|
+
rollbackSession.rebaseExternalDocuments({
|
|
645
|
+
persistedDocument: snapshot.savedDocument,
|
|
646
|
+
workingDocument: snapshot.document,
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
commitProjectAuthoringProjection(snapshot);
|
|
650
|
+
}
|
|
651
|
+
const remoteFingerprint = snapshot
|
|
652
|
+
? createLocalEditorDocumentFingerprint(snapshot.document)
|
|
653
|
+
: null;
|
|
654
|
+
throw new Error(remoteFingerprint !== baseDocumentFingerprint
|
|
655
|
+
? 'Browser authoring was rejected because the project document changed in another client.'
|
|
656
|
+
: operation?.diagnostics?.map(diagnostic => diagnostic.message).join('; ')
|
|
657
|
+
|| 'Project Editor Service rejected the Browser authoring transaction.');
|
|
658
|
+
};
|
|
659
|
+
state.reconcilePendingProjectServiceSnapshot = async () => {
|
|
660
|
+
if (pendingProjectServiceSnapshot) {
|
|
661
|
+
await applyProjectServiceSnapshot(pendingProjectServiceSnapshot);
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
state.runBrowserAuthoringMutation = async (commandId, fingerprint, handler) => {
|
|
665
|
+
const releaseProjectSync = projectCommandService ? await acquireProjectServiceSync() : () => { };
|
|
666
|
+
try {
|
|
667
|
+
const session = state.session;
|
|
668
|
+
if (!session)
|
|
669
|
+
throw new Error('Browser authoring projection is unavailable.');
|
|
670
|
+
if (projectCommandService) {
|
|
671
|
+
if (projectedServiceRevision === null) {
|
|
672
|
+
const remote = await readProjectServiceSnapshot();
|
|
673
|
+
if (remote)
|
|
674
|
+
await applyProjectServiceSnapshot(remote, true);
|
|
675
|
+
}
|
|
676
|
+
const expectedServiceInstanceId = projectedServiceInstanceId;
|
|
677
|
+
const expectedServiceRevision = projectedServiceRevision;
|
|
678
|
+
if (expectedServiceInstanceId === null || expectedServiceRevision === null) {
|
|
679
|
+
throw new Error('Project Editor Service revision is not ready.');
|
|
680
|
+
}
|
|
681
|
+
const baseDocumentFingerprint = createLocalEditorDocumentFingerprint(session.getWorkingDocument());
|
|
682
|
+
const transaction = session.beginTransaction();
|
|
683
|
+
try {
|
|
684
|
+
const authoringState = new Proxy(state, {
|
|
685
|
+
get(target, property, receiver) {
|
|
686
|
+
if (property === 'session')
|
|
687
|
+
return transaction.session;
|
|
688
|
+
return Reflect.get(target, property, receiver);
|
|
689
|
+
},
|
|
690
|
+
set(target, property, value, receiver) {
|
|
691
|
+
if (property === 'session') {
|
|
692
|
+
throw new Error('Browser authoring proposal handlers cannot replace the projection Session.');
|
|
693
|
+
}
|
|
694
|
+
return Reflect.set(target, property, value, receiver);
|
|
695
|
+
},
|
|
696
|
+
});
|
|
697
|
+
const value = await handler(authoringState);
|
|
698
|
+
if (state.session !== session) {
|
|
699
|
+
throw new Error(`Browser authoring scope changed before ${commandId}.`);
|
|
700
|
+
}
|
|
701
|
+
const proposedDocument = transaction.session.getWorkingDocument();
|
|
702
|
+
await pushBrowserDocumentToProjectService(proposedDocument, commandId, fingerprint, expectedServiceInstanceId, expectedServiceRevision, baseDocumentFingerprint, session);
|
|
703
|
+
const committedSnapshot = await readProjectServiceSnapshot();
|
|
704
|
+
if (!committedSnapshot) {
|
|
705
|
+
throw new Error('Project Editor Service did not return the committed authoring snapshot.');
|
|
706
|
+
}
|
|
707
|
+
if (state.prefabStage && state.session === session) {
|
|
708
|
+
const projectionState = session.getState({ cloneDocuments: false });
|
|
709
|
+
runProjectionSessionMutation(session, () => {
|
|
710
|
+
session.rebaseExternalDocuments({
|
|
711
|
+
persistedDocument: projectionState.persistedDocument,
|
|
712
|
+
workingDocument: committedSnapshot.document,
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
commitProjectAuthoringProjection(committedSnapshot);
|
|
716
|
+
harness.render();
|
|
717
|
+
}
|
|
718
|
+
else {
|
|
719
|
+
await applyProjectServiceSnapshot(committedSnapshot, true);
|
|
720
|
+
}
|
|
721
|
+
return value;
|
|
722
|
+
}
|
|
723
|
+
finally {
|
|
724
|
+
transaction.discard();
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
const host = state.authoringHost;
|
|
728
|
+
if (!host)
|
|
729
|
+
throw new Error('Browser authoring authority is unavailable.');
|
|
730
|
+
const expectedDocumentRevision = session.getState({ cloneDocuments: false }).documentRevision;
|
|
731
|
+
const sequence = ++browserAuthoringMutationSequence;
|
|
732
|
+
const requestId = `browser-${sequence}`;
|
|
733
|
+
return await host.runExternalCommandMutation({
|
|
734
|
+
commandId,
|
|
735
|
+
requestId,
|
|
736
|
+
idempotencyKey: requestId,
|
|
737
|
+
expectedDocumentRevision,
|
|
738
|
+
fingerprint,
|
|
739
|
+
}, activeSession => {
|
|
740
|
+
if (state.session !== session) {
|
|
741
|
+
throw new Error(`Browser authoring scope changed before ${commandId}.`);
|
|
742
|
+
}
|
|
743
|
+
const authoringState = new Proxy(state, {
|
|
744
|
+
get(target, property, receiver) {
|
|
745
|
+
if (property === 'session')
|
|
746
|
+
return activeSession;
|
|
747
|
+
return Reflect.get(target, property, receiver);
|
|
748
|
+
},
|
|
749
|
+
set(target, property, value, receiver) {
|
|
750
|
+
if (property === 'session') {
|
|
751
|
+
throw new Error('Browser authoring handlers cannot replace the active Session.');
|
|
752
|
+
}
|
|
753
|
+
return Reflect.set(target, property, value, receiver);
|
|
754
|
+
},
|
|
755
|
+
});
|
|
756
|
+
return handler(authoringState);
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
finally {
|
|
760
|
+
releaseProjectSync();
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
state.tryRunBrowserAuthoringMutationImmediately = (commandId, fingerprint, handler) => {
|
|
764
|
+
if (projectCommandService) {
|
|
765
|
+
return { ok: false, reason: 'Project Editor Service authoring is asynchronous.' };
|
|
766
|
+
}
|
|
767
|
+
const host = state.authoringHost;
|
|
768
|
+
const session = state.session;
|
|
769
|
+
if (!host || !session)
|
|
770
|
+
return { ok: false, reason: 'Browser authoring authority is unavailable.' };
|
|
771
|
+
const releaseProjectSync = tryAcquireProjectServiceSync();
|
|
772
|
+
if (!releaseProjectSync)
|
|
773
|
+
return { ok: false, reason: 'An authoring transaction is still pending.' };
|
|
774
|
+
const expectedDocumentRevision = session.getState({ cloneDocuments: false }).documentRevision;
|
|
775
|
+
const sequence = ++browserAuthoringMutationSequence;
|
|
776
|
+
const requestId = `browser-${sequence}`;
|
|
777
|
+
try {
|
|
778
|
+
const result = host.tryRunExternalCommandMutationImmediately({
|
|
779
|
+
commandId,
|
|
780
|
+
requestId,
|
|
781
|
+
idempotencyKey: requestId,
|
|
782
|
+
expectedDocumentRevision,
|
|
783
|
+
fingerprint,
|
|
784
|
+
}, activeSession => {
|
|
785
|
+
if (state.session !== session) {
|
|
786
|
+
throw new Error(`Browser authoring scope changed before ${commandId}.`);
|
|
787
|
+
}
|
|
788
|
+
return handler(activeSession);
|
|
789
|
+
});
|
|
790
|
+
return result.ok ? { ok: true, value: result.value } : {
|
|
791
|
+
ok: false,
|
|
792
|
+
reason: 'Another authoring transaction is running.',
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
finally {
|
|
796
|
+
releaseProjectSync();
|
|
797
|
+
}
|
|
390
798
|
};
|
|
391
799
|
const getDocumentDirty = () => {
|
|
392
800
|
const stageSnapshot = state.prefabStage?.transaction.snapshot();
|
|
@@ -398,6 +806,8 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
398
806
|
if (change.documentChanged)
|
|
399
807
|
state.diagnosticPhase = 'edit';
|
|
400
808
|
void lifecycleController?.synchronizeDocumentState(getDocumentDirty()).catch(error => {
|
|
809
|
+
state.suppressDocumentMarkDirtyInspectorRefresh = false;
|
|
810
|
+
suppressedDocumentMarkDirtyTransitionId = null;
|
|
401
811
|
console.error('[LocalEditorHarness] lifecycle document synchronization failed', error);
|
|
402
812
|
});
|
|
403
813
|
const eventPublisher = options.pluginHost?.eventPublisher;
|
|
@@ -456,11 +866,93 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
456
866
|
state.createSessionChangeObserver = createSessionChangeObserver;
|
|
457
867
|
state.handleSessionObserverError = handleEditorSessionObserverError;
|
|
458
868
|
let harness;
|
|
869
|
+
const runProjectServiceHistoryOperation = async (operation, historyOptions = {}) => {
|
|
870
|
+
const origin = historyOptions.origin ?? 'user';
|
|
871
|
+
const waitForProjection = historyOptions.waitForProjection ?? 'none';
|
|
872
|
+
const releaseProjectSync = await acquireProjectServiceSync();
|
|
873
|
+
try {
|
|
874
|
+
cancelActiveOperation(state);
|
|
875
|
+
const before = await readProjectServiceSnapshot();
|
|
876
|
+
if (!before)
|
|
877
|
+
throw new Error('Project Editor Service history is unavailable.');
|
|
878
|
+
await applyProjectServiceSnapshot(before, true);
|
|
879
|
+
const available = operation === 'undo' ? before.canUndo : before.canRedo;
|
|
880
|
+
if (!available) {
|
|
881
|
+
return {
|
|
882
|
+
ok: false,
|
|
883
|
+
operation,
|
|
884
|
+
origin,
|
|
885
|
+
waitForProjection,
|
|
886
|
+
documentChanged: false,
|
|
887
|
+
transactionLabel: null,
|
|
888
|
+
workingDocument: before.document,
|
|
889
|
+
dirty: before.dirty,
|
|
890
|
+
history: { canUndo: before.canUndo, canRedo: before.canRedo },
|
|
891
|
+
status: operation === 'undo' ? 'Undo unavailable' : 'Redo unavailable',
|
|
892
|
+
projection: createHistoryProjectionResult(waitForProjection, null, state),
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
await invokeProjectServiceCommand(`history.${operation}`);
|
|
896
|
+
const after = await readProjectServiceSnapshot();
|
|
897
|
+
if (!after)
|
|
898
|
+
throw new Error('Project Editor Service did not return the updated history snapshot.');
|
|
899
|
+
await applyProjectServiceSnapshot(after, true);
|
|
900
|
+
state.summary = summarizeDocument(options, after.document, state.session?.getSource());
|
|
901
|
+
state.status = operation === 'undo' ? 'Undo' : 'Redo';
|
|
902
|
+
state.statusTone = 'default';
|
|
903
|
+
state.statusToneStatus = state.status;
|
|
904
|
+
state.statusDetails = '';
|
|
905
|
+
harness.render();
|
|
906
|
+
const idleState = waitForProjection === 'settled'
|
|
907
|
+
? await state.projection?.waitForIdle() ?? null
|
|
908
|
+
: null;
|
|
909
|
+
return {
|
|
910
|
+
ok: true,
|
|
911
|
+
operation,
|
|
912
|
+
origin,
|
|
913
|
+
waitForProjection,
|
|
914
|
+
documentChanged: after.documentRevision !== before.documentRevision,
|
|
915
|
+
transactionLabel: null,
|
|
916
|
+
workingDocument: after.document,
|
|
917
|
+
dirty: after.dirty,
|
|
918
|
+
history: { canUndo: after.canUndo, canRedo: after.canRedo },
|
|
919
|
+
status: state.status,
|
|
920
|
+
projection: createHistoryProjectionResult(waitForProjection, idleState, state),
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
catch (error) {
|
|
924
|
+
reportBrowserAuthoringFailure(state, () => harness.render(), error);
|
|
925
|
+
const snapshot = state.projectAuthoringSnapshot;
|
|
926
|
+
return {
|
|
927
|
+
ok: false,
|
|
928
|
+
operation,
|
|
929
|
+
origin,
|
|
930
|
+
waitForProjection,
|
|
931
|
+
documentChanged: false,
|
|
932
|
+
transactionLabel: null,
|
|
933
|
+
workingDocument: state.session?.getWorkingDocument() ?? null,
|
|
934
|
+
dirty: snapshot?.dirty ?? state.session?.isDirty() ?? false,
|
|
935
|
+
history: {
|
|
936
|
+
canUndo: snapshot?.canUndo ?? false,
|
|
937
|
+
canRedo: snapshot?.canRedo ?? false,
|
|
938
|
+
},
|
|
939
|
+
status: state.status,
|
|
940
|
+
projection: createHistoryProjectionResult(waitForProjection, null, state),
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
finally {
|
|
944
|
+
releaseProjectSync();
|
|
945
|
+
}
|
|
946
|
+
};
|
|
459
947
|
let renderSelectionChange = () => harness.render();
|
|
948
|
+
let applySceneRenamePresentation = (_input) => false;
|
|
949
|
+
let applyHistoryPresentation = (_impact) => false;
|
|
950
|
+
let applyInspectorPresentation = (_input) => false;
|
|
951
|
+
let applyRenderingPresentation = () => false;
|
|
460
952
|
const busyOperationExecutors = new WeakMap();
|
|
461
953
|
let agentLifecycleController;
|
|
462
954
|
const pluginInspector = createLocalEditorHarnessPluginInspectorOptions(options.pluginHost, options.inspector);
|
|
463
|
-
const builtInSceneHierarchyProvider = createLocalEditorHarnessHierarchyScopeProvider(state, options, () => harness.render(), createLocalEditorSceneHierarchyScopeAdapter(state, options), busyOperationExecutors, () => renderSelectionChange());
|
|
955
|
+
const builtInSceneHierarchyProvider = createLocalEditorHarnessHierarchyScopeProvider(state, options, () => harness.render(), createLocalEditorSceneHierarchyScopeAdapter(state, options, input => applySceneRenamePresentation(input)), busyOperationExecutors, () => renderSelectionChange());
|
|
464
956
|
const builtInPrefabStageHierarchyProvider = createLocalEditorHarnessHierarchyScopeProvider(state, options, () => harness.render(), createLocalEditorPrefabHierarchyScopeAdapter(state, options), busyOperationExecutors, () => renderSelectionChange());
|
|
465
957
|
const hierarchySurface = options.pluginHost
|
|
466
958
|
? resolveHierarchySurfaceContribution(options.pluginHost.contributions)
|
|
@@ -551,6 +1043,8 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
551
1043
|
theme: options.theme,
|
|
552
1044
|
localTestActions: options.localTestActions,
|
|
553
1045
|
gameModeEntryVisible: options.gameModeEntryVisible,
|
|
1046
|
+
commandService: projectCommandService,
|
|
1047
|
+
commandClientId: browserCommandAttachmentId,
|
|
554
1048
|
input: {
|
|
555
1049
|
isShortcutReserved: (event) => state.sceneViewInput?.ownsKeyboardEvent(event) ?? false,
|
|
556
1050
|
},
|
|
@@ -686,8 +1180,10 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
686
1180
|
})();
|
|
687
1181
|
},
|
|
688
1182
|
onCreateFromAsset: (assetId) => {
|
|
689
|
-
|
|
690
|
-
|
|
1183
|
+
void state.runBrowserAuthoringMutation('object.createFromAsset', JSON.stringify({ assetId }), authoringState => createAssetFromBrowserIntent(authoringState, options, assetId)).then(changed => {
|
|
1184
|
+
if (changed)
|
|
1185
|
+
harness.render();
|
|
1186
|
+
}).catch(error => reportBrowserAuthoringFailure(state, harness.render, error));
|
|
691
1187
|
},
|
|
692
1188
|
onSelectAsset: (assetId) => {
|
|
693
1189
|
if (selectBrowserAsset(state, assetId))
|
|
@@ -715,7 +1211,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
715
1211
|
return;
|
|
716
1212
|
}
|
|
717
1213
|
else if (choice === 'discard') {
|
|
718
|
-
discardPrefabStageChanges();
|
|
1214
|
+
await discardPrefabStageChanges();
|
|
719
1215
|
}
|
|
720
1216
|
else {
|
|
721
1217
|
return;
|
|
@@ -729,12 +1225,18 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
729
1225
|
void runExclusive(state, harness.render, executor => (runPrefabContextAction(actionId, executor)), busyOperationExecutors);
|
|
730
1226
|
},
|
|
731
1227
|
onMarkerTypeAction: (input) => {
|
|
732
|
-
|
|
733
|
-
|
|
1228
|
+
void state.runBrowserAuthoringMutation('marker.type.apply', JSON.stringify(input), authoringState => patchMarkerTypeCatalog(authoringState, options, input)).then(changed => {
|
|
1229
|
+
if (changed)
|
|
1230
|
+
harness.render();
|
|
1231
|
+
}).catch(error => reportBrowserAuthoringFailure(state, harness.render, error));
|
|
734
1232
|
},
|
|
735
1233
|
onMarkerRelationAction: (input) => {
|
|
736
|
-
|
|
737
|
-
|
|
1234
|
+
void state.runBrowserAuthoringMutation('marker.relation.apply', JSON.stringify(input), authoringState => {
|
|
1235
|
+
const changed = patchMarkerRelation(authoringState, options, input);
|
|
1236
|
+
if (changed)
|
|
1237
|
+
harness.render();
|
|
1238
|
+
return changed;
|
|
1239
|
+
}).catch(error => reportBrowserAuthoringFailure(state, harness.render, error));
|
|
738
1240
|
},
|
|
739
1241
|
onAssetBrowserRefresh: () => runExclusive(state, harness.render, async () => {
|
|
740
1242
|
await harness.reloadAssets();
|
|
@@ -742,9 +1244,6 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
742
1244
|
onProjectFileRead: options.persistenceAdapter.loadProjectFile
|
|
743
1245
|
? path => Promise.resolve(options.persistenceAdapter.loadProjectFile(path))
|
|
744
1246
|
: undefined,
|
|
745
|
-
onProjectEntrySendToAgent: options.agentContext
|
|
746
|
-
? input => Promise.resolve(options.agentContext.sendProjectEntry(input)).then(() => undefined)
|
|
747
|
-
: undefined,
|
|
748
1247
|
onProjectMediaResolve: options.persistenceAdapter.resolveProjectMedia
|
|
749
1248
|
? path => Promise.resolve(options.persistenceAdapter.resolveProjectMedia(path))
|
|
750
1249
|
: undefined,
|
|
@@ -756,10 +1255,46 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
756
1255
|
harness.render();
|
|
757
1256
|
},
|
|
758
1257
|
onPropertyInput: (input) => {
|
|
759
|
-
const
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1258
|
+
const refreshInspector = input.refreshInspector
|
|
1259
|
+
?? !(input.source === 'custom' && input.commitMode === 'live');
|
|
1260
|
+
const normalizedInput = refreshInspector === input.refreshInspector
|
|
1261
|
+
? input
|
|
1262
|
+
: { ...input, refreshInspector };
|
|
1263
|
+
const lifecycleSnapshot = lifecycleController?.lifecycle.getSnapshot();
|
|
1264
|
+
state.suppressDocumentMarkDirtyInspectorRefresh = !refreshInspector
|
|
1265
|
+
&& normalizedInput.persistence === 'document'
|
|
1266
|
+
&& lifecycleSnapshot?.mode === 'edit'
|
|
1267
|
+
&& lifecycleSnapshot.document !== 'dirty';
|
|
1268
|
+
void state.runBrowserAuthoringMutation('inspector.property.set', JSON.stringify(normalizedInput), authoringState => {
|
|
1269
|
+
const previousStatus = authoringState.status;
|
|
1270
|
+
const patched = patchSerializedProperty(authoringState, options, normalizedInput);
|
|
1271
|
+
return {
|
|
1272
|
+
patched,
|
|
1273
|
+
statusChanged: authoringState.status !== previousStatus,
|
|
1274
|
+
};
|
|
1275
|
+
})
|
|
1276
|
+
.then(({ patched, statusChanged }) => {
|
|
1277
|
+
const presentationApplied = patched
|
|
1278
|
+
? applyInspectorPresentation(normalizedInput)
|
|
1279
|
+
: false;
|
|
1280
|
+
if (!refreshInspector) {
|
|
1281
|
+
if (!presentationApplied && (patched || statusChanged)) {
|
|
1282
|
+
ui.updatePreview?.({
|
|
1283
|
+
status: state.status,
|
|
1284
|
+
statusTone: state.statusToneStatus === state.status ? state.statusTone : 'default',
|
|
1285
|
+
statusDetails: state.statusToneStatus === state.status ? state.statusDetails : '',
|
|
1286
|
+
session: createUiSessionState(state),
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
if ((patched || statusChanged) && !presentationApplied)
|
|
1292
|
+
harness.render();
|
|
1293
|
+
})
|
|
1294
|
+
.catch(error => reportBrowserAuthoringFailure(state, harness.render, error))
|
|
1295
|
+
.finally(() => {
|
|
1296
|
+
state.suppressDocumentMarkDirtyInspectorRefresh = false;
|
|
1297
|
+
});
|
|
763
1298
|
},
|
|
764
1299
|
onInspectorAction: (input) => {
|
|
765
1300
|
void runExclusive(state, harness.render, async () => {
|
|
@@ -769,20 +1304,31 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
769
1304
|
},
|
|
770
1305
|
onRenderingPropertyChange: options.documentAdapter.onRenderingPropertyChange
|
|
771
1306
|
? (input) => {
|
|
772
|
-
void applyRenderingPropertyChange(
|
|
1307
|
+
void state.runBrowserAuthoringMutation('rendering.property.set', JSON.stringify(input), authoringState => applyRenderingPropertyChange(authoringState, options, input))
|
|
773
1308
|
.then((changed) => {
|
|
774
|
-
if (changed)
|
|
1309
|
+
if (changed && !applyRenderingPresentation())
|
|
775
1310
|
harness.render();
|
|
776
|
-
})
|
|
1311
|
+
})
|
|
1312
|
+
.catch(error => reportBrowserAuthoringFailure(state, harness.render, error));
|
|
777
1313
|
}
|
|
778
1314
|
: undefined,
|
|
779
1315
|
onRenderingAction: options.documentAdapter.onRenderingAction
|
|
780
1316
|
? (input) => {
|
|
781
|
-
return applyRenderingAction(
|
|
782
|
-
.then((
|
|
783
|
-
if (
|
|
1317
|
+
return state.runBrowserAuthoringMutation(`rendering.${input.actionId ?? 'action'}`, JSON.stringify(input), authoringState => applyRenderingAction(authoringState, options, input, harness.render))
|
|
1318
|
+
.then((result) => {
|
|
1319
|
+
if (result.rendered && !applyRenderingPresentation())
|
|
784
1320
|
harness.render();
|
|
785
|
-
return
|
|
1321
|
+
return result;
|
|
1322
|
+
})
|
|
1323
|
+
.catch(error => {
|
|
1324
|
+
reportBrowserAuthoringFailure(state, harness.render, error);
|
|
1325
|
+
return {
|
|
1326
|
+
ok: false,
|
|
1327
|
+
changed: false,
|
|
1328
|
+
rendered: false,
|
|
1329
|
+
status: error instanceof Error ? error.message : String(error),
|
|
1330
|
+
statusTone: 'error',
|
|
1331
|
+
};
|
|
786
1332
|
});
|
|
787
1333
|
}
|
|
788
1334
|
: undefined,
|
|
@@ -870,8 +1416,10 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
870
1416
|
});
|
|
871
1417
|
},
|
|
872
1418
|
onTransformAction: (action) => {
|
|
873
|
-
|
|
874
|
-
|
|
1419
|
+
void state.runBrowserAuthoringMutation(`transform.${action}`, JSON.stringify({ action }), authoringState => executeTransformAction(authoringState, options, action)).then(changed => {
|
|
1420
|
+
if (changed)
|
|
1421
|
+
harness.render();
|
|
1422
|
+
}).catch(error => reportBrowserAuthoringFailure(state, harness.render, error));
|
|
875
1423
|
},
|
|
876
1424
|
onViewportViewPresetChange: (preset) => {
|
|
877
1425
|
if (setViewportViewPreset(state, options, preset))
|
|
@@ -935,28 +1483,38 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
935
1483
|
}
|
|
936
1484
|
publishLocalEditorSelectionPresentation(state, options, previewState => ui.updatePreview?.(previewState), 'hierarchy-selection-presentation');
|
|
937
1485
|
};
|
|
938
|
-
const discardPrefabStageChanges = () => {
|
|
1486
|
+
const discardPrefabStageChanges = async (serializedAccess) => {
|
|
939
1487
|
const stage = state.prefabStage;
|
|
940
1488
|
if (!stage || !stage.transaction.snapshot().stageDirty)
|
|
941
1489
|
return false;
|
|
942
1490
|
cancelActiveOperation(state);
|
|
943
|
-
stage.transaction.
|
|
1491
|
+
stage.transaction.assertParentUnchanged();
|
|
944
1492
|
const draftState = stage.transaction.draftSession.getState({ cloneDocuments: false });
|
|
945
|
-
|
|
1493
|
+
if (state.authoringHost) {
|
|
1494
|
+
await state.authoringHost.reset(draftState.persistedDocument, draftState.source, {
|
|
1495
|
+
expectedDocumentRevision: draftState.documentRevision,
|
|
1496
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
else {
|
|
1500
|
+
await state.runBrowserAuthoringMutation('prefab.stage.discard', JSON.stringify({ documentRevision: draftState.documentRevision }), authoringState => authoringState.session?.reset(draftState.persistedDocument, draftState.source));
|
|
1501
|
+
}
|
|
1502
|
+
const resetState = stage.transaction.draftSession.getState({ cloneDocuments: false });
|
|
1503
|
+
rebuildProjectionFromDocument(state, options, resetState.workingDocument, EMPTY_EDITOR_SELECTION);
|
|
946
1504
|
state.status = `Discarded changes to Prefab ${stage.descriptor.label}`;
|
|
947
1505
|
state.statusTone = 'default';
|
|
948
1506
|
state.statusToneStatus = state.status;
|
|
949
1507
|
state.statusDetails = '';
|
|
950
1508
|
return true;
|
|
951
1509
|
};
|
|
952
|
-
runPrefabContextAction = async (actionId, executor) => {
|
|
1510
|
+
runPrefabContextAction = async (actionId, executor, serializedAccess) => {
|
|
953
1511
|
const stage = state.prefabStage;
|
|
954
1512
|
if (!stage)
|
|
955
1513
|
return false;
|
|
956
1514
|
if (actionId === PREFAB_STAGE_CONTEXT_ACTION_IDS.save) {
|
|
957
1515
|
if (!stage.transaction.snapshot().documentDirty)
|
|
958
1516
|
return false;
|
|
959
|
-
return harness.saveScene(executor);
|
|
1517
|
+
return harness.saveScene(executor, undefined, serializedAccess);
|
|
960
1518
|
}
|
|
961
1519
|
if (actionId === PREFAB_STAGE_CONTEXT_ACTION_IDS.discard) {
|
|
962
1520
|
if (!stage.transaction.snapshot().stageDirty)
|
|
@@ -968,7 +1526,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
968
1526
|
confirmLabel: '废弃更改',
|
|
969
1527
|
cancelLabel: '继续编辑',
|
|
970
1528
|
});
|
|
971
|
-
return confirmed ? discardPrefabStageChanges() : false;
|
|
1529
|
+
return confirmed ? discardPrefabStageChanges(serializedAccess) : false;
|
|
972
1530
|
}
|
|
973
1531
|
if (actionId !== PREFAB_STAGE_CONTEXT_ACTION_IDS.exit)
|
|
974
1532
|
return false;
|
|
@@ -984,17 +1542,155 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
984
1542
|
cancelLabel: '取消',
|
|
985
1543
|
});
|
|
986
1544
|
if (choice === 'save') {
|
|
987
|
-
if (!await harness.saveScene(executor))
|
|
1545
|
+
if (!await harness.saveScene(executor, undefined, serializedAccess))
|
|
988
1546
|
return false;
|
|
989
1547
|
}
|
|
990
1548
|
else if (choice === 'discard') {
|
|
991
|
-
discardPrefabStageChanges();
|
|
1549
|
+
await discardPrefabStageChanges(serializedAccess);
|
|
992
1550
|
}
|
|
993
1551
|
else {
|
|
994
1552
|
return false;
|
|
995
1553
|
}
|
|
996
1554
|
}
|
|
997
|
-
return exitPrefabStage(state, options, 'reject');
|
|
1555
|
+
return exitPrefabStage(state, options, 'reject', serializedAccess);
|
|
1556
|
+
};
|
|
1557
|
+
applySceneRenamePresentation = ({ id, name }) => {
|
|
1558
|
+
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
1559
|
+
const document = sessionState?.workingDocument ?? null;
|
|
1560
|
+
const authoritativeName = document
|
|
1561
|
+
? resolveAuthoritativeHierarchyLabels(state, options, document, [id])[id] ?? name
|
|
1562
|
+
: name;
|
|
1563
|
+
let applied = false;
|
|
1564
|
+
try {
|
|
1565
|
+
applied = ui.updatePresentationDelta?.({
|
|
1566
|
+
hierarchyLabelIds: [id],
|
|
1567
|
+
hierarchyLabels: { [id]: authoritativeName },
|
|
1568
|
+
materialUsageOwnerNames: { [id]: authoritativeName },
|
|
1569
|
+
inspector: ['summary'],
|
|
1570
|
+
session: createUiSessionState(state),
|
|
1571
|
+
status: state.status,
|
|
1572
|
+
statusTone: state.statusTone,
|
|
1573
|
+
statusDetails: state.statusDetails,
|
|
1574
|
+
}) === true;
|
|
1575
|
+
}
|
|
1576
|
+
catch {
|
|
1577
|
+
applied = false;
|
|
1578
|
+
}
|
|
1579
|
+
if (!applied)
|
|
1580
|
+
state.hierarchyPresentationFallbackRevision += 1;
|
|
1581
|
+
return applied;
|
|
1582
|
+
};
|
|
1583
|
+
applyHistoryPresentation = impact => {
|
|
1584
|
+
if (!impact || impact.hierarchy === 'full')
|
|
1585
|
+
return false;
|
|
1586
|
+
const inspectorNeedsAssembly = impact.inspector === 'full'
|
|
1587
|
+
|| (Array.isArray(impact.inspector) && impact.inspector.includes('material'));
|
|
1588
|
+
if (inspectorNeedsAssembly)
|
|
1589
|
+
cancelInspectorPresentationPreview(state);
|
|
1590
|
+
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
1591
|
+
const document = sessionState?.workingDocument ?? null;
|
|
1592
|
+
const labelIds = impact.hierarchy?.labelIds ?? [];
|
|
1593
|
+
const labels = document
|
|
1594
|
+
? resolveAuthoritativeHierarchyLabels(state, options, document, labelIds)
|
|
1595
|
+
: {};
|
|
1596
|
+
const inspectorState = inspectorNeedsAssembly && document
|
|
1597
|
+
? createUiSelectionInspectorPreviewState(state, options)
|
|
1598
|
+
: null;
|
|
1599
|
+
const inspectorValuePatches = Array.isArray(impact.inspector)
|
|
1600
|
+
&& impact.inspector.includes('transform')
|
|
1601
|
+
&& document
|
|
1602
|
+
? createHistoryTransformInspectorPresentationPatches(state, document, sessionState?.selection)
|
|
1603
|
+
: [];
|
|
1604
|
+
const renderingPanel = impact.rendering && document
|
|
1605
|
+
? options.documentAdapter.getRenderingPanelState?.(document, {
|
|
1606
|
+
scene: state.world?.scene ?? null,
|
|
1607
|
+
projection: state.projection,
|
|
1608
|
+
renderingAction: state.renderingAction,
|
|
1609
|
+
}) ?? null
|
|
1610
|
+
: undefined;
|
|
1611
|
+
let applied = false;
|
|
1612
|
+
try {
|
|
1613
|
+
applied = ui.updatePresentationDelta?.({
|
|
1614
|
+
hierarchyLabelIds: labelIds,
|
|
1615
|
+
hierarchyLabels: labels,
|
|
1616
|
+
materialUsageOwnerNames: labels,
|
|
1617
|
+
inspector: impact.inspector,
|
|
1618
|
+
...(inspectorValuePatches.length > 0 ? { inspectorValuePatches } : {}),
|
|
1619
|
+
...(inspectorState ? {
|
|
1620
|
+
inspectorObject: inspectorState.inspectorObject,
|
|
1621
|
+
inspectorMultiObject: inspectorState.inspectorMultiObject,
|
|
1622
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
1623
|
+
} : {}),
|
|
1624
|
+
rendering: impact.rendering,
|
|
1625
|
+
...(renderingPanel !== undefined ? { renderingPanel } : {}),
|
|
1626
|
+
session: createUiSessionState(state),
|
|
1627
|
+
status: state.status, statusTone: state.statusTone, statusDetails: state.statusDetails,
|
|
1628
|
+
}) === true;
|
|
1629
|
+
}
|
|
1630
|
+
catch {
|
|
1631
|
+
applied = false;
|
|
1632
|
+
}
|
|
1633
|
+
if (!applied && labelIds.length > 0)
|
|
1634
|
+
state.hierarchyPresentationFallbackRevision += 1;
|
|
1635
|
+
return applied;
|
|
1636
|
+
};
|
|
1637
|
+
applyInspectorPresentation = input => {
|
|
1638
|
+
if (isSerializedNamePath(input.path) && typeof input.value === 'string') {
|
|
1639
|
+
return applySceneRenamePresentation({ id: input.targetId, name: input.value });
|
|
1640
|
+
}
|
|
1641
|
+
const impact = resolveSerializedPresentationImpact(input.path);
|
|
1642
|
+
if (!impact)
|
|
1643
|
+
return false;
|
|
1644
|
+
if (impact.inspector?.includes('material'))
|
|
1645
|
+
cancelInspectorPresentationPreview(state);
|
|
1646
|
+
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
1647
|
+
const inspectorState = impact.inspector?.includes('material')
|
|
1648
|
+
? createUiSelectionInspectorPreviewState(state, options)
|
|
1649
|
+
: null;
|
|
1650
|
+
try {
|
|
1651
|
+
return ui.updatePresentationDelta?.({
|
|
1652
|
+
inspector: impact.inspector,
|
|
1653
|
+
...(impact.inspector?.includes('transform') ? {
|
|
1654
|
+
inspectorValuePatches: [{
|
|
1655
|
+
targetId: input.targetId,
|
|
1656
|
+
propertyPath: input.path,
|
|
1657
|
+
value: input.value,
|
|
1658
|
+
generation: state.inspectorPresentationGeneration,
|
|
1659
|
+
}],
|
|
1660
|
+
} : {}),
|
|
1661
|
+
...(inspectorState ? {
|
|
1662
|
+
inspectorObject: inspectorState.inspectorObject,
|
|
1663
|
+
inspectorMultiObject: inspectorState.inspectorMultiObject,
|
|
1664
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
1665
|
+
} : {}),
|
|
1666
|
+
session: createUiSessionState(state),
|
|
1667
|
+
status: state.status, statusTone: state.statusTone, statusDetails: state.statusDetails,
|
|
1668
|
+
}) === true;
|
|
1669
|
+
}
|
|
1670
|
+
catch {
|
|
1671
|
+
return false;
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1674
|
+
applyRenderingPresentation = () => {
|
|
1675
|
+
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
1676
|
+
const document = sessionState?.workingDocument ?? null;
|
|
1677
|
+
if (!document)
|
|
1678
|
+
return false;
|
|
1679
|
+
try {
|
|
1680
|
+
return ui.updatePresentationDelta?.({
|
|
1681
|
+
rendering: true,
|
|
1682
|
+
renderingPanel: options.documentAdapter.getRenderingPanelState?.(document, {
|
|
1683
|
+
scene: state.world?.scene ?? null,
|
|
1684
|
+
projection: state.projection,
|
|
1685
|
+
renderingAction: state.renderingAction,
|
|
1686
|
+
}) ?? null,
|
|
1687
|
+
session: createUiSessionState(state),
|
|
1688
|
+
status: state.status, statusTone: state.statusTone, statusDetails: state.statusDetails,
|
|
1689
|
+
}) === true;
|
|
1690
|
+
}
|
|
1691
|
+
catch {
|
|
1692
|
+
return false;
|
|
1693
|
+
}
|
|
998
1694
|
};
|
|
999
1695
|
const unsubscribeToolManager = toolManager.subscribe(snapshot => {
|
|
1000
1696
|
if (state.toolManagerRenderSuppression !== 0)
|
|
@@ -1019,11 +1715,12 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1019
1715
|
});
|
|
1020
1716
|
construction.setCleanup(() => {
|
|
1021
1717
|
harnessDisposed = true;
|
|
1718
|
+
stopProjectServiceWatch?.();
|
|
1719
|
+
stopProjectServiceWatch = null;
|
|
1720
|
+
void disposeBrowserCommandAttachment?.then(dispose => dispose?.());
|
|
1721
|
+
disposeBrowserCommandAttachment = null;
|
|
1022
1722
|
pendingScheduledLifecycleExit?.cancel();
|
|
1023
1723
|
pendingScheduledLifecycleExit = null;
|
|
1024
|
-
unregisterAgentBridgeLifecycleParticipant?.();
|
|
1025
|
-
unregisterAgentBridgeLifecycleParticipant = null;
|
|
1026
|
-
agentBridgeLifecycleTransports.clear();
|
|
1027
1724
|
releaseApplicationAuthorityScopeResource?.();
|
|
1028
1725
|
releaseApplicationAuthorityScopeResource = null;
|
|
1029
1726
|
releaseMainSessionScopeResource?.();
|
|
@@ -1038,6 +1735,9 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1038
1735
|
unbindPluginTools?.();
|
|
1039
1736
|
for (const unregister of [...unregisterStandardTools].reverse())
|
|
1040
1737
|
unregister();
|
|
1738
|
+
state.authoringHost?.dispose();
|
|
1739
|
+
state.authoringHost = null;
|
|
1740
|
+
state.replaceProjectionSessionAuthority(null);
|
|
1041
1741
|
disposeLocalEditorHarnessResources(state, ui, hierarchyKernel);
|
|
1042
1742
|
});
|
|
1043
1743
|
const startGameRuntime = async (reason) => {
|
|
@@ -1053,6 +1753,10 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1053
1753
|
return;
|
|
1054
1754
|
// The lifecycle-owned Session Scope clears these before runGame. Keep the
|
|
1055
1755
|
// assignment idempotent for direct harness consumers without a coordinator.
|
|
1756
|
+
state.authoringHost?.dispose();
|
|
1757
|
+
await state.authoringHost?.drain();
|
|
1758
|
+
state.authoringHost = null;
|
|
1759
|
+
state.replaceProjectionSessionAuthority(null);
|
|
1056
1760
|
state.session = null;
|
|
1057
1761
|
state.source = null;
|
|
1058
1762
|
state.status = reason === 'save' ? 'Saved scene; starting game' : 'Discarded editor changes; starting game';
|
|
@@ -1100,6 +1804,25 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1100
1804
|
}, executor);
|
|
1101
1805
|
return runResult.accepted ? runResult.value : false;
|
|
1102
1806
|
};
|
|
1807
|
+
const replaceAuthoringHost = async (session) => {
|
|
1808
|
+
state.unregisterCommandCapabilities?.();
|
|
1809
|
+
state.unregisterCommandCapabilities = null;
|
|
1810
|
+
const previousHost = state.authoringHost;
|
|
1811
|
+
previousHost?.dispose();
|
|
1812
|
+
await previousHost?.drain();
|
|
1813
|
+
if (projectCommandService) {
|
|
1814
|
+
state.authoringHost = null;
|
|
1815
|
+
state.replaceProjectionSessionAuthority(session);
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
state.replaceProjectionSessionAuthority(null);
|
|
1819
|
+
state.authoringHost = createEditorAuthoringHost({
|
|
1820
|
+
serviceInstanceId: createLocalEditorAuthoringServiceInstanceId(),
|
|
1821
|
+
session,
|
|
1822
|
+
commandSystem: commandServiceCommandSystem,
|
|
1823
|
+
disposeCommandSystem: false,
|
|
1824
|
+
});
|
|
1825
|
+
};
|
|
1103
1826
|
const loadOptionalProjectFiles = async () => {
|
|
1104
1827
|
if (!options.persistenceAdapter.loadProjectFiles) {
|
|
1105
1828
|
return { projectFiles: state.projectFiles, warning: null };
|
|
@@ -1153,7 +1876,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1153
1876
|
cloneDocument: options.documentAdapter.cloneDocument,
|
|
1154
1877
|
compareDocuments: options.documentAdapter.compareDocuments,
|
|
1155
1878
|
reduceDocument: options.documentAdapter.reduceDocument,
|
|
1156
|
-
isDocumentStructureChange: options.documentAdapter.isHierarchyStructureChange,
|
|
1879
|
+
isDocumentStructureChange: command => resolveLocalEditorDocumentStructureChange(options.documentAdapter.isHierarchyStructureChange, command),
|
|
1157
1880
|
onChange: createSessionChangeObserver(() => mainSession, {
|
|
1158
1881
|
document: PLAYABLE_LOCAL_EDITOR_MAIN_DOCUMENT_SCOPE_ID,
|
|
1159
1882
|
session: PLAYABLE_LOCAL_EDITOR_MAIN_SESSION_SCOPE_ID,
|
|
@@ -1162,14 +1885,22 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1162
1885
|
});
|
|
1163
1886
|
state.session = mainSession;
|
|
1164
1887
|
try {
|
|
1888
|
+
await replaceAuthoringHost(mainSession);
|
|
1165
1889
|
attachLifecycleOwnedSessionAuthority();
|
|
1890
|
+
activateCommandAuthority();
|
|
1166
1891
|
}
|
|
1167
1892
|
catch (error) {
|
|
1893
|
+
state.authoringHost?.dispose();
|
|
1894
|
+
state.authoringHost = null;
|
|
1895
|
+
state.replaceProjectionSessionAuthority(null);
|
|
1168
1896
|
state.session = null;
|
|
1169
1897
|
state.source = null;
|
|
1170
1898
|
throw error;
|
|
1171
1899
|
}
|
|
1172
1900
|
state.summary = loadedSource?.summary ?? summarizeDocument(options, preparedDocument, source);
|
|
1901
|
+
if (pendingProjectServiceSnapshot) {
|
|
1902
|
+
await applyProjectServiceSnapshot(pendingProjectServiceSnapshot);
|
|
1903
|
+
}
|
|
1173
1904
|
};
|
|
1174
1905
|
const enterEditorWorld = async () => {
|
|
1175
1906
|
if (!state.session)
|
|
@@ -1220,13 +1951,33 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1220
1951
|
if (prefabTransaction) {
|
|
1221
1952
|
prefabTransaction.assertParentUnchanged();
|
|
1222
1953
|
const parentState = prefabTransaction.parentSession.getState({ cloneDocuments: false });
|
|
1223
|
-
|
|
1224
|
-
|
|
1954
|
+
if (state.authoringHost) {
|
|
1955
|
+
await state.authoringHost.resetWithRelatedSession(parentState.persistedDocument, parentState.source, {
|
|
1956
|
+
expectedDocumentRevision: sessionState.documentRevision,
|
|
1957
|
+
relatedSession: prefabTransaction.parentSession,
|
|
1958
|
+
expectedRelatedDocumentRevision: parentState.documentRevision,
|
|
1959
|
+
mutateRelatedSession(parentDraftSession) {
|
|
1960
|
+
parentDraftSession.reset(parentState.persistedDocument, parentState.source);
|
|
1961
|
+
},
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
else {
|
|
1965
|
+
await state.runBrowserAuthoringMutation('document.discard', JSON.stringify({ documentRevision: sessionState.documentRevision }), authoringState => authoringState.session?.reset(parentState.persistedDocument, parentState.source));
|
|
1966
|
+
prefabTransaction.parentSession.reset(parentState.persistedDocument, parentState.source);
|
|
1967
|
+
}
|
|
1968
|
+
prefabTransaction.acceptParentRevision();
|
|
1225
1969
|
state.source = parentState.source ?? null;
|
|
1226
1970
|
state.summary = summarizeDocument(options, parentState.persistedDocument, state.source);
|
|
1227
1971
|
}
|
|
1228
1972
|
else {
|
|
1229
|
-
state.
|
|
1973
|
+
if (state.authoringHost) {
|
|
1974
|
+
await state.authoringHost.reset(sessionState.persistedDocument, sessionState.source, {
|
|
1975
|
+
expectedDocumentRevision: sessionState.documentRevision,
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
else {
|
|
1979
|
+
await state.runBrowserAuthoringMutation('document.discard', JSON.stringify({ documentRevision: sessionState.documentRevision }), authoringState => authoringState.session?.reset(sessionState.persistedDocument, sessionState.source));
|
|
1980
|
+
}
|
|
1230
1981
|
state.source = sessionState.source ?? null;
|
|
1231
1982
|
state.summary = summarizeDocument(options, sessionState.persistedDocument, state.source);
|
|
1232
1983
|
}
|
|
@@ -1235,21 +1986,76 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1235
1986
|
state.statusToneStatus = state.status;
|
|
1236
1987
|
state.statusDetails = '';
|
|
1237
1988
|
};
|
|
1238
|
-
const markDocumentCommitted = async (expectedDocumentFingerprint) => {
|
|
1989
|
+
const markDocumentCommitted = async (expectedDocumentFingerprint, expectedDocumentRevision, preparedAuthoringSource) => {
|
|
1239
1990
|
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
1240
1991
|
if (!state.session || !sessionState)
|
|
1241
1992
|
throw new Error('Cannot commit an unloaded editor document.');
|
|
1242
|
-
|
|
1993
|
+
const hasProjectServiceTransaction = Boolean(projectCommandService
|
|
1994
|
+
&& typeof preparedAuthoringSource?.serviceTransactionId === 'string'
|
|
1995
|
+
&& preparedAuthoringSource.serviceTransactionId.length > 0);
|
|
1996
|
+
if (!hasProjectServiceTransaction
|
|
1997
|
+
&& createLocalEditorDocumentFingerprint(sessionState.workingDocument) !== expectedDocumentFingerprint) {
|
|
1243
1998
|
throw new Error('Editor document changed after export; refusing to commit a stale snapshot.');
|
|
1244
1999
|
}
|
|
2000
|
+
const committedDocument = (preparedAuthoringSource?.document
|
|
2001
|
+
?? sessionState.workingDocument);
|
|
2002
|
+
const committedSource = preparedAuthoringSource?.source ?? sessionState.source;
|
|
1245
2003
|
const prefabTransaction = state.prefabStage?.transaction ?? null;
|
|
2004
|
+
if (projectCommandService) {
|
|
2005
|
+
const transactionId = typeof preparedAuthoringSource?.serviceTransactionId === 'string'
|
|
2006
|
+
? preparedAuthoringSource.serviceTransactionId
|
|
2007
|
+
: null;
|
|
2008
|
+
if (!transactionId) {
|
|
2009
|
+
throw new Error('Platform save confirmation is missing the Project Editor Service transaction.');
|
|
2010
|
+
}
|
|
2011
|
+
const serviceDocumentRevision = preparedAuthoringSource?.serviceDocumentRevision;
|
|
2012
|
+
if (!Number.isSafeInteger(serviceDocumentRevision) || (serviceDocumentRevision ?? -1) < 0) {
|
|
2013
|
+
throw new Error('Platform save confirmation is missing the Project Editor Service document revision.');
|
|
2014
|
+
}
|
|
2015
|
+
await invokeProjectServiceCommand('document.commit', { transactionId }, serviceDocumentRevision);
|
|
2016
|
+
const snapshot = await readProjectServiceSnapshot();
|
|
2017
|
+
if (!snapshot)
|
|
2018
|
+
throw new Error('Project Editor Service did not return the committed checkpoint.');
|
|
2019
|
+
await applyProjectServiceSnapshot(snapshot, true);
|
|
2020
|
+
state.source = sessionState.source ?? null;
|
|
2021
|
+
state.status = 'Platform save committed';
|
|
2022
|
+
state.statusTone = 'success';
|
|
2023
|
+
state.statusToneStatus = state.status;
|
|
2024
|
+
state.statusDetails = '';
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
1246
2027
|
if (prefabTransaction) {
|
|
1247
|
-
|
|
2028
|
+
if (!state.authoringHost)
|
|
2029
|
+
throw new Error('Cannot commit Prefab without an Editor Authoring Host.');
|
|
2030
|
+
if (expectedDocumentRevision === null) {
|
|
2031
|
+
throw new Error('Platform save confirmation is missing the exported document revision.');
|
|
2032
|
+
}
|
|
2033
|
+
await state.authoringHost.markSavedWithRelatedSession(committedDocument, {
|
|
2034
|
+
expectedDocumentRevision,
|
|
2035
|
+
source: committedSource,
|
|
2036
|
+
resetHistory: true,
|
|
2037
|
+
relatedSession: prefabTransaction.parentSession,
|
|
2038
|
+
expectedRelatedDocumentRevision: prefabTransaction.parentSession
|
|
2039
|
+
.getState({ cloneDocuments: false }).documentRevision,
|
|
2040
|
+
mutateRelatedSession(parentDraftSession) {
|
|
2041
|
+
prefabTransaction.stageParentSavedDocument(parentDraftSession, committedDocument, committedSource, `Apply Prefab ${state.prefabStage?.descriptor.label ?? 'changes'}`);
|
|
2042
|
+
},
|
|
2043
|
+
});
|
|
2044
|
+
prefabTransaction.acceptParentRevision();
|
|
1248
2045
|
}
|
|
1249
2046
|
else {
|
|
1250
|
-
state.
|
|
2047
|
+
if (!state.authoringHost)
|
|
2048
|
+
throw new Error('Cannot commit without an Editor Authoring Host.');
|
|
2049
|
+
if (expectedDocumentRevision === null) {
|
|
2050
|
+
throw new Error('Platform save confirmation is missing the exported document revision.');
|
|
2051
|
+
}
|
|
2052
|
+
await state.authoringHost.markSaved(committedDocument, {
|
|
2053
|
+
expectedDocumentRevision,
|
|
2054
|
+
source: committedSource,
|
|
2055
|
+
});
|
|
1251
2056
|
}
|
|
1252
|
-
state.source =
|
|
2057
|
+
state.source = committedSource ?? null;
|
|
2058
|
+
state.summary = summarizeDocument(options, committedDocument, committedSource);
|
|
1253
2059
|
state.status = 'Platform save committed';
|
|
1254
2060
|
state.statusTone = 'success';
|
|
1255
2061
|
state.statusToneStatus = state.status;
|
|
@@ -1330,10 +2136,36 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1330
2136
|
throw error;
|
|
1331
2137
|
}
|
|
1332
2138
|
};
|
|
2139
|
+
const renderSuppressedDocumentMarkDirtyPreview = () => {
|
|
2140
|
+
const lifecycleSnapshot = lifecycleController?.lifecycle.getSnapshot();
|
|
2141
|
+
const activeTransition = lifecycleSnapshot?.activeTransition;
|
|
2142
|
+
if (state.suppressDocumentMarkDirtyInspectorRefresh
|
|
2143
|
+
&& activeTransition?.type === 'document.markDirty') {
|
|
2144
|
+
suppressedDocumentMarkDirtyTransitionId = activeTransition.id;
|
|
2145
|
+
if (!ui.updatePreview)
|
|
2146
|
+
return false;
|
|
2147
|
+
ui.updatePreview({ session: createUiSessionState(state) });
|
|
2148
|
+
return true;
|
|
2149
|
+
}
|
|
2150
|
+
if (suppressedDocumentMarkDirtyTransitionId && lifecycleSnapshot && !lifecycleSnapshot.transitioning) {
|
|
2151
|
+
suppressedDocumentMarkDirtyTransitionId = null;
|
|
2152
|
+
state.suppressDocumentMarkDirtyInspectorRefresh = false;
|
|
2153
|
+
if (!ui.updatePreview)
|
|
2154
|
+
return false;
|
|
2155
|
+
ui.updatePreview({ session: createUiSessionState(state) });
|
|
2156
|
+
return true;
|
|
2157
|
+
}
|
|
2158
|
+
return false;
|
|
2159
|
+
};
|
|
1333
2160
|
harness = {
|
|
1334
2161
|
render() {
|
|
1335
2162
|
if (harnessDisposed)
|
|
1336
2163
|
return;
|
|
2164
|
+
if (renderSuppressedDocumentMarkDirtyPreview())
|
|
2165
|
+
return;
|
|
2166
|
+
if (lifecyclePresentationOnlyRenderDepth > 0)
|
|
2167
|
+
return;
|
|
2168
|
+
cancelInspectorPresentationPreview(state);
|
|
1337
2169
|
syncViewportCameraState(state);
|
|
1338
2170
|
syncViewportMeasurementState(state);
|
|
1339
2171
|
syncViewportSpatialOverlay(state, options);
|
|
@@ -1352,12 +2184,13 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1352
2184
|
getHostServices() {
|
|
1353
2185
|
return options.hostServices ?? null;
|
|
1354
2186
|
},
|
|
1355
|
-
|
|
1356
|
-
return state.
|
|
2187
|
+
getCommandService() {
|
|
2188
|
+
return state.commandService;
|
|
1357
2189
|
},
|
|
1358
2190
|
getWorkingDocument() {
|
|
1359
2191
|
return state.session?.getState().workingDocument ?? null;
|
|
1360
2192
|
},
|
|
2193
|
+
prepareProjectServiceDocumentExport,
|
|
1361
2194
|
projectAssetDropPoint(point) {
|
|
1362
2195
|
return projectBabylonViewportPointToGround({
|
|
1363
2196
|
babylon: state.babylon,
|
|
@@ -1429,7 +2262,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1429
2262
|
}
|
|
1430
2263
|
return runExclusiveResult(state, harness.render, transactionExecutor => executeLocalEditorDocumentOperation(busyOperationExecutors, transactionExecutor, operation), busyOperationExecutors);
|
|
1431
2264
|
},
|
|
1432
|
-
async reloadAssets() {
|
|
2265
|
+
async reloadAssets(serializedAccess) {
|
|
1433
2266
|
try {
|
|
1434
2267
|
const previousAssets = state.assets;
|
|
1435
2268
|
const [assets, projectFilesResult] = await Promise.all([
|
|
@@ -1440,7 +2273,8 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1440
2273
|
? findLocalEditorUpdatedAssetIds(options.documentAdapter.listAssetSnapshots(previousAssets), options.documentAdapter.listAssetSnapshots(assets))
|
|
1441
2274
|
: [];
|
|
1442
2275
|
if (state.session && options.documentAdapter.hydrateDocumentAssets) {
|
|
1443
|
-
const
|
|
2276
|
+
const expectedDocumentRevision = state.session.getState({ cloneDocuments: false }).documentRevision;
|
|
2277
|
+
const applyRefresh = (session = state.session) => applyLocalEditorUpdatedAssetsRefresh(session, {
|
|
1444
2278
|
assetIds: refreshedAssetIds,
|
|
1445
2279
|
assets,
|
|
1446
2280
|
hydrateDocumentAssets: options.documentAdapter.hydrateDocumentAssets,
|
|
@@ -1451,6 +2285,9 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1451
2285
|
? { compareDocuments: options.documentAdapter.compareDocuments }
|
|
1452
2286
|
: {}),
|
|
1453
2287
|
});
|
|
2288
|
+
const result = serializedAccess
|
|
2289
|
+
? state.authoringHost?.runSerializedExternalMutation(serializedAccess, expectedDocumentRevision, session => applyRefresh(session)) ?? (() => { throw new Error('Asset refresh authoring authority is unavailable.'); })()
|
|
2290
|
+
: await state.runBrowserAuthoringMutation('asset.library.refresh', JSON.stringify({ refreshedAssetIds }), authoringState => applyRefresh(authoringState.session));
|
|
1454
2291
|
syncLocalEditorUpdatedAssetProjection(state.updatedAssetProjection, result.changed, () => {
|
|
1455
2292
|
rebuildProjectionFromDocument(state, options, result.workingDocument, result.selection);
|
|
1456
2293
|
});
|
|
@@ -1515,7 +2352,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1515
2352
|
loadOptionalProjectFiles(),
|
|
1516
2353
|
]);
|
|
1517
2354
|
assertLocalEditorUpdatedAssetSnapshotFreshness(options.documentAdapter.resolveUpdatedAssetSnapshot(assets, { assetId: input.assetId }), input);
|
|
1518
|
-
const
|
|
2355
|
+
const applyRefresh = (authoringState) => applyLocalEditorUpdatedAssetRefresh(authoringState.session, {
|
|
1519
2356
|
assetId: input.assetId,
|
|
1520
2357
|
assets,
|
|
1521
2358
|
hydrateDocumentAssets: options.documentAdapter.hydrateDocumentAssets,
|
|
@@ -1526,6 +2363,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1526
2363
|
? { compareDocuments: options.documentAdapter.compareDocuments }
|
|
1527
2364
|
: {}),
|
|
1528
2365
|
});
|
|
2366
|
+
const result = await state.runBrowserAuthoringMutation('asset.library.refreshUpdated', JSON.stringify(input), applyRefresh);
|
|
1529
2367
|
state.assets = assets;
|
|
1530
2368
|
state.projectFiles = projectFilesResult.projectFiles;
|
|
1531
2369
|
state.projectFilesWarning = projectFilesResult.warning;
|
|
@@ -1579,19 +2417,33 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1579
2417
|
}
|
|
1580
2418
|
},
|
|
1581
2419
|
createAssetFromAssetId(assetId, createOptions) {
|
|
1582
|
-
const
|
|
2420
|
+
const execute = (session = state.session ?? undefined) => addAssetToDocument(state, options, assetId, createOptions, session);
|
|
2421
|
+
const immediate = state.tryRunBrowserAuthoringMutationImmediately('object.createFromAsset', JSON.stringify({ assetId, createOptions }), session => execute(session));
|
|
2422
|
+
const result = immediate.ok ? immediate.value : {
|
|
2423
|
+
ok: false,
|
|
2424
|
+
assetId,
|
|
2425
|
+
changed: false,
|
|
2426
|
+
status: `Asset creation unavailable: ${immediate.reason}`,
|
|
2427
|
+
error: 'authoring_busy',
|
|
2428
|
+
};
|
|
1583
2429
|
harness.render();
|
|
1584
2430
|
return result;
|
|
1585
2431
|
},
|
|
1586
2432
|
async undo(historyOptions) {
|
|
1587
|
-
|
|
1588
|
-
|
|
2433
|
+
if (projectCommandService) {
|
|
2434
|
+
return runProjectServiceHistoryOperation('undo', historyOptions);
|
|
2435
|
+
}
|
|
2436
|
+
const result = await state.runBrowserAuthoringMutation('history.undo', JSON.stringify(historyOptions ?? {}), authoringState => applyHistoryOperation(authoringState, options, 'undo', historyOptions));
|
|
2437
|
+
if (result.ok && !applyHistoryPresentation(result.presentationImpact))
|
|
1589
2438
|
harness.render();
|
|
1590
2439
|
return waitForHistoryOperationProjection(state, result);
|
|
1591
2440
|
},
|
|
1592
2441
|
async redo(historyOptions) {
|
|
1593
|
-
|
|
1594
|
-
|
|
2442
|
+
if (projectCommandService) {
|
|
2443
|
+
return runProjectServiceHistoryOperation('redo', historyOptions);
|
|
2444
|
+
}
|
|
2445
|
+
const result = await state.runBrowserAuthoringMutation('history.redo', JSON.stringify(historyOptions ?? {}), authoringState => applyHistoryOperation(authoringState, options, 'redo', historyOptions));
|
|
2446
|
+
if (result.ok && !applyHistoryPresentation(result.presentationImpact))
|
|
1595
2447
|
harness.render();
|
|
1596
2448
|
return waitForHistoryOperationProjection(state, result);
|
|
1597
2449
|
},
|
|
@@ -1599,13 +2451,13 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1599
2451
|
await loadEditorDocument();
|
|
1600
2452
|
await enterEditorWorld();
|
|
1601
2453
|
},
|
|
1602
|
-
async saveScene(executor, saveOptions) {
|
|
2454
|
+
async saveScene(executor, saveOptions, serializedAccess) {
|
|
1603
2455
|
cancelActiveOperation(state);
|
|
1604
2456
|
const validationPhases = [...new Set([
|
|
1605
2457
|
...(saveOptions?.validationPhases ?? []),
|
|
1606
2458
|
'save',
|
|
1607
2459
|
])];
|
|
1608
|
-
const refreshResult = await runValidatedExclusiveDocumentOperation('save', () => harness.reloadAssets(), executor, validationPhases);
|
|
2460
|
+
const refreshResult = await runValidatedExclusiveDocumentOperation('save', () => harness.reloadAssets(serializedAccess), executor, validationPhases);
|
|
1609
2461
|
if (!refreshResult.accepted)
|
|
1610
2462
|
return false;
|
|
1611
2463
|
const assetRefresh = refreshResult.value;
|
|
@@ -1620,6 +2472,19 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1620
2472
|
const prefabTransaction = state.prefabStage?.transaction ?? null;
|
|
1621
2473
|
try {
|
|
1622
2474
|
prefabTransaction?.assertParentUnchanged();
|
|
2475
|
+
if (projectCommandService) {
|
|
2476
|
+
await invokeProjectServiceCommand('document.save');
|
|
2477
|
+
const snapshot = await readProjectServiceSnapshot();
|
|
2478
|
+
if (!snapshot)
|
|
2479
|
+
throw new Error('Project Editor Service did not return the saved checkpoint.');
|
|
2480
|
+
await applyProjectServiceSnapshot(snapshot, true);
|
|
2481
|
+
state.summary = summarizeDocument(options, snapshot.document, state.source);
|
|
2482
|
+
state.status = prefabTransaction ? 'Prefab saved' : 'Scene saved';
|
|
2483
|
+
state.statusTone = 'success';
|
|
2484
|
+
state.statusToneStatus = state.status;
|
|
2485
|
+
state.statusDetails = '';
|
|
2486
|
+
return true;
|
|
2487
|
+
}
|
|
1623
2488
|
let savedSource = source;
|
|
1624
2489
|
let result;
|
|
1625
2490
|
if (source && options.authoringHost) {
|
|
@@ -1663,10 +2528,34 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1663
2528
|
state.source = savedSource ?? null;
|
|
1664
2529
|
if (state.session) {
|
|
1665
2530
|
if (prefabTransaction && state.prefabStage?.transaction === prefabTransaction) {
|
|
1666
|
-
|
|
2531
|
+
if (!state.authoringHost)
|
|
2532
|
+
throw new Error('Cannot save Prefab without an Editor Authoring Host.');
|
|
2533
|
+
if (expectedAuthoredVersion === null)
|
|
2534
|
+
throw new Error('Cannot save without an expected document revision.');
|
|
2535
|
+
await state.authoringHost.markSavedWithRelatedSession(preparedDocument, {
|
|
2536
|
+
expectedDocumentRevision: expectedAuthoredVersion,
|
|
2537
|
+
source: savedSource ?? undefined,
|
|
2538
|
+
resetHistory: true,
|
|
2539
|
+
relatedSession: prefabTransaction.parentSession,
|
|
2540
|
+
expectedRelatedDocumentRevision: prefabTransaction.parentSession
|
|
2541
|
+
.getState({ cloneDocuments: false }).documentRevision,
|
|
2542
|
+
mutateRelatedSession(parentDraftSession) {
|
|
2543
|
+
prefabTransaction.stageParentSavedDocument(parentDraftSession, preparedDocument, savedSource ?? undefined, `Apply Prefab ${state.prefabStage?.descriptor.label ?? 'changes'}`);
|
|
2544
|
+
},
|
|
2545
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
2546
|
+
});
|
|
2547
|
+
prefabTransaction.acceptParentRevision();
|
|
1667
2548
|
}
|
|
1668
2549
|
else {
|
|
1669
|
-
state.
|
|
2550
|
+
if (!state.authoringHost)
|
|
2551
|
+
throw new Error('Cannot save without an Editor Authoring Host.');
|
|
2552
|
+
if (expectedAuthoredVersion === null)
|
|
2553
|
+
throw new Error('Cannot save without an expected document revision.');
|
|
2554
|
+
await state.authoringHost.markSaved(preparedDocument, {
|
|
2555
|
+
expectedDocumentRevision: expectedAuthoredVersion,
|
|
2556
|
+
source: savedSource ?? undefined,
|
|
2557
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
2558
|
+
});
|
|
1670
2559
|
}
|
|
1671
2560
|
}
|
|
1672
2561
|
else {
|
|
@@ -1678,7 +2567,7 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1678
2567
|
cloneDocument: options.documentAdapter.cloneDocument,
|
|
1679
2568
|
compareDocuments: options.documentAdapter.compareDocuments,
|
|
1680
2569
|
reduceDocument: options.documentAdapter.reduceDocument,
|
|
1681
|
-
isDocumentStructureChange: options.documentAdapter.isHierarchyStructureChange,
|
|
2570
|
+
isDocumentStructureChange: command => resolveLocalEditorDocumentStructureChange(options.documentAdapter.isHierarchyStructureChange, command),
|
|
1682
2571
|
onChange: createSessionChangeObserver(() => mainSession, {
|
|
1683
2572
|
document: PLAYABLE_LOCAL_EDITOR_MAIN_DOCUMENT_SCOPE_ID,
|
|
1684
2573
|
session: PLAYABLE_LOCAL_EDITOR_MAIN_SESSION_SCOPE_ID,
|
|
@@ -1687,9 +2576,14 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1687
2576
|
});
|
|
1688
2577
|
state.session = mainSession;
|
|
1689
2578
|
try {
|
|
2579
|
+
await replaceAuthoringHost(mainSession);
|
|
1690
2580
|
attachLifecycleOwnedSessionAuthority();
|
|
2581
|
+
activateCommandAuthority();
|
|
1691
2582
|
}
|
|
1692
2583
|
catch (error) {
|
|
2584
|
+
state.authoringHost?.dispose();
|
|
2585
|
+
state.authoringHost = null;
|
|
2586
|
+
state.replaceProjectionSessionAuthority(null);
|
|
1693
2587
|
state.session = null;
|
|
1694
2588
|
state.source = null;
|
|
1695
2589
|
throw error;
|
|
@@ -1736,20 +2630,22 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1736
2630
|
};
|
|
1737
2631
|
agentLifecycleController = {
|
|
1738
2632
|
enterEditor: () => harness.enterEditor(),
|
|
1739
|
-
saveScene: (_operation,
|
|
2633
|
+
saveScene: (_operation, context, executor) => harness.saveScene(executor, undefined, context
|
|
2634
|
+
?.serializedAuthoringAccess),
|
|
1740
2635
|
saveAndRunGame: (_context, executor) => harness.saveAndRunGame(executor),
|
|
1741
2636
|
async discardAndRunGame(_context, executor) {
|
|
1742
2637
|
await harness.discardAndRunGame(executor);
|
|
1743
2638
|
return true;
|
|
1744
2639
|
},
|
|
1745
|
-
async prepareSaveAndRunGame(
|
|
2640
|
+
async prepareSaveAndRunGame(context, executor) {
|
|
1746
2641
|
return harness.runExclusiveDocumentOperation(async (transactionExecutor) => {
|
|
1747
2642
|
const initialValidation = await runValidatedExclusiveDocumentOperation('run', async () => true, transactionExecutor);
|
|
1748
2643
|
if (!initialValidation.accepted)
|
|
1749
2644
|
return { accepted: false };
|
|
1750
2645
|
const saved = await harness.saveScene(transactionExecutor, {
|
|
1751
2646
|
validationPhases: ['run', 'save'],
|
|
1752
|
-
}
|
|
2647
|
+
}, context
|
|
2648
|
+
?.serializedAuthoringAccess);
|
|
1753
2649
|
if (!saved)
|
|
1754
2650
|
return { accepted: false };
|
|
1755
2651
|
const finalValidation = await runValidatedExclusiveDocumentOperation('run', async (documentRevision) => documentRevision, transactionExecutor);
|
|
@@ -1797,21 +2693,26 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1797
2693
|
}, executor);
|
|
1798
2694
|
},
|
|
1799
2695
|
};
|
|
1800
|
-
const
|
|
1801
|
-
createAssetFromAssetId: (assetId, createOptions) =>
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
2696
|
+
const commandServiceCapabilitySourceOperations = {
|
|
2697
|
+
createAssetFromAssetId: (assetId, createOptions) => {
|
|
2698
|
+
const result = addAssetToDocument(state, options, assetId, createOptions);
|
|
2699
|
+
harness.render();
|
|
2700
|
+
return result;
|
|
2701
|
+
},
|
|
2702
|
+
getPrefabStage: () => summarizeEditorCommandPrefabStage(state, options),
|
|
2703
|
+
getPrefabStageDetails: () => summarizeEditorCommandPrefabStageDetails(state, options),
|
|
2704
|
+
openPrefabStage: (input, access) => runExclusiveResult(state, harness.render, async (executor) => {
|
|
2705
|
+
const serializedAccess = access;
|
|
2706
|
+
const previousStage = summarizeEditorCommandPrefabStage(state, options);
|
|
1806
2707
|
if (previousStage
|
|
1807
2708
|
&& previousStage.assetId !== input.assetId
|
|
1808
2709
|
&& state.prefabStage?.transaction.snapshot().stageDirty) {
|
|
1809
2710
|
if (input.dirtyAction === 'save') {
|
|
1810
|
-
if (!await harness.saveScene(executor))
|
|
2711
|
+
if (!await harness.saveScene(executor, undefined, serializedAccess))
|
|
1811
2712
|
return null;
|
|
1812
2713
|
}
|
|
1813
2714
|
else if (input.dirtyAction === 'discard') {
|
|
1814
|
-
discardPrefabStageChanges();
|
|
2715
|
+
await discardPrefabStageChanges(serializedAccess);
|
|
1815
2716
|
}
|
|
1816
2717
|
else {
|
|
1817
2718
|
state.status = 'Prefab has unsaved changes';
|
|
@@ -1826,32 +2727,33 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1826
2727
|
assetId: input.assetId,
|
|
1827
2728
|
browserAssetId: input.browserAssetId,
|
|
1828
2729
|
assetKind: 'prefab',
|
|
1829
|
-
});
|
|
1830
|
-
const stage =
|
|
2730
|
+
}, serializedAccess);
|
|
2731
|
+
const stage = summarizeEditorCommandPrefabStage(state, options);
|
|
1831
2732
|
if (!opened || !stage)
|
|
1832
2733
|
return null;
|
|
1833
|
-
const alreadyOpen =
|
|
2734
|
+
const alreadyOpen = isSameEditorCommandPrefabStage(previousStage, stage);
|
|
1834
2735
|
return {
|
|
1835
2736
|
opened: !alreadyOpen,
|
|
1836
2737
|
alreadyOpen,
|
|
1837
|
-
prefab:
|
|
2738
|
+
prefab: createEditorCommandPrefabSummaryFromStage(stage),
|
|
1838
2739
|
stage,
|
|
1839
2740
|
status: state.status,
|
|
1840
2741
|
};
|
|
1841
2742
|
}, busyOperationExecutors),
|
|
1842
|
-
exitPrefabStage: (input = {}) => runExclusiveResult(state, harness.render, async (executor) => {
|
|
1843
|
-
const
|
|
2743
|
+
exitPrefabStage: (input = {}, access) => runExclusiveResult(state, harness.render, async (executor) => {
|
|
2744
|
+
const serializedAccess = access;
|
|
2745
|
+
const previousStage = summarizeEditorCommandPrefabStage(state, options);
|
|
1844
2746
|
if (state.prefabStage?.transaction.snapshot().stageDirty) {
|
|
1845
2747
|
if (input.dirtyAction === 'save') {
|
|
1846
|
-
if (!await harness.saveScene(executor)) {
|
|
2748
|
+
if (!await harness.saveScene(executor, undefined, serializedAccess)) {
|
|
1847
2749
|
return { exited: false, wasOpen: true, previousStage, status: state.status };
|
|
1848
2750
|
}
|
|
1849
2751
|
}
|
|
1850
2752
|
else if (input.dirtyAction === 'discard') {
|
|
1851
|
-
discardPrefabStageChanges();
|
|
2753
|
+
await discardPrefabStageChanges(serializedAccess);
|
|
1852
2754
|
}
|
|
1853
2755
|
}
|
|
1854
|
-
const exited = await exitPrefabStage(state, options, 'reject');
|
|
2756
|
+
const exited = await exitPrefabStage(state, options, 'reject', serializedAccess);
|
|
1855
2757
|
return {
|
|
1856
2758
|
exited,
|
|
1857
2759
|
wasOpen: !!previousStage,
|
|
@@ -1859,8 +2761,8 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1859
2761
|
status: exited ? state.status : previousStage ? state.status : 'No Prefab stage is open.',
|
|
1860
2762
|
};
|
|
1861
2763
|
}, busyOperationExecutors),
|
|
1862
|
-
savePrefabStage:
|
|
1863
|
-
discardPrefabStage:
|
|
2764
|
+
savePrefabStage: access => runExclusiveResult(state, harness.render, executor => (runPrefabContextAction(PREFAB_STAGE_CONTEXT_ACTION_IDS.save, executor, access)), busyOperationExecutors),
|
|
2765
|
+
discardPrefabStage: access => discardPrefabStageChanges(access),
|
|
1864
2766
|
selectPrefabStageItem: itemId => selectPrefabStageItemWithPreviewSync(state, options, itemId),
|
|
1865
2767
|
runPrefabStageAssetAction: input => patchBrowserAssetAction(state, options, input),
|
|
1866
2768
|
getHierarchyReadModel,
|
|
@@ -1933,10 +2835,10 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1933
2835
|
})),
|
|
1934
2836
|
};
|
|
1935
2837
|
},
|
|
1936
|
-
executeHierarchyOperation: async (input) => {
|
|
2838
|
+
executeHierarchyOperation: async (input, serializedAccess) => {
|
|
1937
2839
|
const model = getRequiredHierarchyViewModel();
|
|
1938
2840
|
const { snapshot } = model;
|
|
1939
|
-
const
|
|
2841
|
+
const invocation = {
|
|
1940
2842
|
type: 'operation.execute',
|
|
1941
2843
|
operationId: input.operationId,
|
|
1942
2844
|
expectedAuthorityToken: model.authorityToken,
|
|
@@ -1948,9 +2850,13 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
1948
2850
|
contextNodeId: 'contextNodeId' in input ? input.contextNodeId ?? null : snapshot.activeId,
|
|
1949
2851
|
targetIds: input.targetIds ?? [...snapshot.selectedIds],
|
|
1950
2852
|
activeId: 'activeId' in input ? input.activeId ?? null : snapshot.activeId,
|
|
2853
|
+
...(serializedAccess !== undefined
|
|
2854
|
+
? { [SERIALIZED_HIERARCHY_INVOCATION]: serializedAccess }
|
|
2855
|
+
: {}),
|
|
1951
2856
|
},
|
|
1952
2857
|
...(input.input ? { input: input.input } : {}),
|
|
1953
|
-
}
|
|
2858
|
+
};
|
|
2859
|
+
const result = await hierarchyKernel.dispatch(invocation);
|
|
1954
2860
|
return {
|
|
1955
2861
|
ok: result.ok,
|
|
1956
2862
|
changed: result.changed,
|
|
@@ -2012,10 +2918,10 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2012
2918
|
},
|
|
2013
2919
|
runRenderingAction: actionId => applyRenderingAction(state, options, { actionId }, () => harness.render()),
|
|
2014
2920
|
};
|
|
2015
|
-
const
|
|
2016
|
-
if (state.
|
|
2921
|
+
const registerCommandCapabilities = () => {
|
|
2922
|
+
if (state.unregisterCommandCapabilities)
|
|
2017
2923
|
return;
|
|
2018
|
-
const unregisterStandardAgentCapabilities =
|
|
2924
|
+
const unregisterStandardAgentCapabilities = registerLocalEditorCommandCapabilities(state.commandService, createLocalEditorCommandCapabilitySources(state, options, () => harness.render(), context => runExclusive(state, harness.render, () => agentLifecycleController.enterEditor(context), busyOperationExecutors), async (context) => {
|
|
2019
2925
|
const prepared = await runExclusiveResult(state, harness.render, executor => agentLifecycleController.prepareSaveAndRunGame(context, executor), busyOperationExecutors);
|
|
2020
2926
|
if (prepared.accepted)
|
|
2021
2927
|
scheduleEditorLifecycleExit(executor => prepared.run(executor));
|
|
@@ -2025,10 +2931,12 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2025
2931
|
if (prepared.accepted)
|
|
2026
2932
|
scheduleEditorLifecycleExit(executor => prepared.run(executor));
|
|
2027
2933
|
return prepared.accepted;
|
|
2028
|
-
},
|
|
2934
|
+
}, commandServiceCapabilitySourceOperations), state.authoringHost ?? undefined);
|
|
2029
2935
|
try {
|
|
2030
|
-
const unregisterPluginAgentCapabilities =
|
|
2031
|
-
|
|
2936
|
+
const unregisterPluginAgentCapabilities = state.authoringHost
|
|
2937
|
+
? registerEditorPluginCommands(state.commandService, options.pluginHost, state.authoringHost)
|
|
2938
|
+
: () => undefined;
|
|
2939
|
+
state.unregisterCommandCapabilities = () => {
|
|
2032
2940
|
const errors = [];
|
|
2033
2941
|
try {
|
|
2034
2942
|
unregisterPluginAgentCapabilities();
|
|
@@ -2043,44 +2951,50 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2043
2951
|
errors.push(error);
|
|
2044
2952
|
}
|
|
2045
2953
|
if (errors.length > 0) {
|
|
2046
|
-
const error = new Error('Local Editor
|
|
2954
|
+
const error = new Error('Local Editor command cleanup failed.');
|
|
2047
2955
|
error.errors = errors;
|
|
2048
2956
|
throw error;
|
|
2049
2957
|
}
|
|
2050
2958
|
};
|
|
2959
|
+
if (projectCommandService && !disposeBrowserCommandAttachment) {
|
|
2960
|
+
const handlers = Object.fromEntries(state.commandService.commandSystem.listManifests()
|
|
2961
|
+
.map(manifest => [manifest.id, async (input, request) => {
|
|
2962
|
+
if (harnessDisposed)
|
|
2963
|
+
throw new Error('Local editor harness has been disposed.');
|
|
2964
|
+
const result = await state.commandService.callCapability(manifest.id, input, {
|
|
2965
|
+
...(request.invocation.traceId ? { traceId: request.invocation.traceId } : {}),
|
|
2966
|
+
...(request.invocation.traceStepId ? { traceStepId: request.invocation.traceStepId } : {}),
|
|
2967
|
+
});
|
|
2968
|
+
if (!result.ok)
|
|
2969
|
+
throw new Error(result.diagnostics.map(diagnostic => diagnostic.message).join('; '));
|
|
2970
|
+
return result.output;
|
|
2971
|
+
}]));
|
|
2972
|
+
disposeBrowserCommandAttachment = projectCommandService.attach({
|
|
2973
|
+
attachmentId: browserCommandAttachmentId,
|
|
2974
|
+
label: 'Local Editor Command Host',
|
|
2975
|
+
handlers,
|
|
2976
|
+
}).catch(() => null);
|
|
2977
|
+
}
|
|
2051
2978
|
}
|
|
2052
2979
|
catch (error) {
|
|
2053
2980
|
try {
|
|
2054
2981
|
unregisterStandardAgentCapabilities();
|
|
2055
2982
|
}
|
|
2056
2983
|
catch (cleanupError) {
|
|
2057
|
-
const combined = new Error('Plugin
|
|
2984
|
+
const combined = new Error('Plugin command registration failed and standard command rollback reported errors.');
|
|
2058
2985
|
combined.errors = [error, cleanupError];
|
|
2059
2986
|
throw combined;
|
|
2060
2987
|
}
|
|
2061
2988
|
throw error;
|
|
2062
2989
|
}
|
|
2063
2990
|
};
|
|
2064
|
-
const
|
|
2065
|
-
|
|
2066
|
-
if (state.agentBridgeTransport)
|
|
2067
|
-
return;
|
|
2068
|
-
state.agentBridgeTransport = createLocalEditorAgentBridgeWebSocketTransportFromQuery(state.agentBridge, {
|
|
2069
|
-
metadata: options.agentBridge?.sessionMetadata,
|
|
2070
|
-
onStatusChange: agentBridgeStatus => {
|
|
2071
|
-
state.agentBridgeStatus = agentBridgeStatus;
|
|
2072
|
-
harness.render();
|
|
2073
|
-
},
|
|
2074
|
-
});
|
|
2991
|
+
const activateCommandAuthority = () => {
|
|
2992
|
+
registerCommandCapabilities();
|
|
2075
2993
|
};
|
|
2076
|
-
const
|
|
2077
|
-
if (state.
|
|
2078
|
-
state.
|
|
2079
|
-
state.
|
|
2080
|
-
}
|
|
2081
|
-
if (state.unregisterAgentBridgeCapabilities) {
|
|
2082
|
-
state.unregisterAgentBridgeCapabilities();
|
|
2083
|
-
state.unregisterAgentBridgeCapabilities = null;
|
|
2994
|
+
const disposeCommandAuthority = () => {
|
|
2995
|
+
if (state.unregisterCommandCapabilities) {
|
|
2996
|
+
state.unregisterCommandCapabilities();
|
|
2997
|
+
state.unregisterCommandCapabilities = null;
|
|
2084
2998
|
}
|
|
2085
2999
|
};
|
|
2086
3000
|
const attachLifecycleOwnedApplicationAuthority = () => {
|
|
@@ -2088,46 +3002,14 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2088
3002
|
return;
|
|
2089
3003
|
if (!unsubscribeLifecycleRender)
|
|
2090
3004
|
attachLifecycleRenderSubscription();
|
|
2091
|
-
|
|
2092
|
-
attachAgentBridgeLifecycleParticipant();
|
|
3005
|
+
activateCommandAuthority();
|
|
2093
3006
|
if (!releaseApplicationAuthorityScopeResource) {
|
|
2094
3007
|
releaseApplicationAuthorityScopeResource = lifecycleController.addScopeResource(PLAYABLE_LOCAL_EDITOR_APPLICATION_SCOPE_ID, () => {
|
|
2095
|
-
|
|
3008
|
+
disposeCommandAuthority();
|
|
2096
3009
|
releaseApplicationAuthorityScopeResource = null;
|
|
2097
3010
|
});
|
|
2098
3011
|
}
|
|
2099
3012
|
};
|
|
2100
|
-
const reportAgentBridgeLifecycleTransition = (event) => {
|
|
2101
|
-
const transitionId = event.transition.id;
|
|
2102
|
-
const transport = agentBridgeLifecycleTransports.get(transitionId)
|
|
2103
|
-
?? state.agentBridgeTransport;
|
|
2104
|
-
transport?.reportLifecycleTransition(event);
|
|
2105
|
-
if (event.status !== 'started')
|
|
2106
|
-
agentBridgeLifecycleTransports.delete(transitionId);
|
|
2107
|
-
};
|
|
2108
|
-
const attachAgentBridgeLifecycleParticipant = () => {
|
|
2109
|
-
unregisterAgentBridgeLifecycleParticipant?.();
|
|
2110
|
-
unregisterAgentBridgeLifecycleParticipant = null;
|
|
2111
|
-
if (!lifecycleController)
|
|
2112
|
-
return;
|
|
2113
|
-
unregisterAgentBridgeLifecycleParticipant = lifecycleController.registerParticipant({
|
|
2114
|
-
id: 'fps.editor.agent-bridge.lifecycle-trace',
|
|
2115
|
-
transitions: FPS_EDITOR_LIFECYCLE_TRANSITION_TYPES,
|
|
2116
|
-
prepare(context) {
|
|
2117
|
-
const transport = state.agentBridgeTransport;
|
|
2118
|
-
if (transport)
|
|
2119
|
-
agentBridgeLifecycleTransports.set(context.transition.id, transport);
|
|
2120
|
-
reportAgentBridgeLifecycleTransition({
|
|
2121
|
-
status: 'started',
|
|
2122
|
-
transition: context.transition,
|
|
2123
|
-
previous: context.before,
|
|
2124
|
-
current: context.getSnapshot(),
|
|
2125
|
-
});
|
|
2126
|
-
},
|
|
2127
|
-
settled: reportAgentBridgeLifecycleTransition,
|
|
2128
|
-
failed: reportAgentBridgeLifecycleTransition,
|
|
2129
|
-
});
|
|
2130
|
-
};
|
|
2131
3013
|
const attachLifecycleRenderSubscription = () => {
|
|
2132
3014
|
releaseLifecycleRenderScopeResource?.();
|
|
2133
3015
|
releaseLifecycleRenderScopeResource = null;
|
|
@@ -2136,7 +3018,26 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2136
3018
|
if (!lifecycleController)
|
|
2137
3019
|
return;
|
|
2138
3020
|
const lifecycle = lifecycleController.lifecycle;
|
|
2139
|
-
const unsubscribe = lifecycle.subscribe(() =>
|
|
3021
|
+
const unsubscribe = lifecycle.subscribe(() => {
|
|
3022
|
+
let presentationApplied = false;
|
|
3023
|
+
try {
|
|
3024
|
+
presentationApplied = ui.updatePresentationDelta?.({
|
|
3025
|
+
pluginPanel: createLocalEditorPluginPanelState(options.pluginHost, state.lifecycle),
|
|
3026
|
+
}) === true;
|
|
3027
|
+
}
|
|
3028
|
+
catch {
|
|
3029
|
+
// The authoritative full render below preserves lifecycle presentation on adapter failure.
|
|
3030
|
+
}
|
|
3031
|
+
if (presentationApplied)
|
|
3032
|
+
lifecyclePresentationOnlyRenderDepth += 1;
|
|
3033
|
+
try {
|
|
3034
|
+
harness.render();
|
|
3035
|
+
}
|
|
3036
|
+
finally {
|
|
3037
|
+
if (presentationApplied)
|
|
3038
|
+
lifecyclePresentationOnlyRenderDepth -= 1;
|
|
3039
|
+
}
|
|
3040
|
+
});
|
|
2140
3041
|
unsubscribeLifecycleRender = unsubscribe;
|
|
2141
3042
|
releaseLifecycleRenderScopeResource = lifecycleController.addScopeResource(PLAYABLE_LOCAL_EDITOR_APPLICATION_SCOPE_ID, () => {
|
|
2142
3043
|
unsubscribe();
|
|
@@ -2149,14 +3050,18 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2149
3050
|
if (!lifecycleController || !state.session)
|
|
2150
3051
|
return;
|
|
2151
3052
|
if (!releaseMainSessionScopeResource) {
|
|
2152
|
-
releaseMainSessionScopeResource = lifecycleController.addScopeResource(PLAYABLE_LOCAL_EDITOR_MAIN_SESSION_SCOPE_ID, () => {
|
|
3053
|
+
releaseMainSessionScopeResource = lifecycleController.addScopeResource(PLAYABLE_LOCAL_EDITOR_MAIN_SESSION_SCOPE_ID, async () => {
|
|
3054
|
+
state.authoringHost?.dispose();
|
|
3055
|
+
await state.authoringHost?.drain();
|
|
3056
|
+
state.authoringHost = null;
|
|
3057
|
+
state.replaceProjectionSessionAuthority(null);
|
|
2153
3058
|
state.session = null;
|
|
2154
3059
|
state.source = null;
|
|
2155
3060
|
releaseMainSessionScopeResource = null;
|
|
2156
3061
|
});
|
|
2157
3062
|
}
|
|
2158
3063
|
};
|
|
2159
|
-
|
|
3064
|
+
activateCommandAuthority();
|
|
2160
3065
|
registerLocalEditorHarnessLifecycleOperations(harness, {
|
|
2161
3066
|
runGame: startGameRuntime,
|
|
2162
3067
|
validateRun: async () => {
|
|
@@ -2197,9 +3102,45 @@ function createLocalEditorHarnessImplementation(options, construction) {
|
|
|
2197
3102
|
state.statusDetails = stringifyLocalEditorError(error) ?? 'Unknown Tool activation error';
|
|
2198
3103
|
harness.render();
|
|
2199
3104
|
});
|
|
3105
|
+
if (projectCommandService) {
|
|
3106
|
+
void projectCommandService.watchAuthoring({
|
|
3107
|
+
onSnapshot: snapshot => applyProjectServiceSnapshot(snapshot),
|
|
3108
|
+
async onEvents(events) {
|
|
3109
|
+
if (events.length === 0)
|
|
3110
|
+
return;
|
|
3111
|
+
const snapshot = await readProjectServiceSnapshot();
|
|
3112
|
+
if (snapshot)
|
|
3113
|
+
await applyProjectServiceSnapshot(snapshot);
|
|
3114
|
+
},
|
|
3115
|
+
onIdle: () => state.reconcilePendingProjectServiceSnapshot(),
|
|
3116
|
+
onError(error) {
|
|
3117
|
+
if (harnessDisposed)
|
|
3118
|
+
return;
|
|
3119
|
+
reportBrowserAuthoringFailure(state, () => harness.render(), error);
|
|
3120
|
+
},
|
|
3121
|
+
}).then((stop) => {
|
|
3122
|
+
if (harnessDisposed)
|
|
3123
|
+
stop();
|
|
3124
|
+
else
|
|
3125
|
+
stopProjectServiceWatch = stop;
|
|
3126
|
+
}).catch((error) => {
|
|
3127
|
+
if (harnessDisposed)
|
|
3128
|
+
return;
|
|
3129
|
+
state.status = 'Project Editor Service connection failed';
|
|
3130
|
+
state.statusTone = 'error';
|
|
3131
|
+
state.statusToneStatus = state.status;
|
|
3132
|
+
state.statusDetails = stringifyLocalEditorError(error) ?? 'Unknown Editor Service error';
|
|
3133
|
+
harness.render();
|
|
3134
|
+
});
|
|
3135
|
+
}
|
|
2200
3136
|
harness.render();
|
|
2201
3137
|
return harness;
|
|
2202
3138
|
}
|
|
3139
|
+
let localEditorAuthoringServiceSequence = 0;
|
|
3140
|
+
function createLocalEditorAuthoringServiceInstanceId() {
|
|
3141
|
+
localEditorAuthoringServiceSequence += 1;
|
|
3142
|
+
return `local-editor-${Date.now().toString(36)}-${localEditorAuthoringServiceSequence.toString(36)}`;
|
|
3143
|
+
}
|
|
2203
3144
|
function createLocalEditorDocumentFingerprint(document) {
|
|
2204
3145
|
if (document == null)
|
|
2205
3146
|
return null;
|
|
@@ -2221,11 +3162,13 @@ function disposeLocalEditorHarnessResources(state, ui, hierarchyKernel) {
|
|
|
2221
3162
|
errors.push(error);
|
|
2222
3163
|
}
|
|
2223
3164
|
};
|
|
2224
|
-
dispose(() => state.
|
|
2225
|
-
|
|
2226
|
-
|
|
3165
|
+
dispose(() => state.unregisterCommandCapabilities?.(), () => {
|
|
3166
|
+
state.unregisterCommandCapabilities = null;
|
|
3167
|
+
});
|
|
3168
|
+
dispose(() => disposeEditorWorld(state), () => {
|
|
3169
|
+
state.replaceProjectionSessionAuthority(null);
|
|
3170
|
+
state.session = null;
|
|
2227
3171
|
});
|
|
2228
|
-
dispose(() => disposeEditorWorld(state), () => { state.session = null; });
|
|
2229
3172
|
dispose(() => ui.dispose());
|
|
2230
3173
|
dispose(() => hierarchyKernel.setProviders([]));
|
|
2231
3174
|
if (errors.length > 0) {
|
|
@@ -2274,7 +3217,7 @@ export function mergeLocalEditorHarnessInspectorComponentSections(input) {
|
|
|
2274
3217
|
}),
|
|
2275
3218
|
};
|
|
2276
3219
|
}
|
|
2277
|
-
function
|
|
3220
|
+
function isEditorCommandObjectSelectable(options, document, objectId, hierarchyItems) {
|
|
2278
3221
|
const inHierarchy = hierarchyItems.some(item => item.id === objectId);
|
|
2279
3222
|
const hasProjectionNode = !!options.documentAdapter.getProjectionNode(document, objectId);
|
|
2280
3223
|
if (!inHierarchy && !hasProjectionNode)
|
|
@@ -2678,10 +3621,31 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
|
|
|
2678
3621
|
},
|
|
2679
3622
|
onProjectionReady(event) {
|
|
2680
3623
|
getLocalEditorEditingContext(state).handleProjectionReady(event.nodeId);
|
|
3624
|
+
if (isProjectionInspectorRefreshSuppressed(state, event.nodeId, event.batchId)) {
|
|
3625
|
+
renderPreviewUi({
|
|
3626
|
+
status: state.status,
|
|
3627
|
+
statusTone: state.statusToneStatus === state.status ? state.statusTone : 'default',
|
|
3628
|
+
statusDetails: state.statusToneStatus === state.status ? state.statusDetails : '',
|
|
3629
|
+
session: createUiSessionState(state),
|
|
3630
|
+
});
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
2681
3633
|
renderUi();
|
|
2682
3634
|
},
|
|
2683
3635
|
onProjectionBatchSettled(event) {
|
|
2684
3636
|
getLocalEditorEditingContext(state).handleProjectionBatchSettled(event.batchId);
|
|
3637
|
+
const suppressInspectorRefresh = state.suppressedProjectionInspectorRefreshBatchIds.has(event.batchId)
|
|
3638
|
+
|| (event.nodeIds ?? []).some(nodeId => state.suppressedProjectionInspectorRefreshNodeBatches.has(nodeId));
|
|
3639
|
+
releaseProjectionInspectorRefreshSuppression(state, event.batchId);
|
|
3640
|
+
if (suppressInspectorRefresh) {
|
|
3641
|
+
renderPreviewUi({
|
|
3642
|
+
status: state.status,
|
|
3643
|
+
statusTone: state.statusToneStatus === state.status ? state.statusTone : 'default',
|
|
3644
|
+
statusDetails: state.statusToneStatus === state.status ? state.statusDetails : '',
|
|
3645
|
+
session: createUiSessionState(state),
|
|
3646
|
+
});
|
|
3647
|
+
return;
|
|
3648
|
+
}
|
|
2685
3649
|
renderUi();
|
|
2686
3650
|
},
|
|
2687
3651
|
});
|
|
@@ -2710,27 +3674,41 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
|
|
|
2710
3674
|
state.statusTone = policyStatus ? 'warning' : 'default';
|
|
2711
3675
|
state.statusToneStatus = state.status;
|
|
2712
3676
|
state.statusDetails = '';
|
|
2713
|
-
|
|
3677
|
+
renderPreviewUi({
|
|
3678
|
+
status: state.status,
|
|
3679
|
+
statusTone: state.statusTone,
|
|
3680
|
+
statusDetails: state.statusDetails,
|
|
3681
|
+
transformTool: {
|
|
3682
|
+
activeTool: event.tool,
|
|
3683
|
+
activeSpace: event.space,
|
|
3684
|
+
activeConstraint: event.constraint,
|
|
3685
|
+
dragPhase: 'dragging',
|
|
3686
|
+
draggingNodeId: event.nodeId ?? event.activeId ?? null,
|
|
3687
|
+
},
|
|
3688
|
+
});
|
|
3689
|
+
requestEditorSceneFrame(state, 'gizmo-drag-start');
|
|
2714
3690
|
},
|
|
2715
3691
|
onDragUpdate(event) {
|
|
2716
3692
|
updateActiveTransformPreview(state, event);
|
|
2717
|
-
syncMarkerOverlayToSceneArtifacts(state, options, state.session?.
|
|
3693
|
+
syncMarkerOverlayToSceneArtifacts(state, options, state.session?.getSelection() ?? { selectedIds: [], activeId: null });
|
|
2718
3694
|
state.gizmo?.refreshSelection();
|
|
2719
|
-
|
|
3695
|
+
scheduleInspectorPresentationPreview(state, options, renderPreviewUi, 'gizmo-drag-update');
|
|
3696
|
+
requestEditorSceneFrame(state, 'gizmo-drag-update');
|
|
2720
3697
|
},
|
|
2721
3698
|
onDragEnd(event) {
|
|
2722
3699
|
sceneViewInteraction.endGizmoDrag();
|
|
2723
3700
|
clearActiveTransformPreview(state);
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
3701
|
+
void state.runBrowserAuthoringMutation('transform.gizmo.commit', JSON.stringify(event), authoringState => getLocalEditorEditingContext(authoringState).commitTransform(event)).then(changed => {
|
|
3702
|
+
if (!changed)
|
|
3703
|
+
requestEditorSceneFrame(state, 'gizmo-drag-end');
|
|
3704
|
+
renderUi();
|
|
3705
|
+
}).catch(error => reportBrowserAuthoringFailure(state, renderUi, error));
|
|
2728
3706
|
},
|
|
2729
3707
|
onDragCancel(event) {
|
|
2730
3708
|
sceneViewInteraction.endGizmoDrag();
|
|
2731
3709
|
clearActiveTransformPreview(state);
|
|
2732
|
-
if (event.duplicate
|
|
2733
|
-
render();
|
|
3710
|
+
if (event.duplicate) {
|
|
3711
|
+
void state.runBrowserAuthoringMutation('transform.duplicate.cancel', JSON.stringify(event), authoringState => cancelDuplicateDrag(authoringState, options)).then(() => render()).catch(error => reportBrowserAuthoringFailure(state, render, error));
|
|
2734
3712
|
return;
|
|
2735
3713
|
}
|
|
2736
3714
|
state.status = event.targetIds.length > 1
|
|
@@ -2741,8 +3719,9 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
|
|
|
2741
3719
|
onDragBlocked(event) {
|
|
2742
3720
|
sceneViewInteraction.endGizmoDrag();
|
|
2743
3721
|
clearActiveTransformPreview(state);
|
|
2744
|
-
if (event.duplicate)
|
|
2745
|
-
cancelDuplicateDrag(
|
|
3722
|
+
if (event.duplicate) {
|
|
3723
|
+
void state.runBrowserAuthoringMutation('transform.duplicate.cancel', JSON.stringify(event), authoringState => cancelDuplicateDrag(authoringState, options)).catch(error => reportBrowserAuthoringFailure(state, renderUi, error));
|
|
3724
|
+
}
|
|
2746
3725
|
requestEditorSceneFrame(state, 'gizmo-drag-blocked');
|
|
2747
3726
|
state.status = formatBlockedGizmoTransformStatus(event);
|
|
2748
3727
|
state.statusTone = 'warning';
|
|
@@ -2750,10 +3729,17 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
|
|
|
2750
3729
|
renderUi();
|
|
2751
3730
|
},
|
|
2752
3731
|
onDuplicateDragStart(input) {
|
|
2753
|
-
const result = getLocalEditorEditingContext(state).beginDuplicateDrag(input);
|
|
2754
|
-
if (!result)
|
|
3732
|
+
const result = state.tryRunBrowserAuthoringMutationImmediately('transform.duplicate.begin', JSON.stringify(input), session => getLocalEditorEditingContext(state).beginDuplicateDrag(input, session));
|
|
3733
|
+
if (!result.ok) {
|
|
3734
|
+
state.status = `Duplicate drag unavailable: ${result.reason}`;
|
|
3735
|
+
state.statusTone = 'warning';
|
|
3736
|
+
state.statusToneStatus = state.status;
|
|
2755
3737
|
renderUi();
|
|
2756
|
-
|
|
3738
|
+
return null;
|
|
3739
|
+
}
|
|
3740
|
+
if (!result.value)
|
|
3741
|
+
renderUi();
|
|
3742
|
+
return result.value;
|
|
2757
3743
|
},
|
|
2758
3744
|
});
|
|
2759
3745
|
state.gizmo = gizmo;
|
|
@@ -2865,8 +3851,10 @@ async function createEditorWorld(state, options, renderUi, renderPreviewUi, upda
|
|
|
2865
3851
|
return;
|
|
2866
3852
|
}
|
|
2867
3853
|
if (event.state.intent === 'placement') {
|
|
2868
|
-
|
|
2869
|
-
|
|
3854
|
+
void state.runBrowserAuthoringMutation('asset.place', JSON.stringify({ x: event.originalEvent.clientX, y: event.originalEvent.clientY }), authoringState => commitArmedPlacement(authoringState, options, event.originalEvent)).then(changed => {
|
|
3855
|
+
if (changed)
|
|
3856
|
+
render();
|
|
3857
|
+
}).catch(error => reportBrowserAuthoringFailure(state, render, error));
|
|
2870
3858
|
return;
|
|
2871
3859
|
}
|
|
2872
3860
|
if (event.state.intent === 'view-plane-move') {
|
|
@@ -3002,7 +3990,7 @@ function disposeEditorWorld(state) {
|
|
|
3002
3990
|
});
|
|
3003
3991
|
run(() => clearPrefabStageForEditorTeardown(state));
|
|
3004
3992
|
run(() => cancelScheduledSelectionInspectorRefresh(state));
|
|
3005
|
-
state
|
|
3993
|
+
clearActiveTransformPreview(state);
|
|
3006
3994
|
disposeField(() => state.sceneViewInteraction, () => { state.sceneViewInteraction = null; });
|
|
3007
3995
|
if (state.resizeHandler) {
|
|
3008
3996
|
run(() => {
|
|
@@ -3202,7 +4190,7 @@ function requestEditorPreviewFrame(state, options, renderPreviewUi, reason) {
|
|
|
3202
4190
|
function updateActiveTransformPreview(state, event) {
|
|
3203
4191
|
const activeId = event.activeId ?? event.nodeId ?? event.targetIds[0] ?? null;
|
|
3204
4192
|
if (!activeId) {
|
|
3205
|
-
state
|
|
4193
|
+
clearActiveTransformPreview(state);
|
|
3206
4194
|
return;
|
|
3207
4195
|
}
|
|
3208
4196
|
state.activeTransformPreview = {
|
|
@@ -3215,6 +4203,74 @@ function updateActiveTransformPreview(state, event) {
|
|
|
3215
4203
|
}
|
|
3216
4204
|
function clearActiveTransformPreview(state) {
|
|
3217
4205
|
state.activeTransformPreview = null;
|
|
4206
|
+
cancelInspectorPresentationPreview(state);
|
|
4207
|
+
}
|
|
4208
|
+
function cancelInspectorPresentationPreview(state) {
|
|
4209
|
+
state.inspectorPresentationGeneration += 1;
|
|
4210
|
+
state.inspectorPresentationPatches = null;
|
|
4211
|
+
if (state.inspectorPresentationFrame !== null) {
|
|
4212
|
+
globalThis.cancelAnimationFrame?.(state.inspectorPresentationFrame);
|
|
4213
|
+
state.inspectorPresentationFrame = null;
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
function scheduleInspectorPresentationPreview(state, options, renderPreviewUi, _reason) {
|
|
4217
|
+
const preview = state.activeTransformPreview;
|
|
4218
|
+
const transform = preview?.activeId ? preview.transforms[preview.activeId] : null;
|
|
4219
|
+
if (!preview?.activeId || !transform || !isEditorTransformTrsSnapshot(transform))
|
|
4220
|
+
return;
|
|
4221
|
+
const generation = state.inspectorPresentationGeneration;
|
|
4222
|
+
const targetId = preview.activeId;
|
|
4223
|
+
state.inspectorPresentationPatches = createTransformInspectorPresentationPatches(targetId, transform, generation);
|
|
4224
|
+
if (state.inspectorPresentationFrame !== null)
|
|
4225
|
+
return;
|
|
4226
|
+
const publish = () => {
|
|
4227
|
+
if (generation !== state.inspectorPresentationGeneration)
|
|
4228
|
+
return;
|
|
4229
|
+
state.inspectorPresentationFrame = null;
|
|
4230
|
+
const patches = state.inspectorPresentationPatches;
|
|
4231
|
+
state.inspectorPresentationPatches = null;
|
|
4232
|
+
if (!patches?.length || !state.world)
|
|
4233
|
+
return;
|
|
4234
|
+
renderPreviewUi({ inspectorPresentationPatches: patches });
|
|
4235
|
+
};
|
|
4236
|
+
if (typeof globalThis.requestAnimationFrame === 'function') {
|
|
4237
|
+
state.inspectorPresentationFrame = globalThis.requestAnimationFrame(publish);
|
|
4238
|
+
}
|
|
4239
|
+
else {
|
|
4240
|
+
publish();
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
function createTransformInspectorPresentationPatches(targetId, transform, generation) {
|
|
4244
|
+
const patches = [];
|
|
4245
|
+
for (const group of ['position', 'rotation', 'scale']) {
|
|
4246
|
+
for (const axis of ['x', 'y', 'z']) {
|
|
4247
|
+
const rawValue = transform[group][axis];
|
|
4248
|
+
patches.push({
|
|
4249
|
+
targetId,
|
|
4250
|
+
propertyPath: `transform.${group}.${axis}`,
|
|
4251
|
+
value: group === 'rotation' ? radiansToInspectorDegrees(rawValue) : rawValue,
|
|
4252
|
+
generation,
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
return patches;
|
|
4257
|
+
}
|
|
4258
|
+
function createHistoryTransformInspectorPresentationPatches(state, document, selection) {
|
|
4259
|
+
const activeId = selection?.activeId ?? null;
|
|
4260
|
+
if (!activeId || !selection?.selectedIds.includes(activeId))
|
|
4261
|
+
return [];
|
|
4262
|
+
const transform = state.projection?.readNodeTransform(activeId) ?? null;
|
|
4263
|
+
if (!transform)
|
|
4264
|
+
return [];
|
|
4265
|
+
const preview = {
|
|
4266
|
+
targetIds: [...selection.selectedIds],
|
|
4267
|
+
activeId,
|
|
4268
|
+
transforms: { [activeId]: cloneEditorTransformSnapshot(transform) },
|
|
4269
|
+
};
|
|
4270
|
+
const resolved = getLocalEditorEditingContext(state).resolveInspectorPreviewTransform(document, activeId, transform, preview);
|
|
4271
|
+
return resolved && isEditorTransformTrsSnapshot(resolved)
|
|
4272
|
+
? createTransformInspectorPresentationPatches(activeId, resolved, state.inspectorPresentationGeneration)
|
|
4273
|
+
: [];
|
|
3218
4274
|
}
|
|
3219
4275
|
function scheduleProjectionShadowPreviewRebuild(state, reason) {
|
|
3220
4276
|
if (state.projectionShadowPreviewRebuildFrame !== null) {
|
|
@@ -3283,8 +4339,9 @@ async function runExclusiveLocalEditorDocumentOperation(state, render, operation
|
|
|
3283
4339
|
render();
|
|
3284
4340
|
}
|
|
3285
4341
|
}
|
|
3286
|
-
async function runExclusiveResult(state, render, action, executorStates) {
|
|
3287
|
-
const
|
|
4342
|
+
async function runExclusiveResult(state, render, action, executorStates, options = {}) {
|
|
4343
|
+
const renderBoundary = options.renderBoundary !== false;
|
|
4344
|
+
const lease = acquireLocalEditorBusyOperationLease(state, render, executorStates, { renderBoundary });
|
|
3288
4345
|
let failed = false;
|
|
3289
4346
|
try {
|
|
3290
4347
|
return await action(lease.executor);
|
|
@@ -3296,22 +4353,25 @@ async function runExclusiveResult(state, render, action, executorStates) {
|
|
|
3296
4353
|
finally {
|
|
3297
4354
|
lease.release();
|
|
3298
4355
|
state.busy = false;
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
4356
|
+
if (renderBoundary || failed) {
|
|
4357
|
+
try {
|
|
4358
|
+
render();
|
|
4359
|
+
}
|
|
4360
|
+
catch (error) {
|
|
4361
|
+
if (!failed)
|
|
4362
|
+
throw error;
|
|
4363
|
+
}
|
|
3305
4364
|
}
|
|
3306
4365
|
}
|
|
3307
4366
|
}
|
|
3308
|
-
function acquireLocalEditorBusyOperationLease(state, render, executorStates) {
|
|
4367
|
+
function acquireLocalEditorBusyOperationLease(state, render, executorStates, options = {}) {
|
|
3309
4368
|
if (state.busy)
|
|
3310
4369
|
throw new Error('Local editor host is busy. Retry this operation.');
|
|
3311
4370
|
state.busy = true;
|
|
3312
4371
|
const lease = createLocalEditorBusyOperationLease(state, render, executorStates);
|
|
3313
4372
|
try {
|
|
3314
|
-
|
|
4373
|
+
if (options.renderBoundary !== false)
|
|
4374
|
+
render();
|
|
3315
4375
|
return lease;
|
|
3316
4376
|
}
|
|
3317
4377
|
catch (error) {
|
|
@@ -3544,7 +4604,7 @@ function consumeMarkerRelationPickSelectionCommand(state, options, command, rend
|
|
|
3544
4604
|
renderUi();
|
|
3545
4605
|
return true;
|
|
3546
4606
|
}
|
|
3547
|
-
const
|
|
4607
|
+
const relationInput = {
|
|
3548
4608
|
action: 'create',
|
|
3549
4609
|
type: pick.type ?? '',
|
|
3550
4610
|
fromKind: pick.from.kind,
|
|
@@ -3552,16 +4612,18 @@ function consumeMarkerRelationPickSelectionCommand(state, options, command, rend
|
|
|
3552
4612
|
toKind: endpoint.kind,
|
|
3553
4613
|
toId: endpoint.id,
|
|
3554
4614
|
directed: pick.directed,
|
|
3555
|
-
}
|
|
3556
|
-
|
|
3557
|
-
state.markerRelationPick
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
renderUi
|
|
4615
|
+
};
|
|
4616
|
+
void state.runBrowserAuthoringMutation('marker.relation.pick.create', JSON.stringify(relationInput), authoringState => patchMarkerRelation(authoringState, options, relationInput)).then(handled => {
|
|
4617
|
+
if (handled && state.markerRelationPick) {
|
|
4618
|
+
state.markerRelationPick = {
|
|
4619
|
+
...state.markerRelationPick,
|
|
4620
|
+
status: state.status,
|
|
4621
|
+
statusTone: state.statusTone,
|
|
4622
|
+
};
|
|
4623
|
+
}
|
|
4624
|
+
if (renderUi)
|
|
4625
|
+
renderUi();
|
|
4626
|
+
}).catch(error => reportBrowserAuthoringFailure(state, renderUi ?? (() => undefined), error));
|
|
3565
4627
|
return true;
|
|
3566
4628
|
}
|
|
3567
4629
|
function readMarkerRelationPickTargetId(command) {
|
|
@@ -3617,13 +4679,14 @@ function renameSceneGraphNode(state, options, intent) {
|
|
|
3617
4679
|
label: patch.label ?? `Rename ${intent.id}`,
|
|
3618
4680
|
patch: patch.patch,
|
|
3619
4681
|
targetId: intent.id,
|
|
3620
|
-
...withProjectionImpact(
|
|
4682
|
+
...withProjectionImpact(createMetadataProjectionImpact([intent.id])),
|
|
4683
|
+
...withPresentationImpact({ hierarchy: { labelIds: [intent.id] }, inspector: ['summary'] }),
|
|
3621
4684
|
});
|
|
3622
4685
|
if (!result.documentChanged) {
|
|
3623
4686
|
state.status = `Rename unchanged: ${intent.id}`;
|
|
3624
4687
|
return 'rejected';
|
|
3625
4688
|
}
|
|
3626
|
-
|
|
4689
|
+
applyRenameProjectionImpact(state, options, result.workingDocument, result.selection, [intent.id], 'scene-rename');
|
|
3627
4690
|
state.summary = summarizeDocument(options, result.workingDocument, session.getSource());
|
|
3628
4691
|
state.status = patch.label ?? `Renamed ${intent.id}`;
|
|
3629
4692
|
return 'changed';
|
|
@@ -4139,7 +5202,7 @@ function sanitizeSelection(state, options, document, selection) {
|
|
|
4139
5202
|
const hierarchy = graph
|
|
4140
5203
|
? createMarkerGraphHierarchyItems(documentHierarchy, graph, createMarkerGraphHierarchyVisibility(state))
|
|
4141
5204
|
: documentHierarchy;
|
|
4142
|
-
const selectedIds = selection.selectedIds.filter(id =>
|
|
5205
|
+
const selectedIds = selection.selectedIds.filter(id => isEditorCommandObjectSelectable(options, document, id, hierarchy));
|
|
4143
5206
|
const activeId = selection.activeId && selectedIds.includes(selection.activeId)
|
|
4144
5207
|
? selection.activeId
|
|
4145
5208
|
: selectedIds[selectedIds.length - 1] ?? null;
|
|
@@ -4792,7 +5855,9 @@ async function handleBrowserAssetAction(state, options, input) {
|
|
|
4792
5855
|
return enterPrefabStage(state, options, input);
|
|
4793
5856
|
}
|
|
4794
5857
|
if (input.actionId === 'asset.add-to-scene') {
|
|
4795
|
-
return input.assetId
|
|
5858
|
+
return input.assetId
|
|
5859
|
+
? state.runBrowserAuthoringMutation('object.createFromAsset', JSON.stringify({ assetId: input.assetId, source: 'asset-browser-action' }), authoringState => addAssetToDocument(authoringState, options, input.assetId).ok)
|
|
5860
|
+
: false;
|
|
4796
5861
|
}
|
|
4797
5862
|
if (input.actionId === 'asset.place') {
|
|
4798
5863
|
if (!input.assetId)
|
|
@@ -4805,7 +5870,7 @@ async function handleBrowserAssetAction(state, options, input) {
|
|
|
4805
5870
|
}
|
|
4806
5871
|
return armAssetPlacement(state, options, input.assetId);
|
|
4807
5872
|
}
|
|
4808
|
-
const patched = patchBrowserAssetAction(
|
|
5873
|
+
const patched = await state.runBrowserAuthoringMutation(input.actionId, JSON.stringify(input), authoringState => patchBrowserAssetAction(authoringState, options, input));
|
|
4809
5874
|
if (patched)
|
|
4810
5875
|
return true;
|
|
4811
5876
|
state.status = `Asset action unavailable: ${input.actionId}`;
|
|
@@ -4817,11 +5882,11 @@ async function handleInspectorAction(state, options, input) {
|
|
|
4817
5882
|
if (!input.actionId.startsWith('prefab.')) {
|
|
4818
5883
|
const activeId = input.targetId ?? state.session?.getState().selection.activeId ?? null;
|
|
4819
5884
|
const selectedIds = input.targetIds ?? (activeId ? [activeId] : []);
|
|
4820
|
-
return patchBrowserAssetAction(
|
|
5885
|
+
return state.runBrowserAuthoringMutation(input.actionId, JSON.stringify([input, activeId, selectedIds]), authoringState => patchBrowserAssetAction(authoringState, options, {
|
|
4821
5886
|
actionId: input.actionId,
|
|
4822
5887
|
fieldPath: input.path,
|
|
4823
5888
|
value: input.params,
|
|
4824
|
-
}, { activeId, selectedIds });
|
|
5889
|
+
}, { activeId, selectedIds }));
|
|
4825
5890
|
}
|
|
4826
5891
|
const assetId = readInspectorActionParamString(input, 'assetId');
|
|
4827
5892
|
const browserAssetId = readInspectorActionParamString(input, 'browserAssetId')
|
|
@@ -4872,7 +5937,7 @@ function readInspectorActionParamString(input, key) {
|
|
|
4872
5937
|
const value = input.params?.[key];
|
|
4873
5938
|
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
|
|
4874
5939
|
}
|
|
4875
|
-
async function enterPrefabStage(state, options, input) {
|
|
5940
|
+
async function enterPrefabStage(state, options, input, serializedAccess) {
|
|
4876
5941
|
if (state.mode !== 'editor')
|
|
4877
5942
|
return false;
|
|
4878
5943
|
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
@@ -4897,13 +5962,14 @@ async function enterPrefabStage(state, options, input) {
|
|
|
4897
5962
|
return true;
|
|
4898
5963
|
}
|
|
4899
5964
|
if (previousPrefabStage) {
|
|
4900
|
-
const exited = await exitPrefabStage(state, options, 'reject');
|
|
5965
|
+
const exited = await exitPrefabStage(state, options, 'reject', serializedAccess);
|
|
4901
5966
|
if (!exited)
|
|
4902
5967
|
return true;
|
|
4903
5968
|
}
|
|
4904
5969
|
const parentSession = state.session;
|
|
4905
5970
|
if (!parentSession)
|
|
4906
5971
|
throw new Error('Prefab Stage requires an active parent Session.');
|
|
5972
|
+
const expectedParentRevision = parentSession.getState({ cloneDocuments: false }).documentRevision;
|
|
4907
5973
|
const prefabScopeRevision = ++state.nextPrefabScopeRevision;
|
|
4908
5974
|
const documentScopeId = state.scopeOperations
|
|
4909
5975
|
? `editor:document:prefab:${prefabScopeRevision}`
|
|
@@ -4958,12 +6024,32 @@ async function enterPrefabStage(state, options, input) {
|
|
|
4958
6024
|
selectedItemIds: ['prefab-root'],
|
|
4959
6025
|
restoreSceneCameraPreviewEnabled: previousPrefabStage?.restoreSceneCameraPreviewEnabled ?? state.sceneCameraPreviewEnabled,
|
|
4960
6026
|
};
|
|
4961
|
-
const previousSceneContext =
|
|
6027
|
+
const previousSceneContext = state.toolManager?.snapshot().context
|
|
6028
|
+
?? getLocalEditorEditingContextById(state, 'fps.editor.context.scene').getSnapshot();
|
|
6029
|
+
let projectionAuthoritySwitched = false;
|
|
4962
6030
|
try {
|
|
4963
6031
|
await rebindLocalEditorToolContext(state, createLocalEditorPrefabEditingContextSnapshot(state, nextPrefabStage));
|
|
6032
|
+
if (state.authoringHost) {
|
|
6033
|
+
await state.authoringHost.switchSession(transaction.draftSession, {
|
|
6034
|
+
expectedDocumentRevision: expectedParentRevision,
|
|
6035
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
6036
|
+
});
|
|
6037
|
+
}
|
|
6038
|
+
else {
|
|
6039
|
+
state.replaceProjectionSessionAuthority(transaction.draftSession);
|
|
6040
|
+
projectionAuthoritySwitched = true;
|
|
6041
|
+
}
|
|
4964
6042
|
}
|
|
4965
6043
|
catch (error) {
|
|
4966
6044
|
const rollbackErrors = [error];
|
|
6045
|
+
if (projectionAuthoritySwitched) {
|
|
6046
|
+
try {
|
|
6047
|
+
state.replaceProjectionSessionAuthority(parentSession);
|
|
6048
|
+
}
|
|
6049
|
+
catch (authorityRollbackError) {
|
|
6050
|
+
rollbackErrors.push(authorityRollbackError);
|
|
6051
|
+
}
|
|
6052
|
+
}
|
|
4967
6053
|
try {
|
|
4968
6054
|
await rebindLocalEditorToolContext(state, previousSceneContext);
|
|
4969
6055
|
}
|
|
@@ -4997,7 +6083,7 @@ async function enterPrefabStage(state, options, input) {
|
|
|
4997
6083
|
syncTransformOperationSettingsToSceneArtifacts(state, 'prefab-stage-enter-operation-settings');
|
|
4998
6084
|
return true;
|
|
4999
6085
|
}
|
|
5000
|
-
async function exitPrefabStage(state, options, dirtyAction = 'reject') {
|
|
6086
|
+
async function exitPrefabStage(state, options, dirtyAction = 'reject', serializedAccess) {
|
|
5001
6087
|
if (!state.prefabStage)
|
|
5002
6088
|
return false;
|
|
5003
6089
|
const transactionSnapshot = state.prefabStage.transaction.snapshot();
|
|
@@ -5009,13 +6095,25 @@ async function exitPrefabStage(state, options, dirtyAction = 'reject') {
|
|
|
5009
6095
|
state.statusDetails = 'Save or discard the Prefab changes before returning to the Scene.';
|
|
5010
6096
|
return false;
|
|
5011
6097
|
}
|
|
5012
|
-
state.prefabStage.transaction.
|
|
6098
|
+
state.prefabStage.transaction.assertParentUnchanged();
|
|
6099
|
+
const checkpoint = state.prefabStage.transaction.draftSession.getState({ cloneDocuments: false });
|
|
6100
|
+
if (state.authoringHost) {
|
|
6101
|
+
await state.authoringHost.reset(checkpoint.persistedDocument, checkpoint.source, {
|
|
6102
|
+
expectedDocumentRevision: checkpoint.documentRevision,
|
|
6103
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
6104
|
+
});
|
|
6105
|
+
}
|
|
6106
|
+
else {
|
|
6107
|
+
await state.runBrowserAuthoringMutation('prefab.stage.discard', JSON.stringify({ documentRevision: checkpoint.documentRevision }), authoringState => authoringState.session?.reset(checkpoint.persistedDocument, checkpoint.source));
|
|
6108
|
+
}
|
|
5013
6109
|
}
|
|
5014
6110
|
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
5015
6111
|
const label = sessionState?.workingDocument
|
|
5016
6112
|
? resolvePrefabStageDescriptorForDocument(state, options, sessionState.workingDocument)?.label ?? state.prefabStage.descriptor.label
|
|
5017
6113
|
: state.prefabStage.descriptor.label;
|
|
5018
6114
|
const prefabStage = state.prefabStage;
|
|
6115
|
+
const expectedDraftRevision = prefabStage.transaction.draftSession
|
|
6116
|
+
.getState({ cloneDocuments: false }).documentRevision;
|
|
5019
6117
|
const restoreSceneCameraPreviewEnabled = prefabStage.restoreSceneCameraPreviewEnabled;
|
|
5020
6118
|
const currentSceneContext = getLocalEditorEditingContextById(state, 'fps.editor.context.scene').getSnapshot();
|
|
5021
6119
|
const parentDocumentRevision = prefabStage.transaction.parentSession
|
|
@@ -5024,17 +6122,48 @@ async function exitPrefabStage(state, options, dirtyAction = 'reject') {
|
|
|
5024
6122
|
...currentSceneContext,
|
|
5025
6123
|
revision: parentDocumentRevision + state.editorStateRevision + 1,
|
|
5026
6124
|
};
|
|
6125
|
+
const prefabContext = state.toolManager?.snapshot().context
|
|
6126
|
+
?? createLocalEditorPrefabEditingContextSnapshot(state, prefabStage);
|
|
6127
|
+
let projectionAuthoritySwitched = false;
|
|
5027
6128
|
await closePrefabStageLifecycleScopes(state, prefabStage);
|
|
5028
6129
|
try {
|
|
5029
6130
|
await rebindLocalEditorToolContext(state, sceneContext);
|
|
6131
|
+
if (state.authoringHost) {
|
|
6132
|
+
await state.authoringHost.switchSession(prefabStage.transaction.parentSession, {
|
|
6133
|
+
expectedDocumentRevision: expectedDraftRevision,
|
|
6134
|
+
...(serializedAccess ? { serializedAccess } : {}),
|
|
6135
|
+
});
|
|
6136
|
+
}
|
|
6137
|
+
else {
|
|
6138
|
+
state.replaceProjectionSessionAuthority(prefabStage.transaction.parentSession);
|
|
6139
|
+
projectionAuthoritySwitched = true;
|
|
6140
|
+
}
|
|
5030
6141
|
}
|
|
5031
6142
|
catch (error) {
|
|
6143
|
+
const rollbackErrors = [error];
|
|
6144
|
+
if (projectionAuthoritySwitched) {
|
|
6145
|
+
try {
|
|
6146
|
+
state.replaceProjectionSessionAuthority(prefabStage.transaction.draftSession);
|
|
6147
|
+
}
|
|
6148
|
+
catch (authorityRollbackError) {
|
|
6149
|
+
rollbackErrors.push(authorityRollbackError);
|
|
6150
|
+
}
|
|
6151
|
+
}
|
|
5032
6152
|
try {
|
|
5033
6153
|
await openPrefabStageLifecycleScopes(state, prefabStage);
|
|
5034
6154
|
}
|
|
5035
6155
|
catch (rollbackError) {
|
|
6156
|
+
rollbackErrors.push(rollbackError);
|
|
6157
|
+
}
|
|
6158
|
+
try {
|
|
6159
|
+
await rebindLocalEditorToolContext(state, prefabContext);
|
|
6160
|
+
}
|
|
6161
|
+
catch (rollbackError) {
|
|
6162
|
+
rollbackErrors.push(rollbackError);
|
|
6163
|
+
}
|
|
6164
|
+
if (rollbackErrors.length > 1) {
|
|
5036
6165
|
const combined = new Error('Prefab Tool context exit and lifecycle scope rollback failed.');
|
|
5037
|
-
combined.errors =
|
|
6166
|
+
combined.errors = rollbackErrors;
|
|
5038
6167
|
throw combined;
|
|
5039
6168
|
}
|
|
5040
6169
|
throw error;
|
|
@@ -5042,6 +6171,13 @@ async function exitPrefabStage(state, options, dirtyAction = 'reject') {
|
|
|
5042
6171
|
state.session = prefabStage.transaction.parentSession;
|
|
5043
6172
|
state.prefabStage = null;
|
|
5044
6173
|
state.editorStateRevision += 1;
|
|
6174
|
+
let reconciliationError;
|
|
6175
|
+
try {
|
|
6176
|
+
await state.reconcilePendingProjectServiceSnapshot();
|
|
6177
|
+
}
|
|
6178
|
+
catch (error) {
|
|
6179
|
+
reconciliationError = error;
|
|
6180
|
+
}
|
|
5045
6181
|
activateLocalEditorSceneViewContext(state, getLocalEditorEditingContext(state).getViewStateKey(), false);
|
|
5046
6182
|
const parentSessionState = state.session.getState({ cloneDocuments: false });
|
|
5047
6183
|
if (parentSessionState.workingDocument) {
|
|
@@ -5053,10 +6189,12 @@ async function exitPrefabStage(state, options, dirtyAction = 'reject') {
|
|
|
5053
6189
|
syncSceneCameraPreview(state, options);
|
|
5054
6190
|
else
|
|
5055
6191
|
state.sceneCameraPreview?.setActive(false);
|
|
5056
|
-
state.status = `Exited Prefab ${label}`;
|
|
5057
|
-
state.statusTone = 'default';
|
|
6192
|
+
state.status = reconciliationError ? 'Project Editor Service reconciliation failed' : `Exited Prefab ${label}`;
|
|
6193
|
+
state.statusTone = reconciliationError ? 'error' : 'default';
|
|
5058
6194
|
state.statusToneStatus = state.status;
|
|
5059
|
-
state.statusDetails =
|
|
6195
|
+
state.statusDetails = reconciliationError
|
|
6196
|
+
? stringifyLocalEditorError(reconciliationError) ?? 'Unknown project snapshot reconciliation error'
|
|
6197
|
+
: '';
|
|
5060
6198
|
return true;
|
|
5061
6199
|
}
|
|
5062
6200
|
async function rebindLocalEditorToolContext(state, nextContext = getLocalEditorEditingContext(state).getSnapshot()) {
|
|
@@ -5097,7 +6235,7 @@ async function openPrefabStageLifecycleScopes(state, stage) {
|
|
|
5097
6235
|
parentId: stage.sessionScopeId,
|
|
5098
6236
|
});
|
|
5099
6237
|
state.scopeOperations.addScopeResource(stage.previewScopeId, () => {
|
|
5100
|
-
state
|
|
6238
|
+
clearActiveTransformPreview(state);
|
|
5101
6239
|
});
|
|
5102
6240
|
}
|
|
5103
6241
|
function selectPrefabStageItem(state, itemId) {
|
|
@@ -5550,13 +6688,13 @@ function clearArmedPlacement(state) {
|
|
|
5550
6688
|
state.armedPlacement = null;
|
|
5551
6689
|
state.gizmo?.setPlacementMarker(null);
|
|
5552
6690
|
}
|
|
5553
|
-
function addAssetToDocument(state, options, assetId, createOptions = {}) {
|
|
6691
|
+
function addAssetToDocument(state, options, assetId, createOptions = {}, sessionOverride) {
|
|
5554
6692
|
if (state.mode !== 'editor') {
|
|
5555
6693
|
state.status = 'Asset creation rejected: editor is not active';
|
|
5556
6694
|
return { ok: false, assetId, changed: false, status: state.status, error: 'editor_not_active' };
|
|
5557
6695
|
}
|
|
5558
6696
|
cancelActiveOperation(state);
|
|
5559
|
-
const session = state.session;
|
|
6697
|
+
const session = sessionOverride ?? state.session;
|
|
5560
6698
|
const beforeDocument = session?.getState().workingDocument;
|
|
5561
6699
|
if (!session || !beforeDocument) {
|
|
5562
6700
|
state.status = 'Asset creation rejected: document is not loaded';
|
|
@@ -5618,13 +6756,13 @@ function addAssetToDocument(state, options, assetId, createOptions = {}) {
|
|
|
5618
6756
|
createdId: createdId ?? null,
|
|
5619
6757
|
};
|
|
5620
6758
|
}
|
|
5621
|
-
function patchSerializedProperty(state, options, input) {
|
|
6759
|
+
function patchSerializedProperty(state, options, input, onCommitted) {
|
|
5622
6760
|
if (state.mode !== 'editor')
|
|
5623
6761
|
return false;
|
|
5624
6762
|
cancelActiveOperation(state);
|
|
5625
|
-
return getLocalEditorEditingContext(state).patchInspectorProperty(input);
|
|
6763
|
+
return getLocalEditorEditingContext(state).patchInspectorProperty(input, onCommitted);
|
|
5626
6764
|
}
|
|
5627
|
-
function patchSceneSerializedProperty(state, options, input) {
|
|
6765
|
+
function patchSceneSerializedProperty(state, options, input, onCommitted) {
|
|
5628
6766
|
if (!state.session)
|
|
5629
6767
|
return false;
|
|
5630
6768
|
const sessionState = state.session.getState({ cloneDocuments: false });
|
|
@@ -5656,6 +6794,7 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5656
6794
|
if (!patch)
|
|
5657
6795
|
return false;
|
|
5658
6796
|
const changedIds = patch.changedIds ?? targetIds;
|
|
6797
|
+
const serializedNamePatch = isSerializedNamePath(payload.path);
|
|
5659
6798
|
const projectionMetadataPatch = isSerializedProjectionMetadataPath(payload.path);
|
|
5660
6799
|
const projectionMetadataSyncIds = projectionMetadataPatch
|
|
5661
6800
|
? resolveSerializedProjectionMetadataSyncIds(options, document, payload.path, changedIds)
|
|
@@ -5667,15 +6806,18 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5667
6806
|
label: patch.label ?? `Patch ${payload.path} on ${targetIds.length} objects`,
|
|
5668
6807
|
patch: patch.patch,
|
|
5669
6808
|
targetId: sessionState.selection.activeId ?? undefined,
|
|
5670
|
-
...withProjectionImpact(
|
|
5671
|
-
?
|
|
5672
|
-
:
|
|
5673
|
-
? createReprojectProjectionImpact(
|
|
5674
|
-
:
|
|
5675
|
-
?
|
|
5676
|
-
:
|
|
5677
|
-
?
|
|
5678
|
-
:
|
|
6809
|
+
...withProjectionImpact(serializedNamePatch
|
|
6810
|
+
? createMetadataProjectionImpact(changedIds)
|
|
6811
|
+
: resolveProjectionImpact(patch, patch.reprojectIds?.length
|
|
6812
|
+
? createReprojectProjectionImpact(patch.reprojectIds)
|
|
6813
|
+
: shouldReprojectInspectorEdit
|
|
6814
|
+
? createReprojectProjectionImpact(changedIds)
|
|
6815
|
+
: isSerializedTransformPath(payload.path)
|
|
6816
|
+
? createTransformProjectionImpact(targetIds)
|
|
6817
|
+
: projectionMetadataPatch
|
|
6818
|
+
? createMetadataProjectionImpact(projectionMetadataSyncIds)
|
|
6819
|
+
: undefined)),
|
|
6820
|
+
...withPresentationImpact(resolveSerializedPresentationImpact(payload.path, changedIds)),
|
|
5679
6821
|
}, largeProjectionMetadataPatch
|
|
5680
6822
|
? {
|
|
5681
6823
|
assumeDocumentChanged: true,
|
|
@@ -5687,15 +6829,27 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5687
6829
|
if (!result.documentChanged)
|
|
5688
6830
|
return false;
|
|
5689
6831
|
const workingDocument = result.workingDocument;
|
|
6832
|
+
state.status = patch.label ?? `Patch ${payload.path} on ${targetIds.length} objects`;
|
|
6833
|
+
if (isSerializedTransformPath(payload.path))
|
|
6834
|
+
onCommitted?.();
|
|
5690
6835
|
const projectionSyncIds = projectionMetadataPatch
|
|
5691
6836
|
? resolveSerializedProjectionMetadataSyncIds(options, workingDocument, payload.path, changedIds)
|
|
5692
6837
|
: isSerializedTransformPath(payload.path)
|
|
5693
6838
|
? targetIds
|
|
5694
6839
|
: changedIds;
|
|
5695
|
-
if (
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
6840
|
+
if (serializedNamePatch) {
|
|
6841
|
+
applyRenameProjectionImpact(state, options, workingDocument, result.selection, changedIds, 'inspector-name');
|
|
6842
|
+
}
|
|
6843
|
+
else if (patch.reprojectIds?.length) {
|
|
6844
|
+
reprojectProjectionForChangedIds(state, options, workingDocument, patch.reprojectIds, {
|
|
6845
|
+
refreshInspector: input.refreshInspector !== false,
|
|
6846
|
+
});
|
|
6847
|
+
}
|
|
6848
|
+
else if (shouldReprojectInspectorEdit) {
|
|
6849
|
+
reprojectProjectionForChangedIds(state, options, workingDocument, changedIds, {
|
|
6850
|
+
refreshInspector: input.refreshInspector !== false,
|
|
6851
|
+
});
|
|
6852
|
+
}
|
|
5699
6853
|
else if (projectionMetadataPatch) {
|
|
5700
6854
|
syncProjectionMetadataForChangedIds(state, options, workingDocument, projectionSyncIds, {
|
|
5701
6855
|
deferShadowPreviewRefresh: largeProjectionMetadataPatch,
|
|
@@ -5708,7 +6862,6 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5708
6862
|
state.gizmo?.refreshSelection();
|
|
5709
6863
|
}
|
|
5710
6864
|
state.summary = summarizeDocument(options, workingDocument, state.session.getSource());
|
|
5711
|
-
state.status = patch.label ?? `Patch ${payload.path} on ${targetIds.length} objects`;
|
|
5712
6865
|
return true;
|
|
5713
6866
|
}
|
|
5714
6867
|
const patch = options.documentAdapter.createSerializedPropertyPatch({
|
|
@@ -5726,6 +6879,7 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5726
6879
|
if (!patch)
|
|
5727
6880
|
return false;
|
|
5728
6881
|
const changedIds = patch.changedIds ?? [patch.changedId ?? payload.targetId];
|
|
6882
|
+
const serializedNamePatch = isSerializedNamePath(payload.path);
|
|
5729
6883
|
const projectionMetadataPatch = isSerializedProjectionMetadataPath(payload.path);
|
|
5730
6884
|
const projectionMetadataSyncIds = projectionMetadataPatch
|
|
5731
6885
|
? resolveSerializedProjectionMetadataSyncIds(options, document, payload.path, changedIds)
|
|
@@ -5734,20 +6888,34 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5734
6888
|
type: 'document.patch',
|
|
5735
6889
|
label: patch.label ?? `Patch ${payload.path}`,
|
|
5736
6890
|
patch: patch.patch,
|
|
5737
|
-
...withProjectionImpact(
|
|
5738
|
-
?
|
|
5739
|
-
:
|
|
5740
|
-
? createReprojectProjectionImpact(
|
|
5741
|
-
:
|
|
5742
|
-
?
|
|
5743
|
-
:
|
|
5744
|
-
?
|
|
5745
|
-
:
|
|
6891
|
+
...withProjectionImpact(serializedNamePatch
|
|
6892
|
+
? createMetadataProjectionImpact(changedIds)
|
|
6893
|
+
: resolveProjectionImpact(patch, patch.reprojectIds?.length
|
|
6894
|
+
? createReprojectProjectionImpact(patch.reprojectIds)
|
|
6895
|
+
: shouldReprojectInspectorEdit
|
|
6896
|
+
? createReprojectProjectionImpact(changedIds)
|
|
6897
|
+
: isSerializedTransformPath(payload.path)
|
|
6898
|
+
? createTransformProjectionImpact([patch.changedId ?? payload.targetId])
|
|
6899
|
+
: projectionMetadataPatch
|
|
6900
|
+
? createMetadataProjectionImpact(projectionMetadataSyncIds)
|
|
6901
|
+
: undefined)),
|
|
6902
|
+
...withPresentationImpact(resolveSerializedPresentationImpact(payload.path, changedIds)),
|
|
5746
6903
|
});
|
|
5747
|
-
|
|
5748
|
-
|
|
6904
|
+
state.status = patch.label ?? `Patched ${payload.path}`;
|
|
6905
|
+
if (result.documentChanged && isSerializedTransformPath(payload.path))
|
|
6906
|
+
onCommitted?.();
|
|
6907
|
+
if (result.documentChanged && serializedNamePatch) {
|
|
6908
|
+
applyRenameProjectionImpact(state, options, result.workingDocument, result.selection, changedIds, 'inspector-name');
|
|
6909
|
+
}
|
|
6910
|
+
else if (patch.reprojectIds?.length) {
|
|
6911
|
+
reprojectProjectionForChangedIds(state, options, result.workingDocument, patch.reprojectIds, {
|
|
6912
|
+
refreshInspector: input.refreshInspector !== false,
|
|
6913
|
+
});
|
|
6914
|
+
}
|
|
5749
6915
|
else if (shouldReprojectInspectorEdit) {
|
|
5750
|
-
reprojectProjectionForChangedIds(state, options, result.workingDocument, changedIds
|
|
6916
|
+
reprojectProjectionForChangedIds(state, options, result.workingDocument, changedIds, {
|
|
6917
|
+
refreshInspector: input.refreshInspector !== false,
|
|
6918
|
+
});
|
|
5751
6919
|
}
|
|
5752
6920
|
else if (projectionMetadataPatch) {
|
|
5753
6921
|
const syncIds = resolveSerializedProjectionMetadataSyncIds(options, result.workingDocument, payload.path, changedIds);
|
|
@@ -5764,7 +6932,6 @@ function patchSceneSerializedProperty(state, options, input) {
|
|
|
5764
6932
|
state.gizmo?.refreshSelection();
|
|
5765
6933
|
}
|
|
5766
6934
|
state.summary = summarizeDocument(options, result.workingDocument, state.session.getSource());
|
|
5767
|
-
state.status = patch.label ?? `Patched ${payload.path}`;
|
|
5768
6935
|
return true;
|
|
5769
6936
|
}
|
|
5770
6937
|
function patchPrefabSerializedProperty(state, options, input) {
|
|
@@ -6469,6 +7636,7 @@ function applyRenderingDocumentPatch(state, options, document, patch, fallbackLa
|
|
|
6469
7636
|
patch: patch.patch,
|
|
6470
7637
|
targetId: patch.changedId,
|
|
6471
7638
|
...withProjectionImpact(projectionImpact),
|
|
7639
|
+
...withPresentationImpact({ rendering: true }),
|
|
6472
7640
|
});
|
|
6473
7641
|
if (!result.documentChanged) {
|
|
6474
7642
|
return { changed: false, workingDocument: result.workingDocument, label };
|
|
@@ -6574,6 +7742,9 @@ function isSerializedTransformPath(path) {
|
|
|
6574
7742
|
|| path.startsWith('transform.rotation.')
|
|
6575
7743
|
|| path.startsWith('transform.scale.');
|
|
6576
7744
|
}
|
|
7745
|
+
function isSerializedNamePath(path) {
|
|
7746
|
+
return path === 'name';
|
|
7747
|
+
}
|
|
6577
7748
|
function isSerializedProjectionMetadataPath(path) {
|
|
6578
7749
|
return isSerializedShadowMetadataPath(path);
|
|
6579
7750
|
}
|
|
@@ -6586,12 +7757,30 @@ function resolveSerializedProjectionMetadataSyncIds(options, document, path, cha
|
|
|
6586
7757
|
}
|
|
6587
7758
|
return uniqueProjectionIds(changedIds);
|
|
6588
7759
|
}
|
|
6589
|
-
function
|
|
6590
|
-
|
|
7760
|
+
function isSerializedMaterialPath(path) {
|
|
7761
|
+
return path.startsWith('overrides.material')
|
|
7762
|
+
|| path.startsWith('material.')
|
|
7763
|
+
|| path.startsWith('scene.materialAssets.');
|
|
7764
|
+
}
|
|
7765
|
+
function resolveSerializedPresentationImpact(path, targetIds = []) {
|
|
7766
|
+
if (isSerializedNamePath(path)) {
|
|
7767
|
+
const labelIds = uniqueProjectionIds(targetIds);
|
|
7768
|
+
return labelIds.length > 0
|
|
7769
|
+
? { hierarchy: { labelIds }, inspector: ['summary'] }
|
|
7770
|
+
: undefined;
|
|
7771
|
+
}
|
|
7772
|
+
if (isSerializedTransformPath(path))
|
|
7773
|
+
return { inspector: ['transform'] };
|
|
7774
|
+
if (isSerializedMaterialPath(path))
|
|
7775
|
+
return { inspector: ['material'] };
|
|
7776
|
+
return undefined;
|
|
7777
|
+
}
|
|
7778
|
+
function beginDuplicateDrag(state, options, input, sessionOverride) {
|
|
7779
|
+
if (state.mode !== 'editor' || !(sessionOverride ?? state.session))
|
|
6591
7780
|
return null;
|
|
6592
7781
|
if (state.duplicateDrag)
|
|
6593
7782
|
return null;
|
|
6594
|
-
const session = state.session;
|
|
7783
|
+
const session = sessionOverride ?? state.session;
|
|
6595
7784
|
const document = session.getState().workingDocument;
|
|
6596
7785
|
const patch = options.documentAdapter.createDuplicateSelectionPatch?.({
|
|
6597
7786
|
document,
|
|
@@ -6619,7 +7808,7 @@ function beginDuplicateDrag(state, options, input) {
|
|
|
6619
7808
|
const selectedIds = (patch.selectedIds?.length ? patch.selectedIds : patch.createdIds)
|
|
6620
7809
|
.filter(id => isNodeSelectableInDocument(options, result.workingDocument, id));
|
|
6621
7810
|
if (selectedIds.length === 0) {
|
|
6622
|
-
const undone =
|
|
7811
|
+
const undone = session.undo();
|
|
6623
7812
|
if (undone)
|
|
6624
7813
|
rebuildProjectionFromDocument(state, options, undone.workingDocument, originalSelection);
|
|
6625
7814
|
state.status = 'Duplicate drag rejected: duplicated selection is not selectable';
|
|
@@ -6628,7 +7817,7 @@ function beginDuplicateDrag(state, options, input) {
|
|
|
6628
7817
|
const activeId = patch.activeId && selectedIds.includes(patch.activeId)
|
|
6629
7818
|
? patch.activeId
|
|
6630
7819
|
: selectedIds[selectedIds.length - 1] ?? null;
|
|
6631
|
-
const selectionResult =
|
|
7820
|
+
const selectionResult = session.dispatch({
|
|
6632
7821
|
type: 'selection.replace',
|
|
6633
7822
|
selectedIds,
|
|
6634
7823
|
activeId,
|
|
@@ -7222,6 +8411,9 @@ function formatAssetLabel(asset, fallback) {
|
|
|
7222
8411
|
const label = record?.label ?? record?.displayName ?? record?.name;
|
|
7223
8412
|
return typeof label === 'string' && label.trim() ? label : fallback;
|
|
7224
8413
|
}
|
|
8414
|
+
function withPresentationImpact(impact) {
|
|
8415
|
+
return impact ? { presentationImpact: impact } : {};
|
|
8416
|
+
}
|
|
7225
8417
|
function withProjectionImpact(impact) {
|
|
7226
8418
|
return impact ? { projectionImpact: impact } : {};
|
|
7227
8419
|
}
|
|
@@ -7234,6 +8426,18 @@ function createTransformProjectionImpact(ids) {
|
|
|
7234
8426
|
function createMetadataProjectionImpact(ids) {
|
|
7235
8427
|
return createIncrementalProjectionImpact({ syncMetadataIds: ids });
|
|
7236
8428
|
}
|
|
8429
|
+
function applyRenameProjectionImpact(state, options, document, selection, ids, reason) {
|
|
8430
|
+
const impact = createMetadataProjectionImpact(ids);
|
|
8431
|
+
const applied = applyProjectionImpactToDocument(state, options, {
|
|
8432
|
+
document,
|
|
8433
|
+
selection,
|
|
8434
|
+
impact,
|
|
8435
|
+
reason,
|
|
8436
|
+
syncWorld: false,
|
|
8437
|
+
});
|
|
8438
|
+
if (!applied)
|
|
8439
|
+
rebuildProjectionFromDocument(state, options, document, selection);
|
|
8440
|
+
}
|
|
7237
8441
|
function createReprojectProjectionImpact(ids) {
|
|
7238
8442
|
return createIncrementalProjectionImpact({ reprojectIds: ids });
|
|
7239
8443
|
}
|
|
@@ -7356,6 +8560,7 @@ function createHistoryOperationResult(state, input) {
|
|
|
7356
8560
|
},
|
|
7357
8561
|
status: input.status,
|
|
7358
8562
|
projection: createHistoryProjectionResult(input.waitForProjection, null, state),
|
|
8563
|
+
...(input.result?.transaction.presentationImpact ? { presentationImpact: input.result.transaction.presentationImpact } : {}),
|
|
7359
8564
|
};
|
|
7360
8565
|
}
|
|
7361
8566
|
function createHistoryProjectionResult(waitPolicy, idleState, state) {
|
|
@@ -7373,10 +8578,41 @@ function applyHistoryProjectionImpact(state, options, result, operation) {
|
|
|
7373
8578
|
rebuildProjection(state, options, result);
|
|
7374
8579
|
return;
|
|
7375
8580
|
}
|
|
7376
|
-
const applied = applyIncrementalHistoryProjectionImpact(state, options, result, operation, impact);
|
|
8581
|
+
const applied = applyIncrementalHistoryProjectionImpact(state, options, result, operation, impact, !isRenameTransactionImpact(result.transaction));
|
|
7377
8582
|
if (!applied)
|
|
7378
8583
|
rebuildProjection(state, options, result);
|
|
7379
8584
|
}
|
|
8585
|
+
function isRenameTransactionImpact(transaction) {
|
|
8586
|
+
return isRenameImpact(transaction);
|
|
8587
|
+
}
|
|
8588
|
+
function resolveLocalEditorDocumentStructureChange(classify, command) {
|
|
8589
|
+
if (isRenameImpact(command))
|
|
8590
|
+
return false;
|
|
8591
|
+
return classify?.(command) ?? true;
|
|
8592
|
+
}
|
|
8593
|
+
function isRenameImpact(input) {
|
|
8594
|
+
const presentation = input.presentationImpact;
|
|
8595
|
+
const projection = input.projectionImpact;
|
|
8596
|
+
if (!presentation
|
|
8597
|
+
|| presentation.hierarchy === 'full'
|
|
8598
|
+
|| !presentation.hierarchy
|
|
8599
|
+
|| presentation.rendering === true
|
|
8600
|
+
|| !Array.isArray(presentation.inspector)
|
|
8601
|
+
|| presentation.inspector.length !== 1
|
|
8602
|
+
|| presentation.inspector[0] !== 'summary'
|
|
8603
|
+
|| !projection
|
|
8604
|
+
|| projection.type !== 'incremental')
|
|
8605
|
+
return false;
|
|
8606
|
+
const labelIds = uniqueProjectionIds(presentation.hierarchy.labelIds);
|
|
8607
|
+
const metadataIds = uniqueProjectionIds(projection.syncMetadataIds);
|
|
8608
|
+
return labelIds.length > 0
|
|
8609
|
+
&& labelIds.length === metadataIds.length
|
|
8610
|
+
&& labelIds.every(id => metadataIds.includes(id))
|
|
8611
|
+
&& uniqueProjectionIds(projection.syncTransformIds).length === 0
|
|
8612
|
+
&& uniqueProjectionIds(projection.reprojectIds).length === 0
|
|
8613
|
+
&& uniqueProjectionIds(projection.createdNodeIds).length === 0
|
|
8614
|
+
&& uniqueProjectionIds(projection.deletedNodeIds).length === 0;
|
|
8615
|
+
}
|
|
7380
8616
|
function applyProjectionImpactToDocument(state, options, input) {
|
|
7381
8617
|
if (!input.impact || input.impact.type === 'rebuild')
|
|
7382
8618
|
return false;
|
|
@@ -7389,12 +8625,13 @@ function applyProjectionImpactToDocument(state, options, input) {
|
|
|
7389
8625
|
projectNodeIds: input.impact.createdNodeIds,
|
|
7390
8626
|
removeNodeIds: input.impact.deletedNodeIds,
|
|
7391
8627
|
reason: input.reason,
|
|
8628
|
+
syncWorld: input.syncWorld,
|
|
7392
8629
|
});
|
|
7393
8630
|
}
|
|
7394
8631
|
function rebuildProjection(state, options, result) {
|
|
7395
8632
|
rebuildProjectionFromDocument(state, options, result.workingDocument, result.selection);
|
|
7396
8633
|
}
|
|
7397
|
-
function applyIncrementalHistoryProjectionImpact(state, options, result, operation, impact) {
|
|
8634
|
+
function applyIncrementalHistoryProjectionImpact(state, options, result, operation, impact, syncWorld) {
|
|
7398
8635
|
const projectNodeIds = operation === 'redo'
|
|
7399
8636
|
? uniqueProjectionIds(impact.createdNodeIds)
|
|
7400
8637
|
: uniqueProjectionIds(impact.deletedNodeIds);
|
|
@@ -7410,6 +8647,7 @@ function applyIncrementalHistoryProjectionImpact(state, options, result, operati
|
|
|
7410
8647
|
projectNodeIds,
|
|
7411
8648
|
removeNodeIds,
|
|
7412
8649
|
reason: 'history-impact',
|
|
8650
|
+
syncWorld,
|
|
7413
8651
|
});
|
|
7414
8652
|
}
|
|
7415
8653
|
function applyIncrementalProjectionImpactToDocument(state, options, input) {
|
|
@@ -7498,14 +8736,16 @@ function applyIncrementalProjectionImpactToDocument(state, options, input) {
|
|
|
7498
8736
|
applyPreviewVisibilityStateToProjection(state);
|
|
7499
8737
|
const sanitized = sanitizeSelection(state, options, input.document, input.selection);
|
|
7500
8738
|
syncSelectionToProjection(state, options, sanitized ?? input.selection);
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
8739
|
+
if (input.syncWorld !== false) {
|
|
8740
|
+
syncEditorWorldAppearanceFromDocument(state, options, input.document, `world-appearance-${input.reason}`);
|
|
8741
|
+
if (syncMetadataNodes.length > 0) {
|
|
8742
|
+
syncEditorWorldRenderingFromDocument(state, options, input.document, `world-rendering-${input.reason}`, {
|
|
8743
|
+
staticProjectedMetadataChanged: true,
|
|
8744
|
+
});
|
|
8745
|
+
}
|
|
8746
|
+
else {
|
|
8747
|
+
syncEditorWorldRenderingFromDocument(state, options, input.document, `world-rendering-${input.reason}`, true);
|
|
8748
|
+
}
|
|
7509
8749
|
}
|
|
7510
8750
|
invalidateEditorScene(state, `projection-${input.reason}`, options);
|
|
7511
8751
|
return true;
|
|
@@ -7697,7 +8937,7 @@ function syncProjectionMetadataForChangedIds(state, options, document, changedId
|
|
|
7697
8937
|
}
|
|
7698
8938
|
invalidateEditorScene(state, 'projection-sync-metadata-ids');
|
|
7699
8939
|
}
|
|
7700
|
-
function reprojectProjectionForChangedIds(state, options, document, changedIds) {
|
|
8940
|
+
function reprojectProjectionForChangedIds(state, options, document, changedIds, syncOptions = {}) {
|
|
7701
8941
|
if (state.prefabStage) {
|
|
7702
8942
|
rebuildProjectionFromDocument(state, options, document, EMPTY_EDITOR_SELECTION);
|
|
7703
8943
|
return;
|
|
@@ -7706,8 +8946,18 @@ function reprojectProjectionForChangedIds(state, options, document, changedIds)
|
|
|
7706
8946
|
const projectedNodes = resolveProjectionNodesForTarget(options, document, changedId);
|
|
7707
8947
|
if (projectedNodes) {
|
|
7708
8948
|
removeSceneProjectionTarget(state, changedId);
|
|
7709
|
-
for (const projectedNode of projectedNodes)
|
|
8949
|
+
for (const projectedNode of projectedNodes) {
|
|
7710
8950
|
state.projection?.projectNode(projectedNode);
|
|
8951
|
+
if (syncOptions.refreshInspector === false) {
|
|
8952
|
+
const batch = state.projection?.getLastProjectionBatch();
|
|
8953
|
+
if (batch) {
|
|
8954
|
+
suppressProjectionInspectorRefreshForBatch(state, batch.batchId, projectedNode.id);
|
|
8955
|
+
void batch.settled.then(() => {
|
|
8956
|
+
releaseProjectionInspectorRefreshSuppression(state, batch.batchId);
|
|
8957
|
+
});
|
|
8958
|
+
}
|
|
8959
|
+
}
|
|
8960
|
+
}
|
|
7711
8961
|
}
|
|
7712
8962
|
}
|
|
7713
8963
|
applyPreviewVisibilityStateToProjection(state);
|
|
@@ -7716,6 +8966,24 @@ function reprojectProjectionForChangedIds(state, options, document, changedIds)
|
|
|
7716
8966
|
syncEditorWorldRenderingFromDocument(state, options, document, 'world-rendering-reproject-changed-ids', true);
|
|
7717
8967
|
invalidateEditorScene(state, 'projection-reproject-changed-ids', options);
|
|
7718
8968
|
}
|
|
8969
|
+
function suppressProjectionInspectorRefreshForBatch(state, batchId, nodeId) {
|
|
8970
|
+
state.suppressedProjectionInspectorRefreshBatchIds.add(batchId);
|
|
8971
|
+
const batches = state.suppressedProjectionInspectorRefreshNodeBatches.get(nodeId) ?? new Set();
|
|
8972
|
+
batches.add(batchId);
|
|
8973
|
+
state.suppressedProjectionInspectorRefreshNodeBatches.set(nodeId, batches);
|
|
8974
|
+
}
|
|
8975
|
+
function isProjectionInspectorRefreshSuppressed(state, nodeId, batchId) {
|
|
8976
|
+
return (batchId !== undefined && state.suppressedProjectionInspectorRefreshBatchIds.has(batchId))
|
|
8977
|
+
|| state.suppressedProjectionInspectorRefreshNodeBatches.has(nodeId);
|
|
8978
|
+
}
|
|
8979
|
+
function releaseProjectionInspectorRefreshSuppression(state, batchId) {
|
|
8980
|
+
state.suppressedProjectionInspectorRefreshBatchIds.delete(batchId);
|
|
8981
|
+
for (const [nodeId, batches] of state.suppressedProjectionInspectorRefreshNodeBatches) {
|
|
8982
|
+
batches.delete(batchId);
|
|
8983
|
+
if (batches.size === 0)
|
|
8984
|
+
state.suppressedProjectionInspectorRefreshNodeBatches.delete(nodeId);
|
|
8985
|
+
}
|
|
8986
|
+
}
|
|
7719
8987
|
function removeLocalEditorMaterialProfileDiagnostics(state, projectionNodeId) {
|
|
7720
8988
|
state.materialProfileDiagnostics = state.materialProfileDiagnostics.filter(diagnostic => diagnostic.locator?.objectId !== projectionNodeId);
|
|
7721
8989
|
}
|
|
@@ -7826,8 +9094,7 @@ function syncViewportMeasurementState(state) {
|
|
|
7826
9094
|
if (measurement)
|
|
7827
9095
|
state.viewportMeasurement = measurement;
|
|
7828
9096
|
}
|
|
7829
|
-
function hasSceneCameraPreviewRig(
|
|
7830
|
-
const document = state.session?.getState().workingDocument ?? null;
|
|
9097
|
+
function hasSceneCameraPreviewRig(options, document) {
|
|
7831
9098
|
return !!document && !!options.documentAdapter.getSceneCameraPreviewRig?.(document);
|
|
7832
9099
|
}
|
|
7833
9100
|
function applyActiveTransformPreviewToInspectorObject(state, options, document, inspectorObject) {
|
|
@@ -8053,7 +9320,7 @@ function tryFreezeHierarchyContributionDocument(document) {
|
|
|
8053
9320
|
return null;
|
|
8054
9321
|
}
|
|
8055
9322
|
}
|
|
8056
|
-
export function createLocalEditorSceneHierarchyScopeAdapter(state, options) {
|
|
9323
|
+
export function createLocalEditorSceneHierarchyScopeAdapter(state, options, applyRenamePresentation) {
|
|
8057
9324
|
const clipboard = new Map();
|
|
8058
9325
|
return {
|
|
8059
9326
|
id: 'fps.editor.product.scene-hierarchy',
|
|
@@ -8061,7 +9328,7 @@ export function createLocalEditorSceneHierarchyScopeAdapter(state, options) {
|
|
|
8061
9328
|
canProvide: () => !state.prefabStage,
|
|
8062
9329
|
getTree(cache) {
|
|
8063
9330
|
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
8064
|
-
const structureKey = `scene:${String(sessionState?.documentStructureRevision ?? 0)}:${String(state.markerGraphVisibilityRevision)}`;
|
|
9331
|
+
const structureKey = `scene:${String(sessionState?.documentStructureRevision ?? 0)}:${String(state.markerGraphVisibilityRevision)}:${String(state.hierarchyPresentationFallbackRevision)}`;
|
|
8065
9332
|
const revision = resolveLocalEditorHierarchyRevision(state);
|
|
8066
9333
|
if (cache?.structureKey === structureKey && cache.snapshot.revision === revision)
|
|
8067
9334
|
return cache;
|
|
@@ -8163,7 +9430,8 @@ export function createLocalEditorSceneHierarchyScopeAdapter(state, options) {
|
|
|
8163
9430
|
: []),
|
|
8164
9431
|
];
|
|
8165
9432
|
},
|
|
8166
|
-
async executeOperation({ snapshot, invocation, operation, render, getSnapshot }) {
|
|
9433
|
+
async executeOperation({ snapshot, invocation, operation, render, getSnapshot, state: operationState }) {
|
|
9434
|
+
const state = operationState;
|
|
8167
9435
|
const resolve = (rowId) => this.resolveTarget(snapshot, rowId);
|
|
8168
9436
|
if (invocation.operationId === 'hierarchy.node.focus') {
|
|
8169
9437
|
const target = invocation.contextNodeId ? resolve(invocation.contextNodeId) : null;
|
|
@@ -8239,7 +9507,7 @@ export function createLocalEditorSceneHierarchyScopeAdapter(state, options) {
|
|
|
8239
9507
|
if (!targetId || !name || snapshot.readonly)
|
|
8240
9508
|
return createHarnessHierarchyOperationResult(false, false, snapshot.revision, 'hierarchy.rename.invalid', 'Rename target or name is invalid.');
|
|
8241
9509
|
const outcome = renameSceneGraphNode(state, options, { id: resolve(targetId)?.authoredId ?? targetId, name });
|
|
8242
|
-
if (outcome === 'changed')
|
|
9510
|
+
if (outcome === 'changed' && !applyRenamePresentation?.({ id: targetId, name }))
|
|
8243
9511
|
render();
|
|
8244
9512
|
return outcome === 'changed'
|
|
8245
9513
|
? createHarnessHierarchyOperationResult(true, true, getSnapshot().revision)
|
|
@@ -8407,7 +9675,8 @@ export function createLocalEditorPrefabHierarchyScopeAdapter(state, options) {
|
|
|
8407
9675
|
: []),
|
|
8408
9676
|
].flat();
|
|
8409
9677
|
},
|
|
8410
|
-
async executeOperation({ snapshot, invocation, operation, render, getSnapshot, executorStates }) {
|
|
9678
|
+
async executeOperation({ snapshot, invocation, operation, render, getSnapshot, executorStates, state: operationState }) {
|
|
9679
|
+
const state = operationState;
|
|
8411
9680
|
const resolve = (rowId) => this.resolveTarget(snapshot, rowId);
|
|
8412
9681
|
if (invocation.operationId === 'hierarchy.node.focus') {
|
|
8413
9682
|
const target = invocation.contextNodeId ? resolve(invocation.contextNodeId) : null;
|
|
@@ -8679,6 +9948,10 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8679
9948
|
applySelection: applyHierarchySelection,
|
|
8680
9949
|
listOperations,
|
|
8681
9950
|
async executeOperation(invocation) {
|
|
9951
|
+
const serializedAccess = getSerializedHierarchyInvocationAccess(invocation);
|
|
9952
|
+
const serializedOperationState = serializedAccess === undefined
|
|
9953
|
+
? state
|
|
9954
|
+
: createSerializedHierarchyOperationState(state, serializedAccess);
|
|
8682
9955
|
const validated = validateContext(invocation);
|
|
8683
9956
|
if ('ok' in validated)
|
|
8684
9957
|
return validated;
|
|
@@ -8698,13 +9971,16 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8698
9971
|
? invocation.input.visibleIds.filter((id) => typeof id === 'string')
|
|
8699
9972
|
: [...validated.nodeById.keys()];
|
|
8700
9973
|
const selectableIds = requestedIds.filter(id => validated.nodeById.get(id)?.selectable === true);
|
|
8701
|
-
|
|
9974
|
+
const apply = () => applyHierarchySelection({
|
|
8702
9975
|
...invocation,
|
|
8703
9976
|
selectedIds: selectableIds,
|
|
8704
9977
|
activeId: selectableIds.includes(invocation.activeId ?? '')
|
|
8705
9978
|
? invocation.activeId
|
|
8706
9979
|
: selectableIds[selectableIds.length - 1] ?? null,
|
|
8707
9980
|
});
|
|
9981
|
+
return serializedAccess === undefined
|
|
9982
|
+
? apply()
|
|
9983
|
+
: callWithEditorAuthoringSerializedAccess(serializedAccess, apply);
|
|
8708
9984
|
}
|
|
8709
9985
|
const contextNodeId = invocation.contextNodeId;
|
|
8710
9986
|
const contextNode = contextNodeId ? validated.nodeById.get(contextNodeId) : null;
|
|
@@ -8728,11 +10004,14 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8728
10004
|
selectedIds = descendants;
|
|
8729
10005
|
}
|
|
8730
10006
|
const selectableIds = selectedIds.filter(id => validated.nodeById.get(id)?.selectable === true);
|
|
8731
|
-
|
|
10007
|
+
const apply = () => applyHierarchySelection({
|
|
8732
10008
|
...invocation,
|
|
8733
10009
|
selectedIds: selectableIds,
|
|
8734
10010
|
activeId: selectableIds[0] ?? null,
|
|
8735
10011
|
});
|
|
10012
|
+
return serializedAccess === undefined
|
|
10013
|
+
? apply()
|
|
10014
|
+
: callWithEditorAuthoringSerializedAccess(serializedAccess, apply);
|
|
8736
10015
|
}
|
|
8737
10016
|
const contribution = (options.hierarchy?.operations ?? []).find(operation => operation.id === invocation.operationId);
|
|
8738
10017
|
if (contribution) {
|
|
@@ -8742,36 +10021,48 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8742
10021
|
const beforeRevision = validated.revision;
|
|
8743
10022
|
try {
|
|
8744
10023
|
return await runExclusiveResult(state, render, async () => {
|
|
8745
|
-
const
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
10024
|
+
const executeContribution = async (operationState = state) => {
|
|
10025
|
+
const preparedSnapshot = validateContext(invocation);
|
|
10026
|
+
if ('ok' in preparedSnapshot)
|
|
10027
|
+
return preparedSnapshot;
|
|
10028
|
+
const visibleContext = createOperationContributionContext(preparedSnapshot, invocation, invocation.input);
|
|
10029
|
+
if (!visibleContext || contribution.visible?.(visibleContext) === false) {
|
|
10030
|
+
return createHarnessHierarchyOperationResult(false, false, preparedSnapshot.revision, 'hierarchy.operation.unsupported', `Unsupported Hierarchy operation: ${invocation.operationId}`);
|
|
10031
|
+
}
|
|
10032
|
+
const disabledContext = createOperationContributionContext(preparedSnapshot, invocation, invocation.input);
|
|
10033
|
+
const disabled = disabledContext ? contribution.disabled?.(disabledContext) : true;
|
|
10034
|
+
if (disabled === true || typeof disabled === 'string') {
|
|
10035
|
+
return createHarnessHierarchyOperationResult(false, false, preparedSnapshot.revision, 'hierarchy.operation.disabled', typeof disabled === 'string' ? disabled : 'Hierarchy operation is disabled.');
|
|
10036
|
+
}
|
|
10037
|
+
const runContext = createOperationContributionContext(preparedSnapshot, invocation, invocation.input, 'isolated');
|
|
10038
|
+
if (!runContext) {
|
|
10039
|
+
return createHarnessHierarchyOperationResult(false, false, preparedSnapshot.revision, 'hierarchy.operation.unsupported', `Unsupported Hierarchy operation: ${invocation.operationId}`);
|
|
10040
|
+
}
|
|
10041
|
+
const contributionResult = await contribution.run(runContext);
|
|
10042
|
+
const commitSnapshot = validateContext(invocation);
|
|
10043
|
+
if ('ok' in commitSnapshot) {
|
|
10044
|
+
return createHarnessHierarchyOperationResult(false, false, commitSnapshot.revision, 'hierarchy.operation.stale-before-commit', 'Hierarchy scope changed while the operation was being prepared; no patch was applied.');
|
|
10045
|
+
}
|
|
10046
|
+
if (isLocalEditorHarnessPatchResult(contributionResult)
|
|
10047
|
+
&& contribution.effect !== undefined
|
|
10048
|
+
&& contribution.effect !== 'authoring') {
|
|
10049
|
+
return createHarnessHierarchyOperationResult(false, false, commitSnapshot.revision, 'hierarchy.operation.effect-mismatch', `${contribution.label} declared effect '${contribution.effect}' and cannot return an authoring patch.`);
|
|
10050
|
+
}
|
|
10051
|
+
const handled = applyHierarchyOperationContributionResult(operationState, options, contributionResult, contribution.label);
|
|
10052
|
+
if (handled)
|
|
10053
|
+
render();
|
|
10054
|
+
const current = getSnapshot();
|
|
10055
|
+
const changed = current.revision > beforeRevision;
|
|
10056
|
+
if (handled && (contribution.effect !== 'authoring' || changed)) {
|
|
10057
|
+
return createHarnessHierarchyOperationResult(true, changed, current.revision);
|
|
10058
|
+
}
|
|
10059
|
+
return createHarnessHierarchyOperationResult(false, changed, current.revision, 'hierarchy.operation.rejected', `${contribution.label} was rejected.`);
|
|
10060
|
+
};
|
|
10061
|
+
return contribution.effect === 'view'
|
|
10062
|
+
|| contribution.effect === 'selection'
|
|
10063
|
+
|| serializedAccess !== undefined
|
|
10064
|
+
? executeContribution(serializedOperationState)
|
|
10065
|
+
: state.runBrowserAuthoringMutation(invocation.operationId, JSON.stringify([invocation, validated.scopeKey, validated.revision]), executeContribution);
|
|
8775
10066
|
}, executorStates);
|
|
8776
10067
|
}
|
|
8777
10068
|
catch (error) {
|
|
@@ -8785,21 +10076,29 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8785
10076
|
const beforeRevision = validated.revision;
|
|
8786
10077
|
try {
|
|
8787
10078
|
return await runExclusiveResult(state, render, async () => {
|
|
8788
|
-
const
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
10079
|
+
const executeAdapter = async (operationState = state) => {
|
|
10080
|
+
const preparedSnapshot = validateContext(invocation);
|
|
10081
|
+
if ('ok' in preparedSnapshot)
|
|
10082
|
+
return preparedSnapshot;
|
|
10083
|
+
return adapter.executeOperation({
|
|
10084
|
+
snapshot: preparedSnapshot,
|
|
10085
|
+
context: invocation,
|
|
10086
|
+
invocation,
|
|
10087
|
+
operation: listedOperation,
|
|
10088
|
+
state: operationState,
|
|
10089
|
+
options,
|
|
10090
|
+
render,
|
|
10091
|
+
getSnapshot,
|
|
10092
|
+
executorStates,
|
|
10093
|
+
});
|
|
10094
|
+
};
|
|
10095
|
+
return listedOperation.effect === 'authoring' && serializedAccess === undefined
|
|
10096
|
+
? state.runBrowserAuthoringMutation(invocation.operationId, JSON.stringify([invocation, validated.scopeKey, validated.revision]), executeAdapter)
|
|
10097
|
+
: executeAdapter(serializedOperationState);
|
|
10098
|
+
}, executorStates, {
|
|
10099
|
+
renderBoundary: !(adapter.id === 'fps.editor.product.scene-hierarchy'
|
|
10100
|
+
&& invocation.operationId === 'hierarchy.node.rename'),
|
|
10101
|
+
});
|
|
8803
10102
|
}
|
|
8804
10103
|
catch (error) {
|
|
8805
10104
|
const current = getSnapshot();
|
|
@@ -8808,6 +10107,28 @@ export function createLocalEditorHarnessHierarchyScopeProvider(state, options, r
|
|
|
8808
10107
|
},
|
|
8809
10108
|
};
|
|
8810
10109
|
}
|
|
10110
|
+
function getSerializedHierarchyInvocationAccess(invocation) {
|
|
10111
|
+
return invocation[SERIALIZED_HIERARCHY_INVOCATION];
|
|
10112
|
+
}
|
|
10113
|
+
function createSerializedHierarchyOperationState(state, serializedAccess) {
|
|
10114
|
+
const session = state.session;
|
|
10115
|
+
if (!session)
|
|
10116
|
+
return state;
|
|
10117
|
+
const authorizedSession = createEditorAuthoringSerializedSessionView(session, serializedAccess);
|
|
10118
|
+
return new Proxy(state, {
|
|
10119
|
+
get(target, property, receiver) {
|
|
10120
|
+
if (property === 'session')
|
|
10121
|
+
return authorizedSession;
|
|
10122
|
+
return Reflect.get(target, property, receiver);
|
|
10123
|
+
},
|
|
10124
|
+
set(target, property, value, receiver) {
|
|
10125
|
+
if (property === 'session') {
|
|
10126
|
+
throw new Error('Serialized Hierarchy operations cannot replace the active Session.');
|
|
10127
|
+
}
|
|
10128
|
+
return Reflect.set(target, property, value, receiver);
|
|
10129
|
+
},
|
|
10130
|
+
});
|
|
10131
|
+
}
|
|
8811
10132
|
const BUILT_IN_HIERARCHY_OPERATION_IDS = new Set([
|
|
8812
10133
|
'hierarchy.node.focus',
|
|
8813
10134
|
'hierarchy.node.rename',
|
|
@@ -8857,6 +10178,13 @@ function createHarnessHierarchyOperationResult(ok, changed, revision, code, mess
|
|
|
8857
10178
|
: Object.freeze([]),
|
|
8858
10179
|
});
|
|
8859
10180
|
}
|
|
10181
|
+
function reportBrowserAuthoringFailure(state, render, error) {
|
|
10182
|
+
state.status = 'Editor command failed';
|
|
10183
|
+
state.statusTone = 'error';
|
|
10184
|
+
state.statusToneStatus = state.status;
|
|
10185
|
+
state.statusDetails = error instanceof Error ? error.message : String(error);
|
|
10186
|
+
render();
|
|
10187
|
+
}
|
|
8860
10188
|
function sameHierarchySelection(left, right) {
|
|
8861
10189
|
return left.length === right.length && left.every((id, index) => id === right[index]);
|
|
8862
10190
|
}
|
|
@@ -8884,6 +10212,32 @@ function getCachedLocalEditorHierarchyItems(state, options, document) {
|
|
|
8884
10212
|
}
|
|
8885
10213
|
return state.hierarchyItemsCache;
|
|
8886
10214
|
}
|
|
10215
|
+
function resolveAuthoritativeHierarchyLabels(state, options, document, ids) {
|
|
10216
|
+
const cachedItems = getCachedLocalEditorHierarchyItems(state, options, document);
|
|
10217
|
+
const cachedById = new Map(cachedItems.map(item => [item.id, item]));
|
|
10218
|
+
const labels = {};
|
|
10219
|
+
let changed = false;
|
|
10220
|
+
const nextItems = [...cachedItems];
|
|
10221
|
+
for (const id of ids) {
|
|
10222
|
+
const cached = cachedById.get(id);
|
|
10223
|
+
const projectedName = options.documentAdapter.getProjectionNode(document, id)?.name;
|
|
10224
|
+
const label = typeof projectedName === 'string' && projectedName.trim()
|
|
10225
|
+
? projectedName
|
|
10226
|
+
: cached?.label;
|
|
10227
|
+
if (!label)
|
|
10228
|
+
continue;
|
|
10229
|
+
labels[id] = label;
|
|
10230
|
+
if (cached && cached.label !== label) {
|
|
10231
|
+
const index = nextItems.findIndex(item => item.id === id);
|
|
10232
|
+
if (index >= 0)
|
|
10233
|
+
nextItems[index] = Object.freeze({ ...cached, label, name: label });
|
|
10234
|
+
changed = true;
|
|
10235
|
+
}
|
|
10236
|
+
}
|
|
10237
|
+
if (changed)
|
|
10238
|
+
state.hierarchyItemsCache = Object.freeze(nextItems);
|
|
10239
|
+
return labels;
|
|
10240
|
+
}
|
|
8887
10241
|
function getLocalEditorDiagnosticContext(state) {
|
|
8888
10242
|
return {
|
|
8889
10243
|
scopeId: state.prefabStage
|
|
@@ -9149,6 +10503,23 @@ function toBrowserStatusDiagnostic(diagnostic, context) {
|
|
|
9149
10503
|
...(diagnostic.details ? { details: normalizeEditorDiagnosticDetails(diagnostic.details) } : {}),
|
|
9150
10504
|
};
|
|
9151
10505
|
}
|
|
10506
|
+
function createUiSessionState(state) {
|
|
10507
|
+
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
10508
|
+
const projectSnapshot = state.prefabStage ? null : state.projectAuthoringSnapshot;
|
|
10509
|
+
return sessionState
|
|
10510
|
+
? {
|
|
10511
|
+
source: sessionState.source,
|
|
10512
|
+
dirty: state.prefabStage?.transaction.snapshot().documentDirty
|
|
10513
|
+
?? projectSnapshot?.dirty
|
|
10514
|
+
?? sessionState.dirty,
|
|
10515
|
+
canUndo: projectSnapshot?.canUndo ?? sessionState.canUndo,
|
|
10516
|
+
canRedo: projectSnapshot?.canRedo ?? sessionState.canRedo,
|
|
10517
|
+
history: projectSnapshot
|
|
10518
|
+
? { entries: projectSnapshot.history.entries.map(entry => ({ ...entry })) }
|
|
10519
|
+
: sessionState.history,
|
|
10520
|
+
}
|
|
10521
|
+
: null;
|
|
10522
|
+
}
|
|
9152
10523
|
function createUiState(state, options, hierarchySnapshot, toolManager) {
|
|
9153
10524
|
const sessionState = state.session?.getState({ cloneDocuments: false });
|
|
9154
10525
|
const document = sessionState?.workingDocument ?? null;
|
|
@@ -9188,7 +10559,6 @@ function createUiState(state, options, hierarchySnapshot, toolManager) {
|
|
|
9188
10559
|
const uiState = {
|
|
9189
10560
|
mode: state.mode,
|
|
9190
10561
|
busy: state.busy,
|
|
9191
|
-
agentBridge: state.agentBridgeStatus,
|
|
9192
10562
|
status: state.status,
|
|
9193
10563
|
statusTone: state.statusToneStatus === state.status ? state.statusTone : 'default',
|
|
9194
10564
|
statusDetails: state.statusToneStatus === state.status ? state.statusDetails : '',
|
|
@@ -9207,6 +10577,7 @@ function createUiState(state, options, hierarchySnapshot, toolManager) {
|
|
|
9207
10577
|
inspectorObject: previewInspectorObject,
|
|
9208
10578
|
inspectorMultiObject: previewInspectorMultiObject,
|
|
9209
10579
|
inspectorPending: false,
|
|
10580
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9210
10581
|
renderingPanel: document
|
|
9211
10582
|
? options.documentAdapter.getRenderingPanelState?.(document, {
|
|
9212
10583
|
scene: state.world?.scene ?? null,
|
|
@@ -9251,22 +10622,14 @@ function createUiState(state, options, hierarchySnapshot, toolManager) {
|
|
|
9251
10622
|
performanceStats: cloneLocalEditorPerformanceStats(state.performanceStats),
|
|
9252
10623
|
sceneCameraPreview: {
|
|
9253
10624
|
enabled: state.sceneCameraPreviewEnabled,
|
|
9254
|
-
available: hasSceneCameraPreviewRig(
|
|
10625
|
+
available: hasSceneCameraPreviewRig(options, document),
|
|
9255
10626
|
},
|
|
9256
10627
|
prefabStage: createBrowserPrefabStageState(state, options, document),
|
|
9257
10628
|
grid: {
|
|
9258
10629
|
visible: state.gridVisible,
|
|
9259
10630
|
available: !!state.grid,
|
|
9260
10631
|
},
|
|
9261
|
-
session:
|
|
9262
|
-
? {
|
|
9263
|
-
source: sessionState.source,
|
|
9264
|
-
dirty: state.prefabStage?.transaction.snapshot().documentDirty ?? sessionState.dirty,
|
|
9265
|
-
canUndo: sessionState.canUndo,
|
|
9266
|
-
canRedo: sessionState.canRedo,
|
|
9267
|
-
history: sessionState.history,
|
|
9268
|
-
}
|
|
9269
|
-
: null,
|
|
10632
|
+
session: createUiSessionState(state),
|
|
9270
10633
|
};
|
|
9271
10634
|
uiState.documentRevision = sessionState?.documentRevision ?? 0;
|
|
9272
10635
|
const diagnosticContext = getLocalEditorDiagnosticContext(state);
|
|
@@ -9342,25 +10705,25 @@ function createBrowserPrefabStageState(state, options, document, includeInspecto
|
|
|
9342
10705
|
previewNodeId: descriptor.previewNodeId,
|
|
9343
10706
|
};
|
|
9344
10707
|
}
|
|
9345
|
-
function
|
|
10708
|
+
function summarizeEditorCommandPrefabStage(state, options) {
|
|
9346
10709
|
const document = state.session?.getState({ cloneDocuments: false }).workingDocument ?? null;
|
|
9347
10710
|
const stage = createBrowserPrefabStageState(state, options, document);
|
|
9348
10711
|
if (!stage)
|
|
9349
10712
|
return null;
|
|
9350
|
-
return
|
|
10713
|
+
return createEditorCommandPrefabStageState(stage);
|
|
9351
10714
|
}
|
|
9352
|
-
function
|
|
10715
|
+
function summarizeEditorCommandPrefabStageDetails(state, options) {
|
|
9353
10716
|
const document = state.session?.getState({ cloneDocuments: false }).workingDocument ?? null;
|
|
9354
10717
|
const stage = createBrowserPrefabStageState(state, options, document);
|
|
9355
10718
|
if (!stage)
|
|
9356
10719
|
return null;
|
|
9357
10720
|
return {
|
|
9358
|
-
stage:
|
|
9359
|
-
nodeDetails:
|
|
10721
|
+
stage: createEditorCommandPrefabStageState(stage),
|
|
10722
|
+
nodeDetails: createEditorCommandPrefabNodeDetails(stage.structureItems),
|
|
9360
10723
|
inspectorObject: stage.inspectorObject ?? null,
|
|
9361
10724
|
};
|
|
9362
10725
|
}
|
|
9363
|
-
function
|
|
10726
|
+
function createEditorCommandPrefabNodeDetails(items) {
|
|
9364
10727
|
const details = [];
|
|
9365
10728
|
const stack = [...items].reverse();
|
|
9366
10729
|
while (stack.length > 0) {
|
|
@@ -9389,7 +10752,7 @@ function createAgentBridgePrefabNodeDetails(items) {
|
|
|
9389
10752
|
}
|
|
9390
10753
|
return details;
|
|
9391
10754
|
}
|
|
9392
|
-
function
|
|
10755
|
+
function createEditorCommandPrefabStageState(stage) {
|
|
9393
10756
|
return {
|
|
9394
10757
|
assetId: stage.assetId,
|
|
9395
10758
|
...(stage.browserAssetId ? { browserAssetId: stage.browserAssetId } : {}),
|
|
@@ -9405,7 +10768,7 @@ function createAgentBridgePrefabStageState(stage) {
|
|
|
9405
10768
|
canDiscard: stage.canDiscard,
|
|
9406
10769
|
};
|
|
9407
10770
|
}
|
|
9408
|
-
function
|
|
10771
|
+
function createEditorCommandPrefabSummaryFromStage(stage) {
|
|
9409
10772
|
return {
|
|
9410
10773
|
assetId: stage.assetId,
|
|
9411
10774
|
...(stage.browserAssetId ? { browserAssetId: stage.browserAssetId } : {}),
|
|
@@ -9416,7 +10779,7 @@ function createAgentBridgePrefabSummaryFromStage(stage) {
|
|
|
9416
10779
|
status: 'ready',
|
|
9417
10780
|
};
|
|
9418
10781
|
}
|
|
9419
|
-
function
|
|
10782
|
+
function isSameEditorCommandPrefabStage(left, right) {
|
|
9420
10783
|
if (!left || !right)
|
|
9421
10784
|
return false;
|
|
9422
10785
|
return left.assetId === right.assetId
|
|
@@ -9583,10 +10946,10 @@ function createLocalEditorEditingContextProviders(state, options) {
|
|
|
9583
10946
|
return focusProjectionNode(state, activeId);
|
|
9584
10947
|
},
|
|
9585
10948
|
commitTransform: event => commitSceneGizmoTransform(state, options, event),
|
|
9586
|
-
beginDuplicateDrag: input => beginDuplicateDrag(state, options, input),
|
|
10949
|
+
beginDuplicateDrag: (input, session) => beginDuplicateDrag(state, options, input, session),
|
|
9587
10950
|
getInspectorObject: (document, targetId) => createSceneEditingContextInspectorObject(state, options, document, targetId),
|
|
9588
10951
|
getInspectorMultiObject: (document, targetIds, activeId) => createSceneEditingContextInspectorMultiObject(state, options, document, targetIds, activeId),
|
|
9589
|
-
patchInspectorProperty: input => patchSceneSerializedProperty(state, options, input),
|
|
10952
|
+
patchInspectorProperty: (input, onCommitted) => patchSceneSerializedProperty(state, options, input, onCommitted),
|
|
9590
10953
|
resolveInspectorPreviewTransform(document, targetId, transform, preview) {
|
|
9591
10954
|
const createInspectorPreview = options.documentAdapter.createTransformInspectorPreview;
|
|
9592
10955
|
if (!document || !createInspectorPreview)
|
|
@@ -9799,6 +11162,7 @@ function createUiToolPresentationPreviewState(state, snapshot) {
|
|
|
9799
11162
|
};
|
|
9800
11163
|
}
|
|
9801
11164
|
function publishLocalEditorSelectionPresentation(state, options, renderPreviewUi, reason) {
|
|
11165
|
+
cancelInspectorPresentationPreview(state);
|
|
9802
11166
|
syncViewportSpatialOverlay(state, options);
|
|
9803
11167
|
renderPreviewUi(createUiSelectionPresentationPreviewState(state, options));
|
|
9804
11168
|
requestEditorSceneFrame(state, reason);
|
|
@@ -9811,6 +11175,7 @@ function createUiSelectionPresentationPreviewState(state, options) {
|
|
|
9811
11175
|
const transformSelectionIsLarge = isLargeSelection(selectedIds);
|
|
9812
11176
|
const document = state.session?.getState({ cloneDocuments: false }).workingDocument ?? null;
|
|
9813
11177
|
return {
|
|
11178
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9814
11179
|
selectedIds,
|
|
9815
11180
|
activeId,
|
|
9816
11181
|
selectionSummary: {
|
|
@@ -9837,6 +11202,7 @@ function createUiSelectionInspectorPreviewState(state, options) {
|
|
|
9837
11202
|
const document = state.session?.getState({ cloneDocuments: false }).workingDocument ?? null;
|
|
9838
11203
|
if (!document) {
|
|
9839
11204
|
return {
|
|
11205
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9840
11206
|
inspectorObject: null,
|
|
9841
11207
|
inspectorMultiObject: null,
|
|
9842
11208
|
inspectorPending: false,
|
|
@@ -9846,6 +11212,7 @@ function createUiSelectionInspectorPreviewState(state, options) {
|
|
|
9846
11212
|
if (state.prefabStage) {
|
|
9847
11213
|
const prefabStage = createBrowserPrefabStageState(state, options, document);
|
|
9848
11214
|
return {
|
|
11215
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9849
11216
|
prefabStage,
|
|
9850
11217
|
inspectorObject: prefabStage?.inspectorObject ?? null,
|
|
9851
11218
|
inspectorMultiObject: null,
|
|
@@ -9854,6 +11221,7 @@ function createUiSelectionInspectorPreviewState(state, options) {
|
|
|
9854
11221
|
}
|
|
9855
11222
|
const editingContext = getLocalEditorEditingContext(state);
|
|
9856
11223
|
return {
|
|
11224
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9857
11225
|
inspectorObject: editingContext.getInspectorObject(document),
|
|
9858
11226
|
inspectorMultiObject: editingContext.getInspectorMultiObject(document),
|
|
9859
11227
|
inspectorPending: false,
|
|
@@ -9861,10 +11229,6 @@ function createUiSelectionInspectorPreviewState(state, options) {
|
|
|
9861
11229
|
}
|
|
9862
11230
|
function cancelScheduledSelectionInspectorRefresh(state) {
|
|
9863
11231
|
state.selectionInspectorRefreshGeneration += 1;
|
|
9864
|
-
if (state.selectionInspectorRefreshFrame !== null) {
|
|
9865
|
-
globalThis.cancelAnimationFrame?.(state.selectionInspectorRefreshFrame);
|
|
9866
|
-
state.selectionInspectorRefreshFrame = null;
|
|
9867
|
-
}
|
|
9868
11232
|
if (state.selectionInspectorRefreshTimeout !== null) {
|
|
9869
11233
|
globalThis.clearTimeout(state.selectionInspectorRefreshTimeout);
|
|
9870
11234
|
state.selectionInspectorRefreshTimeout = null;
|
|
@@ -9892,18 +11256,7 @@ function scheduleSelectionInspectorRefresh(state, options, renderPreviewUi) {
|
|
|
9892
11256
|
});
|
|
9893
11257
|
}
|
|
9894
11258
|
};
|
|
9895
|
-
|
|
9896
|
-
state.selectionInspectorRefreshFrame = null;
|
|
9897
|
-
if (generation !== state.selectionInspectorRefreshGeneration || !state.world)
|
|
9898
|
-
return;
|
|
9899
|
-
state.selectionInspectorRefreshTimeout = globalThis.setTimeout(publish, 0);
|
|
9900
|
-
};
|
|
9901
|
-
if (typeof globalThis.requestAnimationFrame === 'function') {
|
|
9902
|
-
state.selectionInspectorRefreshFrame = globalThis.requestAnimationFrame(deferUntilAfterFrame);
|
|
9903
|
-
}
|
|
9904
|
-
else {
|
|
9905
|
-
state.selectionInspectorRefreshTimeout = globalThis.setTimeout(publish, 0);
|
|
9906
|
-
}
|
|
11259
|
+
state.selectionInspectorRefreshTimeout = globalThis.setTimeout(publish, 0);
|
|
9907
11260
|
}
|
|
9908
11261
|
function isLocalEditorSelectionDebugEnabled() {
|
|
9909
11262
|
return typeof globalThis.location?.search === 'string'
|
|
@@ -9935,6 +11288,7 @@ function createUiPreviewState(state, options) {
|
|
|
9935
11288
|
? applyActiveTransformPreviewToInspectorObject(state, options, document, withRuntimeInspectorSections(state, options, document, inspectorObjectBase))
|
|
9936
11289
|
: null;
|
|
9937
11290
|
return {
|
|
11291
|
+
inspectorPresentationGeneration: state.inspectorPresentationGeneration,
|
|
9938
11292
|
status: state.status,
|
|
9939
11293
|
statusTone: state.statusToneStatus === state.status ? state.statusTone : 'default',
|
|
9940
11294
|
statusDetails: state.statusToneStatus === state.status ? state.statusDetails : '',
|