object instance creation and deletion

This commit is contained in:
azykov@mail.ru 2026-06-05 22:10:14 +03:00
parent 93e127b2f7
commit dee28ba5b2
No known key found for this signature in database
4 changed files with 44 additions and 13 deletions

View File

@ -1,6 +1,6 @@
.menu { .menu {
user-select: none; user-select: none;
font-size: 13px; font-size: 16px;
& details { & details {
&>summary { &>summary {
@ -12,6 +12,7 @@
display: flex; display: flex;
padding: 8px 8px; padding: 8px 8px;
gap: 8px;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
white-space: nowrap; white-space: nowrap;
@ -31,6 +32,13 @@
&>.title { &>.title {
flex: 1; flex: 1;
overflow-x: hidden;
text-overflow: ellipsis;
}
&>.actions {
display: flex;
gap: 8px;
} }
& svg { & svg {

View File

@ -4,7 +4,6 @@ import { useMemo, useRef, type RefObject } from "react";
import type { Group } from "three"; import type { Group } from "three";
import { TransformControls, useHelper } from "@react-three/drei"; import { TransformControls, useHelper } from "@react-three/drei";
import { BoxHelper } from "three"; import { BoxHelper } from "three";
import type { ThreeEvent } from "@react-three/fiber";
import { state } from "../state"; import { state } from "../state";
import { nextObjectEditMode } from "../state/worldEditorState"; import { nextObjectEditMode } from "../state/worldEditorState";
import { ObjectViewInternal, type ObjectViewInternalHandle } from "./ObjectViewInternal"; import { ObjectViewInternal, type ObjectViewInternalHandle } from "./ObjectViewInternal";

View File

@ -1,7 +1,7 @@
import { makeAutoObservable } from "mobx"; import { makeAutoObservable } from "mobx";
import { state } from "./rootState"; import { state } from "./rootState";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { IconRun } from '@tabler/icons-react'; import { IconRun, IconTrash, IconCubePlus, IconPlus } from '@tabler/icons-react';
export type MenuNodeAction = { export type MenuNodeAction = {
id: string; id: string;
@ -26,27 +26,43 @@ export class MenuState {
} }
private get editorObjectTypesMenu(): MenuNode[] { private get editorObjectTypesMenu(): MenuNode[] {
const scene = state.worldEditor.scene; const editor = state.worldEditor;
const scene = editor.scene;
return Object.values(state.world.data.objectTypes) return Object.values(state.world.data.objectTypes)
.map((ot) => ({ .map((ot) => ({
id: `ot-${ot.id}`, id: `ot-${ot.id}`,
title: ot.name, title: ot.name,
onClick: () => { state.worldEditor.setSelectedObjectType({ id: ot.id, editMode: 'scripts' }) }, actions: [
selected: () => state.worldEditor.selection?.type === 'objectType' && state.worldEditor.selection?.id === ot.id, {
id: 'create-instance',
content: <IconPlus size="1em" />,
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) children: Object.values(scene.objects)
.filter((o) => o.typeId === ot.id) .filter((o) => o.typeId === ot.id)
.map((o) => { .map((o) => {
const isPlayer = scene.playerObjectId === o.id; const isPlayer = scene.playerObjectId === o.id;
const actions: MenuNodeAction[] = []; const actions: MenuNodeAction[] = [];
if (!isPlayer) if (!isPlayer) {
actions.push({
id: 'delete',
content: <IconTrash size="1em" />,
tooltip: 'Delete the object',
onClick: () => { editor.deleteObject(o.id); },
});
actions.push({ actions.push({
id: 'control-by-player', id: 'control-by-player',
content: <IconRun size="1em" />, content: <IconRun size="1em" />,
tooltip: 'Mark as player', tooltip: 'Mark as player',
onClick: () => { state.markObjectAsPlayer(o); }, onClick: () => { scene.playerObjectId = o.id; },
}); });
}
return { return {
id: `o-${o.id}`, id: `o-${o.id}`,

View File

@ -116,14 +116,14 @@ export class WorldEditorState {
}); });
} }
public addObjectCloneAtRandomPosition(typeId: string): ObjectInstance { public addObjectInstanceAtRandomPosition(typeId: string): ObjectInstance {
return this.addObjectClone( return this.addObjectInstance(
typeId, typeId,
{ x: Math.random() * 3, y: Math.random() * 3, z: Math.random() * 1 }, { x: Math.random() * 3, y: Math.random() * 3, z: Math.random() * 1 },
); );
} }
public addObjectClone( public addObjectInstance(
typeId: string, typeId: string,
pos: { x: number; y: number; z: number; }, pos: { x: number; y: number; z: number; },
): ObjectInstance { ): ObjectInstance {
@ -133,7 +133,15 @@ export class WorldEditorState {
this.scene.objects[obj.id] = obj; this.scene.objects[obj.id] = obj;
this.setSelectedObject({ id: obj.id, editMode: 'translate' });
return obj; return obj;
} }
public deleteObject(objectId: string) {
if (this.selection?.type ==='object' && this.selection.id === objectId)
this.resetSelection();
delete (this.scene.objects[objectId]);
}
} }