blockly3d/src/state/worldEditorState.ts

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;
}
}