Add Chromium-only Blender WebEngine parity work
This commit is contained in:
129
web/protocol/ui-schema.ts
Normal file
129
web/protocol/ui-schema.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
export type WorkspaceId = "Layout" | "Modeling" | "Animation";
|
||||
export type EditorType = "3D Viewport" | "Outliner" | "Properties" | "Timeline";
|
||||
export type BlenderMode = "Object" | "Edit" | "Pose";
|
||||
|
||||
export interface RegionIR {
|
||||
id: string;
|
||||
kind: "header" | "main" | "toolbar" | "sidebar" | "footer";
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface AreaIR {
|
||||
id: string;
|
||||
editor: EditorType;
|
||||
regions: RegionIR[];
|
||||
rect: { x: number; y: number; width: number; height: number };
|
||||
maximized: boolean;
|
||||
}
|
||||
|
||||
export interface WorkspaceIR {
|
||||
id: WorkspaceId;
|
||||
name: string;
|
||||
areas: AreaIR[];
|
||||
activeAreaId: string;
|
||||
revision: number;
|
||||
}
|
||||
|
||||
export interface UIContextIR {
|
||||
workspaceId: WorkspaceId;
|
||||
activeAreaId: string;
|
||||
activeEditor: EditorType;
|
||||
mode: BlenderMode;
|
||||
activeObjectId: string | null;
|
||||
selection: string[];
|
||||
viewLayer: string;
|
||||
pinnedData: string | null;
|
||||
revision: number;
|
||||
}
|
||||
|
||||
export interface WebWorkspaceState {
|
||||
workspaces: Record<WorkspaceId, WorkspaceIR>;
|
||||
context: UIContextIR;
|
||||
operatorSearchOpen: boolean;
|
||||
sidebarVisible: boolean;
|
||||
}
|
||||
|
||||
export type UICommand =
|
||||
| { type: "switchWorkspace"; workspaceId: WorkspaceId }
|
||||
| { type: "setMode"; mode: BlenderMode }
|
||||
| { type: "setActiveArea"; areaId: string }
|
||||
| { type: "toggleOperatorSearch"; open?: boolean }
|
||||
| { type: "toggleSidebar"; visible?: boolean };
|
||||
|
||||
function regions(): RegionIR[] {
|
||||
return [
|
||||
{ id: "header", kind: "header", visible: true },
|
||||
{ id: "main", kind: "main", visible: true },
|
||||
{ id: "toolbar", kind: "toolbar", visible: true },
|
||||
{ id: "sidebar", kind: "sidebar", visible: true },
|
||||
];
|
||||
}
|
||||
|
||||
function layoutAreas(): AreaIR[] {
|
||||
return [
|
||||
{ id: "viewport", editor: "3D Viewport", regions: regions(), rect: { x: 0, y: 0, width: 0.8, height: 0.78 }, maximized: false },
|
||||
{ id: "outliner", editor: "Outliner", regions: regions(), rect: { x: 0.8, y: 0, width: 0.2, height: 0.42 }, maximized: false },
|
||||
{ id: "properties", editor: "Properties", regions: regions(), rect: { x: 0.8, y: 0.42, width: 0.2, height: 0.36 }, maximized: false },
|
||||
{ id: "timeline", editor: "Timeline", regions: regions(), rect: { x: 0, y: 0.78, width: 1, height: 0.22 }, maximized: false },
|
||||
];
|
||||
}
|
||||
|
||||
function workspace(id: WorkspaceId): WorkspaceIR {
|
||||
return { id, name: id, areas: layoutAreas(), activeAreaId: "viewport", revision: 0 };
|
||||
}
|
||||
|
||||
export function createDefaultWebWorkspaceState(): WebWorkspaceState {
|
||||
const workspaces = {
|
||||
Layout: workspace("Layout"),
|
||||
Modeling: workspace("Modeling"),
|
||||
Animation: workspace("Animation"),
|
||||
} satisfies Record<WorkspaceId, WorkspaceIR>;
|
||||
return {
|
||||
workspaces,
|
||||
context: {
|
||||
workspaceId: "Layout",
|
||||
activeAreaId: "viewport",
|
||||
activeEditor: "3D Viewport",
|
||||
mode: "Object",
|
||||
activeObjectId: "BasicCube",
|
||||
selection: ["BasicCube"],
|
||||
viewLayer: "ViewLayer",
|
||||
pinnedData: null,
|
||||
revision: 0,
|
||||
},
|
||||
operatorSearchOpen: false,
|
||||
sidebarVisible: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function reduceUICommand(state: WebWorkspaceState, command: UICommand): WebWorkspaceState {
|
||||
switch (command.type) {
|
||||
case "switchWorkspace": {
|
||||
const next = state.workspaces[command.workspaceId];
|
||||
return {
|
||||
...state,
|
||||
context: {
|
||||
...state.context,
|
||||
workspaceId: command.workspaceId,
|
||||
activeAreaId: next.activeAreaId,
|
||||
activeEditor: next.areas.find((area) => area.id === next.activeAreaId)?.editor ?? "3D Viewport",
|
||||
revision: state.context.revision + 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
case "setMode":
|
||||
return { ...state, context: { ...state.context, mode: command.mode, revision: state.context.revision + 1 } };
|
||||
case "setActiveArea": {
|
||||
const active = state.workspaces[state.context.workspaceId].areas.find((area) => area.id === command.areaId);
|
||||
if (!active) return state;
|
||||
return {
|
||||
...state,
|
||||
context: { ...state.context, activeAreaId: active.id, activeEditor: active.editor, revision: state.context.revision + 1 },
|
||||
};
|
||||
}
|
||||
case "toggleOperatorSearch":
|
||||
return { ...state, operatorSearchOpen: command.open ?? !state.operatorSearchOpen };
|
||||
case "toggleSidebar":
|
||||
return { ...state, sidebarVisible: command.visible ?? !state.sidebarVisible };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user