Update ViewportToolPreview to include placement preview and related functions

This commit is contained in:
2026-04-02 23:50:04 +02:00
parent 329785ff91
commit 61b7be6219

View File

@@ -1,4 +1,6 @@
import type { Vec3 } from "../core/vector";
import type { ToolMode } from "../core/tool-mode";
import type { EntityKind } from "../entities/entity-instances";
import type { ViewportPanelId } from "./viewport-layout";
export interface BoxCreateViewportToolPreview {
@@ -7,7 +9,25 @@ export interface BoxCreateViewportToolPreview {
center: Vec3 | null;
}
export type ViewportToolPreview = BoxCreateViewportToolPreview | { kind: "none" };
export type ViewportPlacementPreviewTarget =
| {
kind: "entity";
entityKind: EntityKind;
audioAssetId: string | null;
}
| {
kind: "model-instance";
assetId: string;
};
export interface PlacementViewportToolPreview {
kind: "placement";
sourcePanelId: ViewportPanelId;
target: ViewportPlacementPreviewTarget;
center: Vec3 | null;
}
export type ViewportToolPreview = BoxCreateViewportToolPreview | PlacementViewportToolPreview | { kind: "none" };
export interface ViewportTransientState {
toolPreview: ViewportToolPreview;
@@ -26,6 +46,25 @@ export function cloneViewportToolPreview(toolPreview: ViewportToolPreview): View
return toolPreview;
}
if (toolPreview.kind === "placement") {
return {
kind: "placement",
sourcePanelId: toolPreview.sourcePanelId,
target:
toolPreview.target.kind === "entity"
? {
kind: "entity",
entityKind: toolPreview.target.entityKind,
audioAssetId: toolPreview.target.audioAssetId
}
: {
kind: "model-instance",
assetId: toolPreview.target.assetId
},
center: toolPreview.center === null ? null : { ...toolPreview.center }
};
}
return {
kind: "box-create",
sourcePanelId: toolPreview.sourcePanelId,
@@ -42,6 +81,32 @@ export function areViewportToolPreviewsEqual(left: ViewportToolPreview, right: V
return true;
}
if (left.kind === "placement" && right.kind === "placement") {
if (left.sourcePanelId !== right.sourcePanelId) {
return false;
}
if (left.target.kind !== right.target.kind) {
return false;
}
if (left.target.kind === "entity" && right.target.kind === "entity") {
if (left.target.entityKind !== right.target.entityKind || left.target.audioAssetId !== right.target.audioAssetId) {
return false;
}
}
if (left.target.kind === "model-instance" && right.target.kind === "model-instance" && left.target.assetId !== right.target.assetId) {
return false;
}
if (left.center === null || right.center === null) {
return left.center === right.center;
}
return left.center.x === right.center.x && left.center.y === right.center.y && left.center.z === right.center.z;
}
if (left.sourcePanelId !== right.sourcePanelId) {
return false;
}
@@ -52,3 +117,19 @@ export function areViewportToolPreviewsEqual(left: ViewportToolPreview, right: V
return left.center.x === right.center.x && left.center.y === right.center.y && left.center.z === right.center.z;
}
export function isViewportToolPreviewCompatible(toolMode: ToolMode, toolPreview: ViewportToolPreview): boolean {
if (toolPreview.kind === "none") {
return true;
}
if (toolMode === "box-create") {
return toolPreview.kind === "box-create";
}
if (toolMode === "place") {
return toolPreview.kind === "placement";
}
return false;
}