@volter/editor-game 0.5.66 → 0.5.68
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/contributions/audio-unlock.service.ts +2 -2
- package/contributions/autoplay.service.ts +1 -1
- package/contributions/bridge.command.ts +3 -3
- package/contributions/build-player.document.tsx +95 -0
- package/contributions/canvas/component-board.service.ts +16 -0
- package/contributions/canvas/design-time-mount.service.ts +45 -0
- package/contributions/canvas-story-capture.service.ts +12 -0
- package/contributions/edit-mode-audio.service.ts +2 -2
- package/contributions/edit-mode-networking.service.ts +1 -1
- package/contributions/gameplay.command.ts +4 -4
- package/contributions/generation.service.ts +1 -1
- package/contributions/godot.style.ts +26 -6
- package/contributions/godot.view.ts +6 -0
- package/contributions/ingest.service.ts +2 -2
- package/contributions/instances.command.ts +1 -1
- package/contributions/navmesh.menu.ts +1 -1
- package/contributions/network-observer.service.ts +14 -0
- package/contributions/play.command.ts +10 -4
- package/contributions/react/component-board.service.ts +1 -1
- package/contributions/react/design-time-mount.service.ts +1 -1
- package/contributions/scene-document.service.ts +3 -3
- package/contributions/state-watch.menu.ts +1 -1
- package/contributions/state-watch.utility.tsx +1 -1
- package/contributions/team-playtest.service.ts +4 -4
- package/contributions/three/component-board.service.ts +1 -1
- package/contributions/three/component-verbs.command.ts +6 -6
- package/contributions/three/three-authoring.service.ts +8 -5
- package/contributions/three-story-capture.service.ts +12 -0
- package/contributions/unity.style.ts +17 -7
- package/contributions/unity.view.ts +6 -0
- package/contributions/unreal.style.ts +10 -2
- package/contributions/unreal.view.ts +5 -0
- package/package.json +21 -10
- package/src/asset-budget/AssetBudgetPanel.tsx +1 -1
- package/src/asset-budget/asset-budget-model.ts +1 -1
- package/src/audio/AudioDebuggerPanel.tsx +1 -1
- package/src/bridge/dispatch.ts +14 -14
- package/src/bridge/live-frames.ts +1 -1
- package/src/bridge/screenshot.ts +3 -3
- package/src/build/BuildProfilesPanel.tsx +14 -3
- package/src/build/build-session.ts +35 -0
- package/src/canvas/canvas-board/CanvasBoardDocument.tsx +749 -0
- package/src/canvas/canvas-board/canvas-board-model.ts +407 -0
- package/src/canvas/canvas-board/canvas-component-board.ts +56 -0
- package/src/canvas/canvas-design-mount.ts +524 -0
- package/src/canvas/design-time-canvas-mount.ts +79 -0
- package/src/coverage/live-authoring-surface.ts +5 -5
- package/src/coverage/live-project-verbs.ts +1 -1
- package/src/coverage/native-system-coverage.ts +5 -5
- package/src/coverage/root-coverage.ts +1 -1
- package/src/coverage/session-coverage.ts +3 -3
- package/src/design-system-stories/ApplicationChrome.stories.tsx +5 -5
- package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +7 -7
- package/src/edit-mode/edit-mode-audio.ts +4 -4
- package/src/edit-mode/edit-mode-networking.ts +2 -2
- package/src/game-document/GameCaptureFrameButton.tsx +1 -1
- package/src/game-document/GameDocument.tsx +2 -2
- package/src/game-document/GamePanel.tsx +4 -4
- package/src/game-document/InstanceInspectorPicker.tsx +2 -2
- package/src/game-document/crowd-debug.ts +1 -1
- package/src/game-document/device-preview.ts +10 -11
- package/src/game-document/physics-debug.ts +1 -1
- package/src/generation/GenerationActivity.tsx +3 -3
- package/src/generation/generation-documents.tsx +5 -5
- package/src/generation/generation-jobs.ts +1 -1
- package/src/host/adapter-runtime-bindings.ts +96 -5
- package/src/host/authoring/babylon-authoring-adapter.ts +6 -6
- package/src/host/authoring/gesture-persist.ts +1 -1
- package/src/host/authoring/ingest-data-writer.ts +1 -1
- package/src/host/authoring/ingest-source-persistence.ts +4 -4
- package/src/host/authoring/mounted-authoring.ts +4 -4
- package/src/host/authoring/phaser-live-authoring-adapter.ts +4 -4
- package/src/host/authoring/pixi-authoring-adapter.ts +178 -31
- package/src/host/authoring/pixi-creatable-kinds.ts +62 -0
- package/src/host/authoring/pixi-creation-site-write-target.ts +2 -2
- package/src/host/authoring/pixi-live-write-target.ts +4 -4
- package/src/host/authoring/pixi-source-identity.ts +3 -3
- package/src/host/authoring/pixi-source-write-target.ts +1709 -0
- package/src/host/authoring/pixi-still-presentation.ts +1 -1
- package/src/host/authoring/pixi-structure-history.ts +2 -2
- package/src/host/authoring/pixi-transform-channels.ts +16 -14
- package/src/host/authoring/source-persistence-backend.ts +3 -3
- package/src/host/authoring/struct-write-pipe.ts +1 -1
- package/src/host/binding-resolver.ts +8 -9
- package/src/host/browser-transpile.ts +1 -1
- package/src/host/canvas-entry-runtime.ts +58 -47
- package/src/host/canvas-preview-frames.ts +482 -0
- package/src/host/components/CameraAuthoringOverlay.tsx +1 -1
- package/src/host/components/HeaderTelemetry.tsx +4 -4
- package/src/host/components/PixiIsolationSceneContent.tsx +11 -11
- package/src/host/components/ThreeIsolationSceneContent.tsx +3 -3
- package/src/host/components/frame-debugger-model.ts +2 -2
- package/src/host/components/header-telemetry-model.ts +2 -2
- package/src/host/components/scene-document.tsx +14 -14
- package/src/host/components/utility-view-state.ts +1 -1
- package/src/host/components/world-root-stage-binding.tsx +12 -12
- package/src/host/components/world-root-stage.ts +70 -49
- package/src/host/coverage/system-adapter-coverage.ts +3 -4
- package/src/host/design-system-stories/fixtures/editor-runtime.tsx +9 -11
- package/src/host/document-preview-three.ts +1 -1
- package/src/host/entry-adjudication.ts +6 -6
- package/src/host/game-css-scope-transform.ts +4 -0
- package/src/host/game-realm-page.ts +1 -1
- package/src/host/gameplay-export.ts +25 -14
- package/src/host/gameplay-recording.ts +5 -5
- package/src/host/gated-globals.ts +2 -2
- package/src/host/history/json-history-resource.ts +1 -1
- package/src/host/projection/pixi.ts +24 -2
- package/src/host/r3f-entry-runtime.ts +65 -34
- package/src/host/react-mount-runtime.ts +7 -48
- package/src/host/realm-services.ts +1 -1
- package/src/host/roots/canvas-root.tsx +373 -0
- package/src/host/roots/r3f-root.tsx +473 -0
- package/src/host/roots/react-root.ts +9 -43
- package/src/host/served-bundle-runtime-modules.ts +3 -19
- package/src/host/server-log-bridge.ts +2 -2
- package/src/host/stories/mounted-story-viewport-source.ts +1 -1
- package/src/host/stories/pixi-story-model.ts +30 -0
- package/src/host/stories/story-media-captures.ts +46 -0
- package/src/host/stories/story-media-presence.ts +3 -3
- package/src/host/stories/story-pixi-preview.ts +408 -0
- package/src/host/stories/story-three-preview.ts +806 -0
- package/src/host/stories/three-story-captures.ts +35 -0
- package/src/host/story-three-preview-runtime.ts +56 -0
- package/src/host/use-active-performance-source.ts +2 -2
- package/src/host/viewport-pose-memory.ts +1 -1
- package/src/host/viewport-root-presentation.ts +6 -5
- package/src/ingest/active-ingest.ts +1 -1
- package/src/ingest/authoring/ingest-dom-surface-authoring.ts +4 -4
- package/src/ingest/authoring/ingest-root-adapter.ts +8 -8
- package/src/ingest/deferred-ingest-play.ts +6 -6
- package/src/ingest/discovery-public-ingest.ts +2 -2
- package/src/ingest/ingest-boot-viewport.ts +2 -2
- package/src/ingest/ingest-canvas-scene-document.tsx +9 -9
- package/src/ingest/ingest-canvas-scene.ts +3 -3
- package/src/ingest/ingest-evidence-hook.ts +1 -1
- package/src/ingest/ingest-frame-snapshot.ts +1 -1
- package/src/ingest/ingest-play-control.ts +1 -1
- package/src/ingest/ingest-render-debug.ts +10 -10
- package/src/ingest/ingest-siblings.ts +13 -25
- package/src/ingest/module-mode.ts +14 -14
- package/src/ingest/mount-canvas-ingest-root.ts +21 -21
- package/src/ingest/mount-coverage.ts +2 -2
- package/src/ingest/mount-dom-ingest-root.ts +11 -11
- package/src/ingest/mount-ingest-root.ts +8 -8
- package/src/ingest/mount-three-ingest-root.ts +8 -8
- package/src/ingest/resolve-canvas.ts +1 -1
- package/src/ingest/served-html-boot.ts +1 -1
- package/src/ingest/surface-canvas.ts +1 -1
- package/src/ingest/unmount-ingest-root.ts +5 -5
- package/src/navmesh/navmesh-handler.ts +24 -16
- package/src/network/NetworkInspectorPanel.tsx +939 -37
- package/src/network/network-inspector-model.ts +20 -2
- package/src/play/play-log-events.ts +1 -1
- package/src/play/play-mode.ts +76 -133
- package/src/play/play-recording.ts +1 -1
- package/src/play/react-play-live-authoring.ts +3 -3
- package/src/play/run-selection.ts +93 -0
- package/src/play-bar/PlayBar.tsx +20 -39
- package/src/profiler/FrameDebuggerPanel.tsx +1 -1
- package/src/profiler/PerformancePanel.tsx +3 -3
- package/src/react/design-time-react-mount.ts +23 -65
- package/src/react/dom-authoring-adapter.ts +9 -9
- package/src/react/react-inspector-section.tsx +5 -5
- package/src/react/react-world-authoring-adapter.ts +11 -11
- package/src/react/story-documents/story-documents.tsx +9 -9
- package/src/react/ui-board-document.tsx +7 -7
- package/src/react/ui-component-board.ts +2 -2
- package/src/runtime/adapter/audio-meter.ts +21 -0
- package/src/runtime/adapter/first-party-audio-system.ts +230 -0
- package/src/runtime/adapter/ingest/contract-debug-adapter.ts +114 -0
- package/src/runtime/adapter/ingest/contract-system-adapters.ts +256 -0
- package/src/runtime/adapter/ingest/merge-debug-adapters.ts +197 -0
- package/src/runtime/adapter/ingest/observation-debug-adapter.ts +162 -0
- package/src/runtime/adapter/ingest/upstream-pin.ts +51 -0
- package/src/runtime/adapter/native-debug-module.ts +498 -0
- package/src/runtime/audio/bus-mixer.ts +161 -0
- package/src/runtime/audio/pose-guard.ts +80 -0
- package/src/runtime/core/frame-pacing.ts +126 -0
- package/src/runtime/core/game-loop.ts +225 -0
- package/src/runtime/core/game-scoped-slot.ts +28 -0
- package/src/runtime/core/seeded-random.ts +162 -0
- package/src/runtime/core/sim-clock.ts +391 -0
- package/src/runtime/core/system-runner.ts +269 -0
- package/src/runtime/core/types.ts +104 -0
- package/src/runtime/create-runtime.ts +1128 -0
- package/src/runtime/debug-bridge.ts +570 -0
- package/src/runtime/debug-registry.ts +899 -0
- package/src/runtime/dev/chrome-trace.ts +153 -0
- package/src/runtime/dev/instruments.ts +403 -0
- package/src/runtime/dev/logger.ts +119 -0
- package/src/runtime/dev/performance-profiler.ts +367 -0
- package/src/runtime/dev/register-render-vitals.ts +276 -0
- package/src/runtime/dev/render-census.ts +354 -0
- package/src/runtime/dev/render-debug-adapter.ts +218 -0
- package/src/runtime/dev/render-memory.ts +226 -0
- package/src/runtime/dev/render-vitals.ts +338 -0
- package/src/runtime/dev/static-batch-advisor.ts +188 -0
- package/src/runtime/dev/webgl-frame-capture.ts +366 -0
- package/src/runtime/dev/webgl-gpu-timer.ts +53 -0
- package/src/runtime/dev-build.ts +47 -0
- package/src/runtime/game.ts +1636 -0
- package/src/runtime/gameplay-rng-trap.ts +135 -0
- package/src/runtime/host-context.ts +64 -0
- package/src/runtime/input-router.ts +182 -0
- package/src/runtime/mount-manifest.ts +480 -0
- package/src/runtime/pixi/authoring.ts +706 -0
- package/src/runtime/pixi/ingest.ts +116 -0
- package/src/runtime/pixi/physics-registry.ts +49 -0
- package/src/runtime/pixi/render-pass-bracket.ts +117 -0
- package/src/runtime/pixi/scene-capture.ts +179 -0
- package/src/runtime/pixi/system-adapters.ts +69 -0
- package/src/runtime/playtest.ts +22 -0
- package/src/runtime/presentation.ts +141 -0
- package/src/runtime/render-control.ts +642 -0
- package/src/runtime/render-seed.ts +77 -0
- package/src/runtime/run-ticks-settled.ts +73 -0
- package/src/runtime/setup/setup-audio.ts +72 -0
- package/src/services/audio-pose-guard.ts +2 -2
- package/src/services/game-audio.ts +152 -0
- package/src/services/game-network.ts +767 -0
- package/src/services/game-physics.ts +334 -0
- package/src/state-watch/StateWatchPanel.tsx +1 -1
- package/src/three/authoring/camera-runtime-inspector-section.tsx +3 -2
- package/src/three/authoring/constraint-inspector-section.tsx +6 -5
- package/src/three/authoring/model-asset-inspector-section.tsx +7 -6
- package/src/three/authoring/oid-source-persistence.ts +7 -7
- package/src/three/authoring/r3f-design-session.ts +58 -54
- package/src/three/authoring/r3f-source-authoring-adapter.ts +95 -91
- package/src/three/authoring/reflection-probe-inspector-section.tsx +3 -2
- package/src/three/authoring/three-authoring-adapter.ts +29 -29
- package/src/three/component-verbs/extract-menu.ts +7 -6
- package/src/three/component-verbs/fork-menu.ts +7 -6
- package/src/three/component-verbs/internals-menu.ts +2 -2
- package/src/three/story-documents/three-story-documents.tsx +13 -13
- package/src/three/three-board/ThreeBoardDocument.tsx +13 -12
- package/src/three/three-board/board-scene.ts +6 -6
- package/src/three/three-board/three-component-board.ts +2 -2
- package/src/services/game-audio-unlock.ts +0 -48
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* pause/filter, the sparkline sample history, and the polyline geometry —
|
|
10
10
|
* lives here.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
12
|
+
* The inspector reads only the `NetworkingAdapter` interface; decoding a
|
|
13
|
+
* game's Colyseus rooms is the observer's (`services/game-network.ts`).
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import type {
|
|
@@ -82,6 +82,18 @@ export interface NetworkCapabilityMap {
|
|
|
82
82
|
/** The adapter can SET the local identity (`setPlayerIdentity`) — the
|
|
83
83
|
* inspector shows an EDITABLE name field. Implies `identity`. */
|
|
84
84
|
identitySettable: boolean;
|
|
85
|
+
/** Traffic per message type (`getTrafficByType`). */
|
|
86
|
+
traffic: boolean;
|
|
87
|
+
/** Sending a message into the room as this client (`sendMessage`). */
|
|
88
|
+
send: boolean;
|
|
89
|
+
/** Measuring a round trip (`ping`). */
|
|
90
|
+
ping: boolean;
|
|
91
|
+
/** The room server's own view (`inspectServer`). */
|
|
92
|
+
server: boolean;
|
|
93
|
+
/** Traffic per replicated entity (`getTrafficByEntity`). */
|
|
94
|
+
entityTraffic: boolean;
|
|
95
|
+
/** Tallying that can be started and stopped (`isRecording`/`setRecording`). */
|
|
96
|
+
recording: boolean;
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
export function deriveNetworkCapabilities(
|
|
@@ -103,6 +115,12 @@ export function deriveNetworkCapabilities(
|
|
|
103
115
|
stats: typeof adapter.getReplicationStats === 'function',
|
|
104
116
|
identity: typeof adapter.getPlayerIdentity === 'function',
|
|
105
117
|
identitySettable: typeof adapter.setPlayerIdentity === 'function',
|
|
118
|
+
traffic: typeof adapter.getTrafficByType === 'function',
|
|
119
|
+
send: typeof adapter.sendMessage === 'function',
|
|
120
|
+
ping: typeof adapter.ping === 'function',
|
|
121
|
+
server: typeof adapter.inspectServer === 'function',
|
|
122
|
+
entityTraffic: typeof adapter.getTrafficByEntity === 'function',
|
|
123
|
+
recording: typeof adapter.isRecording === 'function' && typeof adapter.setRecording === 'function',
|
|
106
124
|
};
|
|
107
125
|
}
|
|
108
126
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LogEntry } from '@volter/editor-
|
|
1
|
+
import type { LogEntry } from '@volter/editor-sdk/kit/editor-api';
|
|
2
2
|
import type { TickStampedEvent } from '@volter/editor-project/adapter/system-adapter';
|
|
3
3
|
|
|
4
4
|
/** Convert newly observed game-authored debug events into persistent JSONL entries. */
|
package/src/play/play-mode.ts
CHANGED
|
@@ -15,19 +15,19 @@ import { editorHost } from '@volter/editor-sdk/host';
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { installAdapterRuntimeBindings } from '../host/adapter-runtime-bindings';
|
|
18
|
-
import { getAuthoringOverride, setActiveAuthoring } from '@volter/editor-
|
|
18
|
+
import { getAuthoringOverride, setActiveAuthoring } from '@volter/editor-sdk/kit/authoring/active-adapter';
|
|
19
19
|
import {
|
|
20
20
|
getActiveNetworking,
|
|
21
21
|
inspectedInstanceId,
|
|
22
22
|
setActiveSystems,
|
|
23
23
|
setInspectedInstance,
|
|
24
24
|
updateInstanceSystems,
|
|
25
|
-
} from '@volter/editor-
|
|
26
|
-
import { BoundaryAuthoringAdapter } from '@volter/editor-
|
|
25
|
+
} from '@volter/editor-sdk/kit/authoring/active-systems';
|
|
26
|
+
import { BoundaryAuthoringAdapter } from '@volter/editor-sdk/kit/authoring/boundary-authoring-adapter';
|
|
27
27
|
import {
|
|
28
28
|
CompositeAuthoringAdapter,
|
|
29
29
|
type CompositeChild,
|
|
30
|
-
} from '@volter/editor-
|
|
30
|
+
} from '@volter/editor-sdk/kit/authoring/composite-authoring-adapter';
|
|
31
31
|
import { createEphemeralPersistence } from '../host/authoring/ephemeral-persistence';
|
|
32
32
|
import {
|
|
33
33
|
EPHEMERAL_DESTINATION,
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
type WriteAck,
|
|
37
37
|
} from '@volter/editor-sdk/kit/write-pipe';
|
|
38
38
|
import { resolveAllRootEntries } from '../host/binding-resolver';
|
|
39
|
-
import type { LogEntry } from '@volter/editor-
|
|
40
|
-
import { endLogSession, flushLogEntries, startLogSession } from '@volter/editor-
|
|
39
|
+
import type { LogEntry } from '@volter/editor-sdk/kit/editor-api';
|
|
40
|
+
import { endLogSession, flushLogEntries, startLogSession } from '@volter/editor-sdk/kit/editor-api';
|
|
41
41
|
import type { ConsoleEntry } from '@volter/editor-sdk/kit/editor-console';
|
|
42
42
|
import {
|
|
43
43
|
editorConsole,
|
|
@@ -45,15 +45,15 @@ import {
|
|
|
45
45
|
resumeEditorConsoleCapture,
|
|
46
46
|
suspendEditorConsoleCapture,
|
|
47
47
|
} from '@volter/editor-sdk/kit/editor-console';
|
|
48
|
-
import { EDITOR_PARTICIPANT_ID, sendControl } from '@volter/editor-
|
|
48
|
+
import { EDITOR_PARTICIPANT_ID, sendControl } from '@volter/editor-sdk/kit/editor-presence';
|
|
49
49
|
import {
|
|
50
50
|
isEditorPresentationActive,
|
|
51
51
|
subscribeEditorPresentationActivity,
|
|
52
52
|
} from '@volter/editor-sdk/kit/editor-presentation-activity';
|
|
53
|
-
import type { EditorShellStore } from '@volter/editor-
|
|
53
|
+
import type { EditorShellStore } from '@volter/editor-threejs/kit/editor-shell-store';
|
|
54
54
|
import { GAME_SURFACE_CONTAINMENT_CSS } from '../host/game-realm-page';
|
|
55
55
|
import { reclaimGameRealm } from '../host/game-realm-reclaim';
|
|
56
|
-
import { toolContributionRecording } from '@volter/editor-
|
|
56
|
+
import { toolContributionRecording } from '@volter/editor-sdk/kit/gameplay-sessions';
|
|
57
57
|
import {
|
|
58
58
|
clearGameSurface,
|
|
59
59
|
currentGameRealmMountId,
|
|
@@ -64,18 +64,18 @@ import {
|
|
|
64
64
|
import { hierarchyProjectionFromProjectConfig } from '@volter/editor-sdk/kit/hierarchy-projection';
|
|
65
65
|
import { type JournalSubject, playJournal } from '../host/history/json-history-resource';
|
|
66
66
|
import { isEditableTarget, setActiveScope } from '@volter/editor-sdk/kit/hotkeys';
|
|
67
|
-
import { projectBootstrapSettled } from '@volter/editor-
|
|
68
|
-
import { registerGameNullSubject } from '@volter/editor-
|
|
69
|
-
import { fetchGameManifest } from '@volter/editor-
|
|
70
|
-
import { registerPerformanceSource } from '@volter/editor-
|
|
67
|
+
import { projectBootstrapSettled } from '@volter/editor-sdk/kit/initial-project';
|
|
68
|
+
import { registerGameNullSubject } from '@volter/editor-sdk/kit/inspection/game-subject';
|
|
69
|
+
import { fetchGameManifest } from '@volter/editor-sdk/kit/manifest-project';
|
|
70
|
+
import { registerPerformanceSource } from '@volter/editor-sdk/kit/performance-sources';
|
|
71
71
|
import {
|
|
72
72
|
beginPlayBoot,
|
|
73
73
|
endPlayBoot,
|
|
74
74
|
markPlayBootPhase,
|
|
75
75
|
type PlayBootPhase,
|
|
76
|
-
} from '@volter/editor-
|
|
76
|
+
} from '@volter/editor-sdk/kit/play-boot-phase';
|
|
77
77
|
import { presentationSurface } from '@volter/editor-sdk/kit/presentation-surface';
|
|
78
|
-
import { getCurrentProject } from '@volter/editor-
|
|
78
|
+
import { getCurrentProject } from '@volter/editor-sdk/kit/active-project';
|
|
79
79
|
import {
|
|
80
80
|
beginProjectModuleSplitWatch,
|
|
81
81
|
clearProjectModuleSplitReports,
|
|
@@ -83,31 +83,30 @@ import {
|
|
|
83
83
|
formatProjectModuleSplitMessage,
|
|
84
84
|
} from '@volter/editor-sdk/kit/project-module-split';
|
|
85
85
|
import { clearRootReadiness, recordRootReadiness } from '@volter/editor-sdk/kit/readiness';
|
|
86
|
-
import {
|
|
87
|
-
import { mountedStoryHasPixiContent } from '@volter/editor-core/stories/pixi-story-model';
|
|
86
|
+
import { mountedStoryHasPixiContent } from '../host/stories/pixi-story-model';
|
|
88
87
|
import { domHasRenderableContent, threeSceneHasRenderableContent } from '../host/surface-content';
|
|
89
|
-
import {
|
|
90
|
-
import { publishToolContributionPlay } from '@volter/editor-
|
|
88
|
+
import { surfaceHoldsKeyboard } from '@volter/editor-sdk/kit/surface-keyboard';
|
|
89
|
+
import { publishToolContributionPlay } from '@volter/editor-sdk/kit/tool-contribution-play';
|
|
91
90
|
import { liveWorldId, presentThreeRoots } from '../host/viewport-root-presentation';
|
|
92
91
|
import {
|
|
93
92
|
cancelPendingWorkspacePlayUtilities,
|
|
94
93
|
revealWorkspacePlayUtilities,
|
|
95
|
-
} from '@volter/editor-
|
|
94
|
+
} from '@volter/editor-sdk/kit/workspace-play-utilities';
|
|
96
95
|
import { markGameCssScope } from '@volter/editor-sdk/session/game-css-scope';
|
|
97
96
|
import type { EntrypointSelectionOverride } from '@volter/editor-sdk/session/project-module-url';
|
|
98
97
|
import { isEditorLanePath } from '@volter/editor-sdk/session/tool-contribution-convention';
|
|
99
|
-
import { getSeededRandom, type SeededRandom } from '
|
|
100
|
-
import { _engineLogActive } from '
|
|
101
|
-
import type { PerformanceProfiler } from '
|
|
102
|
-
import type { GameSession } from '
|
|
98
|
+
import { getSeededRandom, type SeededRandom } from '../runtime/core/seeded-random';
|
|
99
|
+
import { _engineLogActive } from '../runtime/dev/logger';
|
|
100
|
+
import type { PerformanceProfiler } from '../runtime/dev/performance-profiler';
|
|
101
|
+
import type { GameSession } from '../runtime/create-runtime';
|
|
103
102
|
import {
|
|
104
103
|
type DebugVirtualInputTarget,
|
|
105
104
|
getDebugRegistry,
|
|
106
105
|
type RunTicksOptions,
|
|
107
|
-
} from '
|
|
108
|
-
import type { GameLoop, RootInstance } from '
|
|
109
|
-
import type { PlaytestContext } from '
|
|
110
|
-
import { runTicksWhenSettled } from '
|
|
106
|
+
} from '../runtime/debug-registry';
|
|
107
|
+
import type { GameLoop, RootInstance } from '../runtime/game';
|
|
108
|
+
import type { PlaytestContext } from '../runtime/playtest';
|
|
109
|
+
import { runTicksWhenSettled } from '../runtime/run-ticks-settled';
|
|
111
110
|
import {
|
|
112
111
|
type AuthoringAdapter,
|
|
113
112
|
type InspectorProvider,
|
|
@@ -119,6 +118,7 @@ import { declaredRoots, rootById } from '@volter/editor-project/adapter/manifest
|
|
|
119
118
|
import { readOidSourceAnchors } from '../three/authoring/oid-source-persistence';
|
|
120
119
|
import { oidThree, structuralThree } from '../three/authoring/three-authoring-adapter';
|
|
121
120
|
import type * as THREE from 'three';
|
|
121
|
+
import { threeRoot } from '@volter/editor-threejs/adapter/three-contract';
|
|
122
122
|
import { deviceEmulatedPixelRatio } from '../game-document/device-preview';
|
|
123
123
|
import { exitDeferredIngestPlay, mountDeferredIngestForPlay } from '../ingest/deferred-ingest-play';
|
|
124
124
|
import { getIngestPlayControl } from '../ingest/ingest-play-control';
|
|
@@ -126,6 +126,8 @@ import { withPlayBootStallGuard } from './play-boot-stall';
|
|
|
126
126
|
import { debugEventsToLogEntries } from './play-log-events';
|
|
127
127
|
import { bindPlayRecordingStop, endPlayRecording } from './play-recording';
|
|
128
128
|
import { createReactPlayAuthoringAdapter } from './react-play-live-authoring';
|
|
129
|
+
import { onThreeStore } from '@volter/editor-threejs/kit/three-state';
|
|
130
|
+
import { presentViewportRoots } from '@volter/editor-threejs/viewport-door';
|
|
129
131
|
|
|
130
132
|
/** Context needed by the orchestrator (passed from the world root's stage). */
|
|
131
133
|
export interface PlayModeContext {
|
|
@@ -251,8 +253,8 @@ let _hostMountedReadyRootIds: readonly string[] = [];
|
|
|
251
253
|
// id) resolves to the primary, so the default — and the single-instance case —
|
|
252
254
|
// is "the primary has the keyboard", exactly as before split screen existed.
|
|
253
255
|
// A click on an instance's viewport routes the keyboard to it
|
|
254
|
-
// (`setFocusedInstance`);
|
|
255
|
-
//
|
|
256
|
+
// (`setFocusedInstance`); every instance's input gate reads this, so exactly
|
|
257
|
+
// the focused one is live and the rest are inert.
|
|
256
258
|
let _focusedInstanceId: string | null = null;
|
|
257
259
|
const focusListeners = new Set<() => void>();
|
|
258
260
|
|
|
@@ -293,7 +295,6 @@ export function setFocusedInstance(id: string): void {
|
|
|
293
295
|
setInspectedInstance(id);
|
|
294
296
|
if (focusedInstanceId() === id) return;
|
|
295
297
|
_focusedInstanceId = id;
|
|
296
|
-
resyncInstanceInputs();
|
|
297
298
|
notifyFocusedInstance();
|
|
298
299
|
}
|
|
299
300
|
|
|
@@ -301,59 +302,23 @@ export function setFocusedInstance(id: string): void {
|
|
|
301
302
|
* Game tab is active, this instance holds keyboard focus, AND our surface
|
|
302
303
|
* holds the keyboard.
|
|
303
304
|
*
|
|
304
|
-
* The fourth term is U2's
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
* without this a keystroke meant for the source file beside the running game
|
|
311
|
-
* moves the game too. Standalone it is a constant true and nothing changes.
|
|
312
|
-
* See `@editor/surface-keyboard`. */
|
|
305
|
+
* The fourth term is U2's: `gated-globals.ts` ANDs this predicate into every
|
|
306
|
+
* raw `window`/`document` listener a project module registers, and under the
|
|
307
|
+
* Code-OSS frame that window also carries Monaco, so without it a keystroke
|
|
308
|
+
* meant for the source file beside the running game moves the game too.
|
|
309
|
+
* Standalone it is a constant true and nothing changes. See
|
|
310
|
+
* `@editor/surface-keyboard`. */
|
|
313
311
|
function instanceInputActive(id: string): boolean {
|
|
314
312
|
if (!_ctx) return false;
|
|
315
313
|
const { store } = _ctx;
|
|
316
314
|
return (
|
|
317
|
-
store.playState === 'playing' &&
|
|
318
|
-
store.activeViewportTab === 'play' &&
|
|
315
|
+
store.shell.playState === 'playing' &&
|
|
316
|
+
store.shell.activeViewportTab === 'play' &&
|
|
319
317
|
focusedInstanceId() === id &&
|
|
320
318
|
surfaceHoldsKeyboard()
|
|
321
319
|
);
|
|
322
320
|
}
|
|
323
321
|
|
|
324
|
-
/** The first-party `InputManager` for an instance, or `undefined` — a session's
|
|
325
|
-
* game handle may lack one (an ingest mount, a partial double), so resolve it
|
|
326
|
-
* defensively. */
|
|
327
|
-
function instanceInput(inst: PlayInstance): { setEnabled(on: boolean): void } | undefined {
|
|
328
|
-
try {
|
|
329
|
-
return inst.session?.game?.input;
|
|
330
|
-
} catch {
|
|
331
|
-
return undefined;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** Re-apply the enabled/disabled state of every live instance's InputManager
|
|
336
|
-
* from the current play/tab/focus predicate. Called whenever any of those
|
|
337
|
-
* change (store subscription, focus switch, an instance mounting). The raw
|
|
338
|
-
* window/document gates are closures over `instanceInputActive`, so they need
|
|
339
|
-
* no re-registration — they re-read focus on every event. */
|
|
340
|
-
function resyncInstanceInputs(): void {
|
|
341
|
-
if (_instance.id) instanceInput(_instance)?.setEnabled(instanceInputActive(_instance.id));
|
|
342
|
-
for (const inst of _additional) instanceInput(inst)?.setEnabled(instanceInputActive(inst.id));
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* THE SURFACE TERM'S OWN EDGE. The store subscription re-gates on play/tab
|
|
347
|
-
* changes and `setFocusedInstance` on focus changes, but the fourth term above
|
|
348
|
-
* moves on neither: a person clicks into Monaco and nothing in the editor's own
|
|
349
|
-
* state has changed. `InputManager` is a LATCHED `setEnabled`, so unlike the
|
|
350
|
-
* raw gates (closures re-read per event) it has to be told. Module scope and
|
|
351
|
-
* never unsubscribed on purpose — the notification is a no-op with no instances
|
|
352
|
-
* mounted, and a lane-scoped subscription would have to be rebuilt on every
|
|
353
|
-
* mount for a predicate that is process-wide.
|
|
354
|
-
*/
|
|
355
|
-
subscribeSurfaceKeyboard(resyncInstanceInputs);
|
|
356
|
-
|
|
357
322
|
let _ctx: PlayModeContext | null = null;
|
|
358
323
|
const playModeBindingWaiters = new Set<() => void>();
|
|
359
324
|
|
|
@@ -513,7 +478,6 @@ export async function runWarmRestartPauseBracket(
|
|
|
513
478
|
if (!wasPaused) session.resume();
|
|
514
479
|
}
|
|
515
480
|
}
|
|
516
|
-
let _unsubStore: (() => void) | null = null;
|
|
517
481
|
/** Browser-mode component-source watch (Phase A2); null in server mode / stopped. */
|
|
518
482
|
/**
|
|
519
483
|
* The authoring override that was active before THIS play session installed its
|
|
@@ -658,7 +622,7 @@ async function installPlayRootAuthoring(
|
|
|
658
622
|
children.push({
|
|
659
623
|
worldId: world.id,
|
|
660
624
|
kind: world.kind,
|
|
661
|
-
adapter: new BoundaryAuthoringAdapter(store, {
|
|
625
|
+
adapter: new BoundaryAuthoringAdapter(store.shell, {
|
|
662
626
|
id: world.id,
|
|
663
627
|
kind: world.kind,
|
|
664
628
|
adapter: declaration.adapter.identity,
|
|
@@ -672,24 +636,25 @@ async function installPlayRootAuthoring(
|
|
|
672
636
|
}
|
|
673
637
|
const mounted = world.mounted;
|
|
674
638
|
if (mounted.kind === 'three') {
|
|
639
|
+
const scene = threeRoot(mounted).scene;
|
|
675
640
|
// The presented subject uses OID identity so Edit→Play selection stays
|
|
676
641
|
// continuous. A headless or non-Three host can omit presentation; its
|
|
677
642
|
// mounted tree still gets an honest structural live projection.
|
|
678
643
|
// `frameControl: 'host'` on the structural branch follows from the same
|
|
679
644
|
// tick-ownership fact: play's own loop drives the root and this adapter
|
|
680
645
|
// holds no handle that can stop it for a gesture.
|
|
681
|
-
const isPresentedSubject = world.id === presentedWorldId &&
|
|
646
|
+
const isPresentedSubject = world.id === presentedWorldId && scene === store.scene;
|
|
682
647
|
const sourceAnchor = isPresentedSubject ? await readOidSourceAnchors() : undefined;
|
|
683
648
|
if (!isCurrentGeneration()) {
|
|
684
649
|
abandon();
|
|
685
650
|
return;
|
|
686
651
|
}
|
|
687
652
|
const adapter = isPresentedSubject
|
|
688
|
-
? oidThree(store,
|
|
653
|
+
? oidThree(store, scene, liveWorldId(world.id), playRunJournal(world.id), {
|
|
689
654
|
explicitSourceCommit: true,
|
|
690
655
|
sourceAnchor,
|
|
691
656
|
})
|
|
692
|
-
: structuralThree(store,
|
|
657
|
+
: structuralThree(store, scene, {
|
|
693
658
|
frameControl: 'host',
|
|
694
659
|
journal: playRunJournal(world.id),
|
|
695
660
|
});
|
|
@@ -734,7 +699,7 @@ async function installPlayRootAuthoring(
|
|
|
734
699
|
}
|
|
735
700
|
if (mounted.substrate.name !== 'pixi') {
|
|
736
701
|
const adapter = new BoundaryAuthoringAdapter(
|
|
737
|
-
store,
|
|
702
|
+
store.shell,
|
|
738
703
|
{
|
|
739
704
|
id: world.id,
|
|
740
705
|
kind: world.kind,
|
|
@@ -752,8 +717,8 @@ async function installPlayRootAuthoring(
|
|
|
752
717
|
const stage = mounted.substrate.root as import('pixi.js').Container;
|
|
753
718
|
const [physicsRegistry, physicsAdapters, pixiAuthoring, pixiWriteTarget, canvasRuntime] =
|
|
754
719
|
await Promise.all([
|
|
755
|
-
import('
|
|
756
|
-
import('
|
|
720
|
+
import('../runtime/pixi/physics-registry'),
|
|
721
|
+
import('../runtime/pixi/system-adapters'),
|
|
757
722
|
import('../host/authoring/pixi-authoring-adapter'),
|
|
758
723
|
import('../host/authoring/pixi-live-write-target'),
|
|
759
724
|
import('../host/canvas-entry-runtime'),
|
|
@@ -827,7 +792,7 @@ async function installPlayRootAuthoring(
|
|
|
827
792
|
// the left hierarchy panel only re-checks `hasAuthoringOverride()` when the
|
|
828
793
|
// store notifies (same reason `ingest/mount-ingest-root.ts` calls this right after
|
|
829
794
|
// installing its own override).
|
|
830
|
-
store.notifyIngestEdit();
|
|
795
|
+
store.shell.notifyIngestEdit();
|
|
831
796
|
|
|
832
797
|
// Dev/e2e diagnostic handle — the SAME pattern `ingest/mount-ingest-root.ts`'s
|
|
833
798
|
// `window.__vgaiIngest`/`window.__vgaiIngest2D` use:
|
|
@@ -869,7 +834,7 @@ function exitPlayRootAuthoring(store: EditorShellStore): void {
|
|
|
869
834
|
// Play edits are session-local by architecture: nothing this run journaled
|
|
870
835
|
// may still be undoable once the run is over.
|
|
871
836
|
if (_instance.journalSession) {
|
|
872
|
-
store.projectHistory?.expireSession(_instance.journalSession);
|
|
837
|
+
store.shell.projectHistory?.expireSession(_instance.journalSession);
|
|
873
838
|
_instance.journalSession = '';
|
|
874
839
|
}
|
|
875
840
|
if (import.meta.env.DEV) {
|
|
@@ -1047,9 +1012,9 @@ export function bindPlayMode(store: EditorShellStore): void {
|
|
|
1047
1012
|
// game's, and what decides is the workbench: our stage actions carry a
|
|
1048
1013
|
// `when` clause over `vgai.stage.focused`/`vgai.play`, so a bare key reaches
|
|
1049
1014
|
// the game rather than a shell binding, and a ⌘-chord stays the workbench's.
|
|
1050
|
-
// The
|
|
1051
|
-
//
|
|
1052
|
-
//
|
|
1015
|
+
// The realm gate tracks the same predicate independently (`gated-globals.ts`
|
|
1016
|
+
// and `surface-keyboard.ts`), which is what keeps a game's raw
|
|
1017
|
+
// `window.addEventListener('keydown')` gated too.
|
|
1053
1018
|
// The idle auto-stop needs a way to end play without `play-recording.ts`
|
|
1054
1019
|
// importing the play lifecycle it is driven BY. Handed over here rather than
|
|
1055
1020
|
// at module scope so the two directions of the edge stay one-way.
|
|
@@ -1063,7 +1028,7 @@ export function isPlayModeActive(): boolean {
|
|
|
1063
1028
|
}
|
|
1064
1029
|
|
|
1065
1030
|
/**
|
|
1066
|
-
* Narrow relay accessor — the live play session's
|
|
1031
|
+
* Narrow relay accessor — the live play session's virtual input targets
|
|
1067
1032
|
* and the Game root's loop, for `command-listener.ts`'s
|
|
1068
1033
|
* `inject-input`/`set-time-scale`/`set-seed` cases. This is exactly the
|
|
1069
1034
|
* accessor the vgai-sdk honest-gap jsdocs prescribed
|
|
@@ -1073,13 +1038,7 @@ export function isPlayModeActive(): boolean {
|
|
|
1073
1038
|
* `setActiveSystems`/`getActiveSystems` instead.
|
|
1074
1039
|
*
|
|
1075
1040
|
* `getInputTarget(worldId?)` (D15/T-D15.5 — review objection 2's fix)
|
|
1076
|
-
*
|
|
1077
|
-
* `Game.input` always resolves to the DEFAULT world's `InputManager` only,
|
|
1078
|
-
* while the debug bridge's `window.__vgai.input.*` reached whichever world's
|
|
1079
|
-
* `InputManager` last called `DebugRegistry.setVirtualInputTarget` (a
|
|
1080
|
-
* SEPARATE, last-writer-wins slot). In a multi-world project those two could
|
|
1081
|
-
* name DIFFERENT roots — the exact closed-PR review objection. Now both
|
|
1082
|
-
* doors call the SAME `getDebugRegistry(game).getVirtualInputTarget(worldId)`
|
|
1041
|
+
* is one resolution for every input door: both the SAME `getDebugRegistry(game).getVirtualInputTarget(worldId)`
|
|
1083
1042
|
* — one resolution function (`debug-registry.ts`'s `resolveInputRootId`),
|
|
1084
1043
|
* so `inject-input` (this accessor) and `window.__vgai.input.*`
|
|
1085
1044
|
* (`debug-bridge.ts`) can never disagree about which world an unqualified
|
|
@@ -1135,7 +1094,7 @@ export function getPlayRuntimeAccess(): {
|
|
|
1135
1094
|
/** Get the running game's scene (for editor Scene tab rendering). */
|
|
1136
1095
|
export function getGameScene(): THREE.Scene | null {
|
|
1137
1096
|
const mounted = _instance.session?.game.defaultRoot.mounted;
|
|
1138
|
-
return mounted?.kind === 'three' ? mounted.scene : null;
|
|
1097
|
+
return mounted?.kind === 'three' ? threeRoot(mounted).scene : null;
|
|
1139
1098
|
}
|
|
1140
1099
|
|
|
1141
1100
|
export interface GameRootSurfaceFact {
|
|
@@ -1152,7 +1111,7 @@ export function gameRootSurfaceFacts(): readonly GameRootSurfaceFact[] {
|
|
|
1152
1111
|
const mounted = root.mounted;
|
|
1153
1112
|
let hasRenderableContent = false;
|
|
1154
1113
|
if (mounted.kind === 'three') {
|
|
1155
|
-
hasRenderableContent = threeSceneHasRenderableContent(mounted.scene);
|
|
1114
|
+
hasRenderableContent = threeSceneHasRenderableContent(threeRoot(mounted).scene);
|
|
1156
1115
|
} else if (mounted.kind === 'canvas') {
|
|
1157
1116
|
try {
|
|
1158
1117
|
hasRenderableContent =
|
|
@@ -1651,7 +1610,7 @@ async function enterPlayModeInner(
|
|
|
1651
1610
|
editorHost().viewport.transition.begin();
|
|
1652
1611
|
|
|
1653
1612
|
// setPlayState auto-switches to Game tab
|
|
1654
|
-
store.setPlayState('playing');
|
|
1613
|
+
store.shell.setPlayState('playing');
|
|
1655
1614
|
// THE GAME TAKES THE KEYBOARD AS PLAY STARTS. Until the player clicks the
|
|
1656
1615
|
// pane, focus stays on the transport button they pressed and the hotkey
|
|
1657
1616
|
// scope on the workspace — so the next Enter or Space activates that
|
|
@@ -1663,7 +1622,7 @@ async function enterPlayModeInner(
|
|
|
1663
1622
|
editorConsole.log('Play mode started', 'play-mode');
|
|
1664
1623
|
// Apply the project's adapter-declared utilities after transient Play chrome settles.
|
|
1665
1624
|
editorHost().viewport.transition.onSettled(() => {
|
|
1666
|
-
if (epoch === _playEpoch && store.playState === 'playing') revealWorkspacePlayUtilities();
|
|
1625
|
+
if (epoch === _playEpoch && store.shell.playState === 'playing') revealWorkspacePlayUtilities();
|
|
1667
1626
|
});
|
|
1668
1627
|
|
|
1669
1628
|
// WHAT THIS BOOT CREATED, BEFORE ANYTHING ELSE CAN REACH IT. `_instance.id`
|
|
@@ -1746,7 +1705,7 @@ async function enterPlayModeInner(
|
|
|
1746
1705
|
// MEASURED at N=20000: the block that ate three command budgets started
|
|
1747
1706
|
// here and ran for 199.5s with nothing anywhere able to name it.
|
|
1748
1707
|
markPlayBootPhase('mounting the runtime roots');
|
|
1749
|
-
const { mountManifestRoots } = await import('
|
|
1708
|
+
const { mountManifestRoots } = await import('../runtime/mount-manifest');
|
|
1750
1709
|
session = await mountManifestRoots({
|
|
1751
1710
|
manifest,
|
|
1752
1711
|
container: gameContainer,
|
|
@@ -1818,7 +1777,7 @@ async function enterPlayModeInner(
|
|
|
1818
1777
|
}
|
|
1819
1778
|
notifySessionListeners();
|
|
1820
1779
|
// D19: play edits are session-local regardless of world count.
|
|
1821
|
-
store.setPlayEditRegime('ephemeral');
|
|
1780
|
+
store.shell.setPlayEditRegime('ephemeral');
|
|
1822
1781
|
|
|
1823
1782
|
// Swap store to game scene so hierarchy/inspector show game entities.
|
|
1824
1783
|
// liveHierarchy: first-party play mode is the ONLY adoption path that may
|
|
@@ -1828,7 +1787,7 @@ async function enterPlayModeInner(
|
|
|
1828
1787
|
// are the whole layout), Play still adopts its roots, so the hierarchy door and every
|
|
1829
1788
|
// inspector reach the live objects exactly as they do beside a Scene tab.
|
|
1830
1789
|
_instance.presentation =
|
|
1831
|
-
|
|
1790
|
+
presentViewportRoots(session.game.roots) ??
|
|
1832
1791
|
presentThreeRoots(store, session.game.roots);
|
|
1833
1792
|
markPlayBootPhase('installing play authoring for each root');
|
|
1834
1793
|
await installPlayRootAuthoring(
|
|
@@ -1878,8 +1837,7 @@ async function enterPlayModeInner(
|
|
|
1878
1837
|
}) ?? null;
|
|
1879
1838
|
|
|
1880
1839
|
// T6.3: gate game input (raw `window`/`document` listeners in game code via
|
|
1881
|
-
// gated-globals
|
|
1882
|
-
// fire while play is actually running AND the Game tab is the focused
|
|
1840
|
+
// gated-globals) to only fire while play is actually running AND the Game tab is the focused
|
|
1883
1841
|
// viewport — so keystrokes typed into the editor (Scene tab, inspector
|
|
1884
1842
|
// fields) don't leak into the running game.
|
|
1885
1843
|
// The gate is FOCUS-AWARE (`instanceInputActive`): input flows only while
|
|
@@ -1892,19 +1850,10 @@ async function enterPlayModeInner(
|
|
|
1892
1850
|
// the modules find the default realm's gate instead of their own.
|
|
1893
1851
|
setGameInputGate(() => instanceInputActive(mountId), mountId);
|
|
1894
1852
|
// THE DEFAULT REALM follows the focused instance too. Module-lifetime code
|
|
1895
|
-
// that no mount id reaches lives there — a game's own
|
|
1896
|
-
//
|
|
1897
|
-
//
|
|
1898
|
-
// the game played still reached it.
|
|
1853
|
+
// that no mount id reaches lives there — a game's own input store,
|
|
1854
|
+
// attached at module load — and the stop path leaves it open, so a key
|
|
1855
|
+
// aimed at a Model document while the game played still reached it.
|
|
1899
1856
|
setGameInputGate(() => instanceInputActive(focusedInstanceId()));
|
|
1900
|
-
// Sync EVERY live instance's first-party InputManager from the play/tab/
|
|
1901
|
-
// focus predicate whenever the store changes (a tab switch flips the active
|
|
1902
|
-
// viewport for all of them). `resyncInstanceInputs` resolves each
|
|
1903
|
-
// instance's `game.input` defensively — a session whose game handle has no
|
|
1904
|
-
// first-party InputManager (an ingest mount, a partial double) has only the
|
|
1905
|
-
// raw window/document gate above.
|
|
1906
|
-
resyncInstanceInputs();
|
|
1907
|
-
_unsubStore = store.subscribe(resyncInstanceInputs);
|
|
1908
1857
|
|
|
1909
1858
|
// Node-id keyed only: `setEcsSyncTransform` hands this an editor node id
|
|
1910
1859
|
// and a THREE `Transform`, which a display-keyed carrier has no values for.
|
|
@@ -2019,7 +1968,7 @@ export async function mountAdditionalInstance(
|
|
|
2019
1968
|
}
|
|
2020
1969
|
markGameCssScope(container);
|
|
2021
1970
|
setGameSurface(container, mountId);
|
|
2022
|
-
const { mountManifestRoots } = await import('
|
|
1971
|
+
const { mountManifestRoots } = await import('../runtime/mount-manifest');
|
|
2023
1972
|
const session = await mountManifestRoots({
|
|
2024
1973
|
manifest,
|
|
2025
1974
|
container,
|
|
@@ -2070,15 +2019,12 @@ export async function mountAdditionalInstance(
|
|
|
2070
2019
|
}) ?? null;
|
|
2071
2020
|
// FOCUS-AWARE input, exactly like the primary: this instance takes the shared
|
|
2072
2021
|
// keyboard only while it holds focus. It mounts UNFOCUSED (the primary keeps
|
|
2073
|
-
// focus), so its gate is closed
|
|
2022
|
+
// focus), so its gate is closed until a click
|
|
2074
2023
|
// on its viewport routes focus here (`setFocusedInstance`). This is what stops
|
|
2075
2024
|
// the pre-focus bug where every seat took the same keystroke, AND what lets
|
|
2076
2025
|
// you drive a chosen seat manually rather than only via autoplay.
|
|
2077
2026
|
setGameInputGate(() => instanceInputActive(mountId), mountId);
|
|
2078
2027
|
_additional.push(inst);
|
|
2079
|
-
// Now that it is in `_additional`, sync its (and every) InputManager to the
|
|
2080
|
-
// current focus — disabled here, since the primary is focused.
|
|
2081
|
-
resyncInstanceInputs();
|
|
2082
2028
|
|
|
2083
2029
|
// `setActiveSystems` moved editor focus (`getActiveSystems`) onto the newer
|
|
2084
2030
|
// mount. The user is still authoring the PRIMARY, so restore its focus
|
|
@@ -2153,11 +2099,10 @@ export function unmountAdditionalInstance(id: string): void {
|
|
|
2153
2099
|
inst.container = null;
|
|
2154
2100
|
inst.session = null;
|
|
2155
2101
|
// If the removed instance held keyboard focus, focus falls back to the primary
|
|
2156
|
-
// (`focusedInstanceId` already resolves a stale id to it);
|
|
2157
|
-
//
|
|
2102
|
+
// (`focusedInstanceId` already resolves a stale id to it); notify the
|
|
2103
|
+
// viewport highlight.
|
|
2158
2104
|
if (_focusedInstanceId === id) {
|
|
2159
2105
|
_focusedInstanceId = null;
|
|
2160
|
-
resyncInstanceInputs();
|
|
2161
2106
|
notifyFocusedInstance();
|
|
2162
2107
|
}
|
|
2163
2108
|
notifySessionListeners();
|
|
@@ -2310,7 +2255,7 @@ export function exitPlayMode(): void {
|
|
|
2310
2255
|
exitPlayRootAuthoring(store);
|
|
2311
2256
|
restorePriorAuthoring();
|
|
2312
2257
|
// Readout-only — clear the regime the moment play is no longer active.
|
|
2313
|
-
store.setPlayEditRegime(null);
|
|
2258
|
+
store.shell.setPlayEditRegime(null);
|
|
2314
2259
|
|
|
2315
2260
|
// Always null _instance.session even if stop() throws — otherwise enterPlayMode's
|
|
2316
2261
|
// `if (_instance.session) return` guard would permanently block re-entering play mode.
|
|
@@ -2339,11 +2284,9 @@ export function exitPlayMode(): void {
|
|
|
2339
2284
|
_hostMountedReadyRootIds = [];
|
|
2340
2285
|
|
|
2341
2286
|
// Cleanup subscriptions
|
|
2342
|
-
_unsubStore?.();
|
|
2343
|
-
_unsubStore = null;
|
|
2344
2287
|
|
|
2345
|
-
// T6.3: no game running — game input (raw window/document listeners
|
|
2346
|
-
//
|
|
2288
|
+
// T6.3: no game running — game input (raw window/document listeners) should
|
|
2289
|
+
// never be suppressed again until the next
|
|
2347
2290
|
// play session re-gates it. The mount's own gate is DROPPED rather than set
|
|
2348
2291
|
// to always-true: its id is never reused, so overwriting would retain one
|
|
2349
2292
|
// dead closure per play run.
|
|
@@ -2392,7 +2335,7 @@ export function exitPlayMode(): void {
|
|
|
2392
2335
|
// that FAILED before ever flipping the store to 'playing' never produces
|
|
2393
2336
|
// that edge, so release directly too — `releaseGameDocument` is the one
|
|
2394
2337
|
// idempotent teardown path either way (`game-document.ts`).
|
|
2395
|
-
store.setPlayState('stopped');
|
|
2338
|
+
store.shell.setPlayState('stopped');
|
|
2396
2339
|
editorHost().workspace.liveDocument.release();
|
|
2397
2340
|
// LAST — the run's error window closes only once teardown is done, so every
|
|
2398
2341
|
// error this teardown itself logged still belongs to the run that caused it
|
|
@@ -2417,7 +2360,7 @@ export function pausePlayMode(): void {
|
|
|
2417
2360
|
// Freeze EVERY seat, not just the primary — a paused split with the extras
|
|
2418
2361
|
// still ticking is not paused.
|
|
2419
2362
|
for (const inst of allLiveInstances()) inst.session?.pause();
|
|
2420
|
-
_ctx.store.setPlayState('paused');
|
|
2363
|
+
_ctx.store.shell.setPlayState('paused');
|
|
2421
2364
|
|
|
2422
2365
|
editorConsole.log('Play mode paused', 'play-mode');
|
|
2423
2366
|
}
|
|
@@ -2429,7 +2372,7 @@ export function resumePlayMode(): void {
|
|
|
2429
2372
|
if (!_instance.session || !_ctx) return;
|
|
2430
2373
|
|
|
2431
2374
|
for (const inst of allLiveInstances()) inst.session?.resume();
|
|
2432
|
-
_ctx.store.setPlayState('playing');
|
|
2375
|
+
_ctx.store.shell.setPlayState('playing');
|
|
2433
2376
|
|
|
2434
2377
|
editorConsole.log('Play mode resumed', 'play-mode');
|
|
2435
2378
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* recorder's stream never sees, so nothing about the evidence changes.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
-
import { isRootCanvas } from '@volter/editor-
|
|
40
|
+
import { isRootCanvas } from '@volter/editor-sdk/kit/composite-screenshot';
|
|
41
41
|
import { editorConsole } from '@volter/editor-sdk/kit/editor-console';
|
|
42
42
|
import {
|
|
43
43
|
type GameplayRecordingCapture,
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
* three gizmo drag during play. That is the regime, not a defect.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
-
import type { EditorShellStore } from '@volter/editor-
|
|
48
|
-
import type { SourceWriteBackend } from '@volter/editor-
|
|
47
|
+
import type { EditorShellStore } from '@volter/editor-threejs/kit/editor-shell-store';
|
|
48
|
+
import type { SourceWriteBackend } from '@volter/editor-sdk/kit/ui-source/source-write-backend';
|
|
49
49
|
import {
|
|
50
50
|
type OidElementLike,
|
|
51
51
|
ReactRootAuthoringAdapter,
|
|
@@ -158,7 +158,7 @@ export function createReactPlayAuthoringAdapter(
|
|
|
158
158
|
root: OidElementLike,
|
|
159
159
|
store: EditorShellStore,
|
|
160
160
|
): ReactRootAuthoringAdapter {
|
|
161
|
-
return new ReactRootAuthoringAdapter(root, store, {
|
|
161
|
+
return new ReactRootAuthoringAdapter(root, store.shell, {
|
|
162
162
|
writeBackend: createEphemeralDomWriteBackend(root),
|
|
163
163
|
provenance: EPHEMERAL_DOM_PROVENANCE,
|
|
164
164
|
});
|