workspaces folders
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { state } from "./rootState";
|
||||
import type { ReactNode } from "react";
|
||||
import { IconRun, IconTrash, IconPlus, IconCubePlus, IconCubeOff, IconEdit } from '@tabler/icons-react';
|
||||
|
||||
export type MenuNodeAction = {
|
||||
id: string;
|
||||
content: ReactNode;
|
||||
tooltip: string;
|
||||
onClick?: () => void;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
export type MenuNode = {
|
||||
id: string;
|
||||
title: ReactNode;
|
||||
className?: string;
|
||||
actions?: MenuNodeAction[];
|
||||
onClick?: () => void;
|
||||
selected?: () => boolean;
|
||||
children?: MenuNode[];
|
||||
}
|
||||
|
||||
export class MenuState {
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
private get editorObjectTypesMenu(): MenuNode[] {
|
||||
const editor = state.worldEditor;
|
||||
const scene = editor.scene;
|
||||
|
||||
return Object.values(state.world.data.objectTypes)
|
||||
.map((ot) => {
|
||||
const children = Object.values(scene.objects)
|
||||
.filter((o) => o.typeId === ot.id)
|
||||
.map((o, idx) => {
|
||||
const isPlayer = scene.playerObjectId === o.id;
|
||||
|
||||
const actions: MenuNodeAction[] = [];
|
||||
if (!isPlayer) {
|
||||
actions.push({
|
||||
id: 'delete-object-instance',
|
||||
content: <IconTrash size="1em" />,
|
||||
tooltip: 'Delete the object',
|
||||
onClick: () => { editor.deleteObject(o.id); },
|
||||
});
|
||||
actions.push({
|
||||
id: 'control-object-instance-by-player',
|
||||
content: <IconRun size="1em" />,
|
||||
tooltip: 'Mark as player',
|
||||
onClick: () => { scene.playerObjectId = o.id; },
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
id: `o-${o.id}`,
|
||||
title: <>
|
||||
{isPlayer && <IconRun size="1em" />}
|
||||
{`${ot.name} ${idx + 1}`}
|
||||
</>,
|
||||
className: isPlayer ? 'player-controlled-object' : undefined,
|
||||
actions,
|
||||
onClick: () => { state.worldEditor.setSelectedObject({ id: o.id, editMode: 'translate' }); },
|
||||
selected: () => state.worldEditor.selection?.type === 'object' && state.worldEditor.selection?.id === o.id,
|
||||
} as MenuNode;
|
||||
});
|
||||
|
||||
return {
|
||||
id: `ot-${ot.id}`,
|
||||
title: `${ot.name} (${children.length ? children.length : 'no'} instance${children.length != 1 ? 's' : ''})`,
|
||||
actions: [
|
||||
{
|
||||
id: 'create-object-instance',
|
||||
content: <IconPlus size="1em" />,
|
||||
tooltip: 'Create new object instance',
|
||||
onClick: () => { editor.addObjectInstanceAtRandomPosition(ot.id); },
|
||||
},
|
||||
{
|
||||
id: 'edit-object-type-voxels',
|
||||
content: <IconEdit size="1em" />,
|
||||
tooltip: 'Edit object type voxels',
|
||||
link: `/editor/objectType/${ot.id}/voxels`,
|
||||
},
|
||||
{
|
||||
id: 'delete-object-type',
|
||||
content: <IconCubeOff size="1em" />,
|
||||
tooltip: 'Delete object type',
|
||||
onClick: () => { editor.deleteObjectType(ot.id); },
|
||||
},
|
||||
],
|
||||
onClick: () => { editor.setSelectedObjectType({ id: ot.id, editMode: 'scripts' }); },
|
||||
selected: () => editor.selection?.type === 'objectType' && editor.selection?.id === ot.id,
|
||||
children,
|
||||
} as MenuNode;
|
||||
});
|
||||
}
|
||||
|
||||
private get editorMenu(): MenuNode[] {
|
||||
return [
|
||||
{
|
||||
id: 'editor-scene-menu',
|
||||
title: 'Scene',
|
||||
onClick: () => { state.worldEditor.resetSelection(); },
|
||||
selected: () => !state.worldEditor.selection,
|
||||
children: this.editorObjectTypesMenu,
|
||||
actions: [{
|
||||
id: 'create-object-type',
|
||||
content: <IconCubePlus size="1em" />,
|
||||
tooltip: 'Create new object type',
|
||||
onClick: () => { state.worldEditor.addObjectType(); },
|
||||
}],
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public get nodes(): MenuNode[] {
|
||||
return [
|
||||
...this.editorMenu,
|
||||
];
|
||||
}
|
||||
|
||||
public nodeContainsSelected(node: MenuNode): boolean {
|
||||
return !!(node.selected?.() || node.children?.some((child) => this.nodeContainsSelected(child)));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user