diff --git a/src/components/MenuView.scss b/src/components/MenuView.scss index 1533bcd..02a9327 100644 --- a/src/components/MenuView.scss +++ b/src/components/MenuView.scss @@ -1,6 +1,6 @@ .menu { user-select: none; - font-size: 13px; + font-size: 16px; & details { &>summary { @@ -12,6 +12,7 @@ display: flex; padding: 8px 8px; + gap: 8px; cursor: pointer; border-radius: 4px; white-space: nowrap; @@ -28,15 +29,22 @@ background: rgba(255, 255, 255, 0.15); color: #fff; } - + &>.title { flex: 1; + overflow-x: hidden; + text-overflow: ellipsis; + } + + &>.actions { + display: flex; + gap: 8px; } & svg { vertical-align: middle; margin: 2px; - + box-sizing: border-box; } } diff --git a/src/components/ObjectEditorView.tsx b/src/components/ObjectEditorView.tsx index 9905033..dcd50d4 100644 --- a/src/components/ObjectEditorView.tsx +++ b/src/components/ObjectEditorView.tsx @@ -4,7 +4,6 @@ import { useMemo, useRef, type RefObject } from "react"; import type { Group } from "three"; import { TransformControls, useHelper } from "@react-three/drei"; import { BoxHelper } from "three"; -import type { ThreeEvent } from "@react-three/fiber"; import { state } from "../state"; import { nextObjectEditMode } from "../state/worldEditorState"; import { ObjectViewInternal, type ObjectViewInternalHandle } from "./ObjectViewInternal"; diff --git a/src/state/menuState.tsx b/src/state/menuState.tsx index 7606f85..44bcda7 100644 --- a/src/state/menuState.tsx +++ b/src/state/menuState.tsx @@ -1,7 +1,7 @@ import { makeAutoObservable } from "mobx"; import { state } from "./rootState"; import type { ReactNode } from "react"; -import { IconRun } from '@tabler/icons-react'; +import { IconRun, IconTrash, IconCubePlus, IconPlus } from '@tabler/icons-react'; export type MenuNodeAction = { id: string; @@ -26,27 +26,43 @@ export class MenuState { } private get editorObjectTypesMenu(): MenuNode[] { - const scene = state.worldEditor.scene; + const editor = state.worldEditor; + const scene = editor.scene; return Object.values(state.world.data.objectTypes) .map((ot) => ({ id: `ot-${ot.id}`, title: ot.name, - onClick: () => { state.worldEditor.setSelectedObjectType({ id: ot.id, editMode: 'scripts' }) }, - selected: () => state.worldEditor.selection?.type === 'objectType' && state.worldEditor.selection?.id === ot.id, + actions: [ + { + id: 'create-instance', + content: , + tooltip: 'Create new object instance', + onClick: () => { editor.addObjectInstanceAtRandomPosition(ot.id); }, + }, + ], + onClick: () => { editor.setSelectedObjectType({ id: ot.id, editMode: 'scripts' }) }, + selected: () => editor.selection?.type === 'objectType' && editor.selection?.id === ot.id, children: Object.values(scene.objects) .filter((o) => o.typeId === ot.id) .map((o) => { const isPlayer = scene.playerObjectId === o.id; const actions: MenuNodeAction[] = []; - if (!isPlayer) + if (!isPlayer) { + actions.push({ + id: 'delete', + content: , + tooltip: 'Delete the object', + onClick: () => { editor.deleteObject(o.id); }, + }); actions.push({ id: 'control-by-player', content: , tooltip: 'Mark as player', - onClick: () => { state.markObjectAsPlayer(o); }, + onClick: () => { scene.playerObjectId = o.id; }, }); + } return { id: `o-${o.id}`, diff --git a/src/state/worldEditorState.ts b/src/state/worldEditorState.ts index a67f621..e4d0ba0 100644 --- a/src/state/worldEditorState.ts +++ b/src/state/worldEditorState.ts @@ -116,14 +116,14 @@ export class WorldEditorState { }); } - public addObjectCloneAtRandomPosition(typeId: string): ObjectInstance { - return this.addObjectClone( + public addObjectInstanceAtRandomPosition(typeId: string): ObjectInstance { + return this.addObjectInstance( typeId, { x: Math.random() * 3, y: Math.random() * 3, z: Math.random() * 1 }, ); } - public addObjectClone( + public addObjectInstance( typeId: string, pos: { x: number; y: number; z: number; }, ): ObjectInstance { @@ -133,7 +133,15 @@ export class WorldEditorState { this.scene.objects[obj.id] = obj; + this.setSelectedObject({ id: obj.id, editMode: 'translate' }); + return obj; } + + public deleteObject(objectId: string) { + if (this.selection?.type ==='object' && this.selection.id === objectId) + this.resetSelection(); + delete (this.scene.objects[objectId]); + } }