Enhance editor store with viewport layout state management

This commit is contained in:
2026-04-03 01:36:16 +02:00
parent a6f8e43c9f
commit d32129edfc

View File

@@ -22,11 +22,16 @@ import {
type ViewportTransientState
} from "../viewport-three/viewport-transient-state";
import {
areViewportPanelCameraStatesEqual,
cloneViewportLayoutState,
cloneViewportPanelCameraState,
createDefaultViewportLayoutState,
type ViewportDisplayMode,
type ViewportLayoutState,
type ViewportLayoutMode,
type ViewportPanelId,
type ViewportPanelState,
type ViewportPanelCameraState,
type ViewportQuadSplit
} from "../viewport-three/viewport-layout";
@@ -47,6 +52,7 @@ export interface EditorStoreState {
interface EditorStoreOptions {
initialDocument?: SceneDocument;
initialViewportLayoutState?: ViewportLayoutState;
storage?: KeyValueStorage | null;
storageKey?: string;
}
@@ -60,10 +66,10 @@ export class EditorStore {
private document: SceneDocument;
private selection: EditorSelection = { kind: "none" };
private toolMode: ToolMode = "select";
private viewportLayoutMode: ViewportLayoutMode = "single";
private activeViewportPanelId: ViewportPanelId = "topLeft";
private viewportPanels = createDefaultViewportLayoutState().panels;
private viewportQuadSplit = createDefaultViewportLayoutState().viewportQuadSplit;
private viewportLayoutMode: ViewportLayoutMode;
private activeViewportPanelId: ViewportPanelId;
private viewportPanels: Record<ViewportPanelId, ViewportPanelState>;
private viewportQuadSplit: ViewportQuadSplit;
private viewportTransientState = createDefaultViewportTransientState();
private previousEditingToolMode: Exclude<ToolMode, "play"> = "select";
private readonly history = new CommandHistory();
@@ -89,7 +95,13 @@ export class EditorStore {
};
constructor(options: EditorStoreOptions = {}) {
const initialViewportLayoutState = cloneViewportLayoutState(options.initialViewportLayoutState ?? createDefaultViewportLayoutState());
this.document = options.initialDocument ?? createEmptySceneDocument();
this.viewportLayoutMode = initialViewportLayoutState.layoutMode;
this.activeViewportPanelId = initialViewportLayoutState.activePanelId;
this.viewportPanels = initialViewportLayoutState.panels;
this.viewportQuadSplit = initialViewportLayoutState.viewportQuadSplit;
this.storage = options.storage ?? null;
this.storageKey = options.storageKey ?? DEFAULT_SCENE_DRAFT_STORAGE_KEY;
this.snapshot = this.createSnapshot();
@@ -171,6 +183,21 @@ export class EditorStore {
this.emit();
}
setViewportPanelCameraState(panelId: ViewportPanelId, cameraState: ViewportPanelCameraState) {
if (areViewportPanelCameraStatesEqual(this.viewportPanels[panelId].cameraState, cameraState)) {
return;
}
this.viewportPanels = {
...this.viewportPanels,
[panelId]: {
...this.viewportPanels[panelId],
cameraState: cloneViewportPanelCameraState(cameraState)
}
};
this.emit();
}
setViewportQuadSplit(viewportQuadSplit: ViewportQuadSplit) {
if (this.viewportQuadSplit.x === viewportQuadSplit.x && this.viewportQuadSplit.y === viewportQuadSplit.y) {
return;
@@ -298,7 +325,7 @@ export class EditorStore {
};
}
return saveSceneDocumentDraft(this.storage, this.document, this.storageKey);
return saveSceneDocumentDraft(this.storage, this.document, this.createViewportLayoutState(), this.storageKey);
}
loadDraft(): EditorDraftLoadResult {
@@ -316,6 +343,11 @@ export class EditorStore {
}
this.replaceDocument(draftResult.document);
if (draftResult.viewportLayoutState !== null) {
this.applyViewportLayoutState(draftResult.viewportLayoutState);
}
return draftResult;
}
@@ -337,6 +369,24 @@ export class EditorStore {
}
}
private createViewportLayoutState(): ViewportLayoutState {
return cloneViewportLayoutState({
layoutMode: this.viewportLayoutMode,
activePanelId: this.activeViewportPanelId,
panels: this.viewportPanels,
viewportQuadSplit: this.viewportQuadSplit
});
}
private applyViewportLayoutState(viewportLayoutState: ViewportLayoutState) {
const nextViewportLayoutState = cloneViewportLayoutState(viewportLayoutState);
this.viewportLayoutMode = nextViewportLayoutState.layoutMode;
this.activeViewportPanelId = nextViewportLayoutState.activePanelId;
this.viewportPanels = nextViewportLayoutState.panels;
this.viewportQuadSplit = nextViewportLayoutState.viewportQuadSplit;
}
private createSnapshot(): EditorStoreState {
return {
document: this.document,