95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
import { makeAutoObservable, runInAction } from "mobx";
|
|
import type { WorldState } from "./worldState";
|
|
import { type ObjectInstance, type Pos3, type R3, type V3, type RuntimeScene } from "../types";
|
|
import { createObjectInstance } from "../utils/object";
|
|
import { randomId } from "../utils";
|
|
import { state } from "./rootState";
|
|
import { populateRuntimeObject } from "../utils/runtime";
|
|
|
|
export const SelectionEditModeEnum = [
|
|
'translate',
|
|
'rotate',
|
|
'scale',
|
|
] as const;
|
|
type SelectionEditModeTuple = typeof SelectionEditModeEnum;
|
|
export type SelectionEditMode = SelectionEditModeTuple[number];
|
|
|
|
export function nextSelectionEditMode(mode: SelectionEditMode | undefined): SelectionEditMode {
|
|
if (mode === undefined)
|
|
return 'translate';
|
|
|
|
const idx = SelectionEditModeEnum.indexOf(mode);
|
|
return SelectionEditModeEnum[(idx + 1) % SelectionEditModeEnum.length];
|
|
}
|
|
|
|
export class WorldEditorState {
|
|
private readonly world: WorldState;
|
|
|
|
public selectedObjectId: string | undefined;
|
|
public selectedObjectMode: SelectionEditMode | undefined;
|
|
|
|
constructor(world: WorldState) {
|
|
this.world = world;
|
|
makeAutoObservable(this);
|
|
}
|
|
|
|
public get isEnabled(): boolean {
|
|
return !state.isGamePlaying;
|
|
}
|
|
|
|
public setCamera(value: Pos3): void {
|
|
this.world.data.editorCamera = value;
|
|
}
|
|
|
|
public setSelectedObject(id: string, mode: SelectionEditMode): void {
|
|
this.selectedObjectId = id;
|
|
this.selectedObjectMode = mode;
|
|
}
|
|
|
|
public resetSelectedObject(): void {
|
|
this.selectedObjectId = undefined;
|
|
this.selectedObjectMode = undefined;
|
|
}
|
|
|
|
public get scene(): RuntimeScene {
|
|
return this.world.data.initialScene;
|
|
}
|
|
|
|
public get camera(): Pos3 {
|
|
return this.world.data.editorCamera;
|
|
}
|
|
|
|
public setObjectTransform(id: string, position: V3, rotation: R3, scale: V3): void {
|
|
const obj = this.scene.objects[id];
|
|
if (!obj)
|
|
return;
|
|
|
|
runInAction(() => { // all in one go
|
|
obj.position = position;
|
|
obj.rotation = rotation;
|
|
obj.scale = scale;
|
|
});
|
|
}
|
|
|
|
public addObjectCloneAtRandomPosition(typeId: string): ObjectInstance {
|
|
return this.addObjectClone(
|
|
typeId,
|
|
{ x: Math.random() * 3, y: Math.random() * 3, z: Math.random() * 1 },
|
|
);
|
|
}
|
|
|
|
public addObjectClone(
|
|
typeId: string,
|
|
pos: { x: number; y: number; z: number; },
|
|
): ObjectInstance {
|
|
const obj = populateRuntimeObject(createObjectInstance(randomId(), typeId), this.world.data);
|
|
obj.position = [pos.x, pos.y, pos.z];
|
|
obj.rotation = [0, 0, 0];
|
|
|
|
this.scene.objects[obj.id] = obj;
|
|
|
|
return obj;
|
|
}
|
|
}
|
|
|