Update ViewportCanvas and ViewportPanel to support terrain brush state and commit handling

This commit is contained in:
2026-04-18 20:21:58 +02:00
parent d42765d9f8
commit fc375c4937
2 changed files with 37 additions and 0 deletions

View File

@@ -4,6 +4,10 @@ import type { LoadedModelAsset } from "../assets/gltf-model-import";
import type { LoadedImageAsset } from "../assets/image-assets";
import type { ProjectAssetRecord } from "../assets/project-assets";
import type { EditorSelection } from "../core/selection";
import type {
ArmedTerrainBrushState,
TerrainBrushStrokeCommit
} from "../core/terrain-brush";
import { getWhiteboxSelectionFeedbackLabel } from "../core/whitebox-selection-feedback";
import type { ToolMode } from "../core/tool-mode";
import { type WhiteboxSelectionMode } from "../core/whitebox-selection-mode";
@@ -52,6 +56,7 @@ interface ViewportCanvasProps {
viewportGridVisible: boolean;
selection: EditorSelection;
activeSelectionId: string | null;
terrainBrushState: ArmedTerrainBrushState | null;
toolMode: ToolMode;
toolPreview: ViewportToolPreview;
transformSession: TransformSessionState;
@@ -63,6 +68,7 @@ interface ViewportCanvasProps {
focusRequestId: number;
focusSelection: EditorSelection;
onSelectionChange(selection: EditorSelection): void;
onTerrainBrushCommit(commit: TerrainBrushStrokeCommit): boolean;
onCommitCreation(toolPreview: CreationViewportToolPreview): boolean;
onCameraStateChange(cameraState: ViewportPanelCameraState): void;
onToolPreviewChange(toolPreview: ViewportToolPreview): void;
@@ -86,6 +92,7 @@ export function ViewportCanvas({
viewportGridVisible,
selection,
activeSelectionId,
terrainBrushState,
toolMode,
toolPreview,
transformSession,
@@ -97,6 +104,7 @@ export function ViewportCanvas({
focusRequestId,
focusSelection,
onSelectionChange,
onTerrainBrushCommit,
onCommitCreation,
onCameraStateChange,
onToolPreviewChange,
@@ -209,6 +217,10 @@ export function ViewportCanvas({
hostRef.current?.setBrushSelectionChangeHandler(onSelectionChange);
}, [onSelectionChange]);
useEffect(() => {
hostRef.current?.setTerrainBrushCommitHandler?.(onTerrainBrushCommit);
}, [onTerrainBrushCommit]);
useEffect(() => {
hostRef.current?.setWhiteboxHoverLabelChangeHandler(
setHoveredWhiteboxLabel
@@ -252,6 +264,10 @@ export function ViewportCanvas({
hostRef.current?.setToolMode(toolMode);
}, [toolMode]);
useLayoutEffect(() => {
hostRef.current?.setTerrainBrushState?.(terrainBrushState);
}, [terrainBrushState]);
useLayoutEffect(() => {
hostRef.current?.setCreationPreview(
toolMode === "create" && toolPreview.kind === "create"
@@ -280,6 +296,8 @@ export function ViewportCanvas({
const selectedWhiteboxLabel = toolMode === "select"
? getWhiteboxSelectionFeedbackLabel(sceneDocument, selection)
: null;
const terrainBrushOverlayVisible =
toolMode === "select" && terrainBrushState !== null;
const resolvedViewportBackground =
editorSimulationScene !== null && editorSimulationClock !== null
? resolveRuntimeDayNightWorldState(
@@ -291,6 +309,7 @@ export function ViewportCanvas({
const showOverlay =
previewVisible ||
transformPreviewVisible ||
terrainBrushOverlayVisible ||
selectedWhiteboxLabel !== null ||
hoveredWhiteboxLabel !== null;
@@ -351,6 +370,14 @@ export function ViewportCanvas({
]
.filter((part) => part !== null)
.join(" · ")}
</div>
)}
{!terrainBrushOverlayVisible ? null : (
<div
className="viewport-canvas__overlay-preview"
data-testid={`viewport-terrain-brush-preview-${panelId}`}
>
terrain · {terrainBrushState.tool}
</div>
)}
{selectedWhiteboxLabel === null ? null : (

View File

@@ -25,6 +25,10 @@ import type { LoadedModelAsset } from "../assets/gltf-model-import";
import type { LoadedImageAsset } from "../assets/image-assets";
import type { ProjectAssetRecord } from "../assets/project-assets";
import type { EditorSelection } from "../core/selection";
import type {
ArmedTerrainBrushState,
TerrainBrushStrokeCommit
} from "../core/terrain-brush";
import {
getWhiteboxSelectionModeLabel,
WHITEBOX_SELECTION_MODES,
@@ -62,6 +66,7 @@ interface ViewportPanelProps {
viewportGridVisible: boolean;
selection: EditorSelection;
activeSelectionId: string | null;
terrainBrushState: ArmedTerrainBrushState | null;
toolMode: ToolMode;
toolPreview: ViewportToolPreview;
transformSession: TransformSessionState;
@@ -85,6 +90,7 @@ interface ViewportPanelProps {
displayMode: ViewportDisplayMode
): void;
onCommitCreation(toolPreview: CreationViewportToolPreview): boolean;
onTerrainBrushCommit(commit: TerrainBrushStrokeCommit): boolean;
onCameraStateChange(cameraState: ViewportPanelCameraState): void;
onToolPreviewChange(toolPreview: ViewportToolPreview): void;
onBeginTransformOperation(operation: TransformOperation): void;
@@ -136,6 +142,7 @@ export function ViewportPanel({
viewportGridVisible,
selection,
activeSelectionId,
terrainBrushState,
toolMode,
toolPreview,
transformSession,
@@ -153,6 +160,7 @@ export function ViewportPanel({
onSetPanelViewMode,
onSetPanelDisplayMode,
onCommitCreation,
onTerrainBrushCommit,
onCameraStateChange,
onToolPreviewChange,
onBeginTransformOperation,
@@ -198,6 +206,7 @@ export function ViewportPanel({
viewportGridVisible={viewportGridVisible}
selection={selection}
activeSelectionId={activeSelectionId}
terrainBrushState={terrainBrushState}
toolMode={toolMode}
toolPreview={toolPreview}
transformSession={transformSession}
@@ -209,6 +218,7 @@ export function ViewportPanel({
focusRequestId={focusRequestId}
focusSelection={focusSelection}
onSelectionChange={onSelectionChange}
onTerrainBrushCommit={onTerrainBrushCommit}
onCommitCreation={onCommitCreation}
onCameraStateChange={onCameraStateChange}
onToolPreviewChange={onToolPreviewChange}