Update editor store and viewport logic for tool preview compatibility
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
|||||||
areViewportToolPreviewsEqual,
|
areViewportToolPreviewsEqual,
|
||||||
cloneViewportToolPreview,
|
cloneViewportToolPreview,
|
||||||
createDefaultViewportTransientState,
|
createDefaultViewportTransientState,
|
||||||
|
isViewportToolPreviewCompatible,
|
||||||
type ViewportToolPreview,
|
type ViewportToolPreview,
|
||||||
type ViewportTransientState
|
type ViewportTransientState
|
||||||
} from "../viewport-three/viewport-transient-state";
|
} from "../viewport-three/viewport-transient-state";
|
||||||
@@ -112,7 +113,7 @@ export class EditorStore {
|
|||||||
|
|
||||||
this.toolMode = toolMode;
|
this.toolMode = toolMode;
|
||||||
|
|
||||||
if (toolMode !== "box-create" && this.viewportTransientState.toolPreview.kind !== "none") {
|
if (!isViewportToolPreviewCompatible(toolMode, this.viewportTransientState.toolPreview)) {
|
||||||
this.viewportTransientState = createDefaultViewportTransientState();
|
this.viewportTransientState = createDefaultViewportTransientState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createOpaqueId } from "../core/ids";
|
import { createOpaqueId } from "../core/ids";
|
||||||
import type { Vec3 } from "../core/vector";
|
import type { Vec3 } from "../core/vector";
|
||||||
|
import type { ModelAssetRecord } from "./project-assets";
|
||||||
|
|
||||||
export interface ModelInstance {
|
export interface ModelInstance {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -94,6 +95,26 @@ export function createModelInstance(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createModelInstancePlacementPosition(asset: ModelAssetRecord | undefined, anchor: Vec3 | null): Vec3 {
|
||||||
|
const boundingBox = asset?.metadata.boundingBox;
|
||||||
|
|
||||||
|
if (anchor !== null) {
|
||||||
|
const floorOffset = boundingBox === null || boundingBox === undefined ? 0 : -boundingBox.min.y;
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: anchor.x,
|
||||||
|
y: anchor.y + floorOffset,
|
||||||
|
z: anchor.z
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: DEFAULT_MODEL_INSTANCE_POSITION.x,
|
||||||
|
y: boundingBox === null || boundingBox === undefined ? DEFAULT_MODEL_INSTANCE_POSITION.y : Math.max(DEFAULT_MODEL_INSTANCE_POSITION.y, -boundingBox.min.y),
|
||||||
|
z: DEFAULT_MODEL_INSTANCE_POSITION.z
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function cloneModelInstance(instance: ModelInstance): ModelInstance {
|
export function cloneModelInstance(instance: ModelInstance): ModelInstance {
|
||||||
return createModelInstance(instance);
|
return createModelInstance(instance);
|
||||||
}
|
}
|
||||||
@@ -134,4 +155,3 @@ export function getModelInstances(modelInstances: Record<string, ModelInstance>)
|
|||||||
export function getModelInstanceKindLabel(): string {
|
export function getModelInstanceKindLabel(): string {
|
||||||
return "Model Instance";
|
return "Model Instance";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ import {
|
|||||||
type ViewportViewMode
|
type ViewportViewMode
|
||||||
} from "./viewport-view-modes";
|
} from "./viewport-view-modes";
|
||||||
import type { ViewportDisplayMode } from "./viewport-layout";
|
import type { ViewportDisplayMode } from "./viewport-layout";
|
||||||
|
import type { PlacementViewportToolPreview, ViewportToolPreview } from "./viewport-transient-state";
|
||||||
|
|
||||||
interface BrushRenderObjects {
|
interface BrushRenderObjects {
|
||||||
mesh: Mesh<BoxGeometry, Array<MeshStandardMaterial | MeshBasicMaterial>>;
|
mesh: Mesh<BoxGeometry, Array<MeshStandardMaterial | MeshBasicMaterial>>;
|
||||||
@@ -187,10 +188,14 @@ export class ViewportHost {
|
|||||||
private brushSelectionChangeHandler: ((selection: EditorSelection) => void) | null = null;
|
private brushSelectionChangeHandler: ((selection: EditorSelection) => void) | null = null;
|
||||||
private createBoxBrushHandler: ((center: Vec3) => void) | null = null;
|
private createBoxBrushHandler: ((center: Vec3) => void) | null = null;
|
||||||
private boxCreatePreviewChangeHandler: ((center: Vec3 | null) => void) | null = null;
|
private boxCreatePreviewChangeHandler: ((center: Vec3 | null) => void) | null = null;
|
||||||
|
private placementPreviewChangeHandler: ((toolPreview: ViewportToolPreview) => void) | null = null;
|
||||||
|
private placementCommitHandler: ((toolPreview: PlacementViewportToolPreview) => void) | null = null;
|
||||||
private toolMode: ToolMode = "select";
|
private toolMode: ToolMode = "select";
|
||||||
private viewMode: ViewportViewMode = "perspective";
|
private viewMode: ViewportViewMode = "perspective";
|
||||||
private displayMode: ViewportDisplayMode = "normal";
|
private displayMode: ViewportDisplayMode = "normal";
|
||||||
private lastBoxCreatePreviewCenter: Vec3 | null = null;
|
private lastBoxCreatePreviewCenter: Vec3 | null = null;
|
||||||
|
private placementPreview: PlacementViewportToolPreview | null = null;
|
||||||
|
private placementPreviewObject: Group | null = null;
|
||||||
private activeCameraDragPointerId: number | null = null;
|
private activeCameraDragPointerId: number | null = null;
|
||||||
private lastCameraDragClientPosition: { x: number; y: number } | null = null;
|
private lastCameraDragClientPosition: { x: number; y: number } | null = null;
|
||||||
// Click-through cycling: track the last click position and the last picked object
|
// Click-through cycling: track the last click position and the last picked object
|
||||||
@@ -300,6 +305,18 @@ export class ViewportHost {
|
|||||||
this.syncBoxCreatePreview(center);
|
this.syncBoxCreatePreview(center);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPlacementPreviewChangeHandler(handler: ((toolPreview: ViewportToolPreview) => void) | null) {
|
||||||
|
this.placementPreviewChangeHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlacementCommitHandler(handler: ((toolPreview: PlacementViewportToolPreview) => void) | null) {
|
||||||
|
this.placementCommitHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlacementPreview(toolPreview: PlacementViewportToolPreview | null) {
|
||||||
|
this.syncPlacementPreview(toolPreview);
|
||||||
|
}
|
||||||
|
|
||||||
setToolMode(toolMode: ToolMode) {
|
setToolMode(toolMode: ToolMode) {
|
||||||
this.toolMode = toolMode;
|
this.toolMode = toolMode;
|
||||||
this.lastClickPointer = null;
|
this.lastClickPointer = null;
|
||||||
@@ -308,6 +325,10 @@ export class ViewportHost {
|
|||||||
if (toolMode !== "box-create") {
|
if (toolMode !== "box-create") {
|
||||||
this.syncBoxCreatePreview(null);
|
this.syncBoxCreatePreview(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toolMode !== "place") {
|
||||||
|
this.syncPlacementPreview(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewMode(viewMode: ViewportViewMode) {
|
setViewMode(viewMode: ViewportViewMode) {
|
||||||
@@ -394,6 +415,9 @@ export class ViewportHost {
|
|||||||
this.clearEntityMarkers();
|
this.clearEntityMarkers();
|
||||||
this.boxCreatePreviewChangeHandler = null;
|
this.boxCreatePreviewChangeHandler = null;
|
||||||
this.syncBoxCreatePreview(null);
|
this.syncBoxCreatePreview(null);
|
||||||
|
this.placementPreviewChangeHandler = null;
|
||||||
|
this.placementCommitHandler = null;
|
||||||
|
this.syncPlacementPreview(null);
|
||||||
this.advancedRenderingComposer?.dispose();
|
this.advancedRenderingComposer?.dispose();
|
||||||
this.advancedRenderingComposer = null;
|
this.advancedRenderingComposer = null;
|
||||||
this.currentAdvancedRenderingSettings = null;
|
this.currentAdvancedRenderingSettings = null;
|
||||||
@@ -1272,6 +1296,23 @@ export class ViewportHost {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.toolMode === "place" && this.placementPreview !== null) {
|
||||||
|
const previewCenter = this.getPlacementPreviewCenter(event);
|
||||||
|
|
||||||
|
if (previewCenter !== null) {
|
||||||
|
const nextPlacementPreview = {
|
||||||
|
...this.placementPreview,
|
||||||
|
center: previewCenter
|
||||||
|
} as PlacementViewportToolPreview;
|
||||||
|
|
||||||
|
this.syncPlacementPreview(nextPlacementPreview);
|
||||||
|
this.placementPreviewChangeHandler?.(nextPlacementPreview);
|
||||||
|
this.placementCommitHandler?.(nextPlacementPreview);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bounds = this.renderer.domElement.getBoundingClientRect();
|
const bounds = this.renderer.domElement.getBoundingClientRect();
|
||||||
|
|
||||||
if (bounds.width === 0 || bounds.height === 0) {
|
if (bounds.width === 0 || bounds.height === 0) {
|
||||||
@@ -1414,6 +1455,15 @@ export class ViewportHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.toolMode !== "box-create") {
|
if (this.toolMode !== "box-create") {
|
||||||
|
if (this.toolMode !== "place" || this.placementPreview === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const previewCenter = this.getPlacementPreviewCenter(event);
|
||||||
|
const nextPlacementPreview = previewCenter === null ? { kind: "none" } : { ...this.placementPreview, center: previewCenter };
|
||||||
|
|
||||||
|
this.syncPlacementPreview(previewCenter === null ? null : (nextPlacementPreview as PlacementViewportToolPreview));
|
||||||
|
this.placementPreviewChangeHandler?.(nextPlacementPreview as ViewportToolPreview);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1440,12 +1490,18 @@ export class ViewportHost {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.toolMode !== "box-create") {
|
if (this.toolMode !== "box-create" && this.toolMode !== "place") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.syncBoxCreatePreview(null);
|
if (this.toolMode === "box-create") {
|
||||||
this.boxCreatePreviewChangeHandler?.(null);
|
this.syncBoxCreatePreview(null);
|
||||||
|
this.boxCreatePreviewChangeHandler?.(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.syncPlacementPreview(null);
|
||||||
|
this.placementPreviewChangeHandler?.({ kind: "none" });
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleWheel = (event: WheelEvent) => {
|
private handleWheel = (event: WheelEvent) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user