Refactor tool mode handling and creation logic in App.tsx

This commit is contained in:
2026-04-03 00:22:56 +02:00
parent 0c84ccdd3c
commit 5895f79264

View File

@@ -1250,10 +1250,10 @@ export function App({ store, initialStatusMessage }: AppProps) {
return; return;
} }
if (event.key === "Escape" && editorState.toolMode === "place") { if (event.key === "Escape" && editorState.toolMode === "create") {
event.preventDefault(); event.preventDefault();
store.setToolMode("select"); store.setToolMode("select");
setStatusMessage("Cancelled the current placement preview."); setStatusMessage("Cancelled the current creation preview.");
return; return;
} }
@@ -1342,14 +1342,6 @@ export function App({ store, initialStatusMessage }: AppProps) {
return; return;
} }
if (
nextLayoutMode === "single" &&
editorState.viewportTransientState.toolPreview.kind === "box-create" &&
editorState.viewportTransientState.toolPreview.sourcePanelId !== activePanelId
) {
store.clearViewportToolPreview(editorState.viewportTransientState.toolPreview.sourcePanelId);
}
blurActiveTextEntry(); blurActiveTextEntry();
store.setViewportLayoutMode(nextLayoutMode); store.setViewportLayoutMode(nextLayoutMode);
setStatusMessage(`Switched the viewport to ${getViewportLayoutModeLabel(nextLayoutMode)}.`); setStatusMessage(`Switched the viewport to ${getViewportLayoutModeLabel(nextLayoutMode)}.`);
@@ -1370,13 +1362,6 @@ export function App({ store, initialStatusMessage }: AppProps) {
return; return;
} }
if (
editorState.viewportTransientState.toolPreview.kind === "box-create" &&
editorState.viewportTransientState.toolPreview.sourcePanelId === panelId
) {
store.clearViewportToolPreview(panelId);
}
blurActiveTextEntry(); blurActiveTextEntry();
store.setViewportPanelViewMode(panelId, nextViewMode); store.setViewportPanelViewMode(panelId, nextViewMode);
@@ -1393,17 +1378,26 @@ export function App({ store, initialStatusMessage }: AppProps) {
setStatusMessage(`Set the viewport panel to ${getViewportDisplayModeLabel(nextDisplayMode)} display.`); setStatusMessage(`Set the viewport panel to ${getViewportDisplayModeLabel(nextDisplayMode)} display.`);
}; };
const handleCreateBoxBrush = (center?: Vec3) => { const beginCreation = (toolPreview: CreationViewportToolPreview, status: string) => {
try { blurActiveTextEntry();
store.executeCommand(createCreateBoxBrushCommand(center === undefined ? {} : { center })); closeAddMenu();
setStatusMessage( store.setViewportToolPreview(toolPreview);
center === undefined store.setToolMode("create");
? `Created a box brush snapped to the ${DEFAULT_GRID_SIZE}m grid.` setStatusMessage(status);
: `Created a box brush at snapped center ${formatVec3(center)}.` };
);
} catch (error) { const beginBoxCreation = () => {
setStatusMessage(getErrorMessage(error)); beginCreation(
} {
kind: "create",
sourcePanelId: activePanelId,
target: {
kind: "box-brush"
},
center: null
},
"Previewing a box brush. Click in the viewport to create it."
);
}; };
const applySelection = ( const applySelection = (
@@ -1510,18 +1504,10 @@ export function App({ store, initialStatusMessage }: AppProps) {
setStatusMessage(successMessage); setStatusMessage(successMessage);
}; };
const beginPlacement = (toolPreview: PlacementViewportToolPreview, status: string) => { const beginEntityCreation = (kind: EntityKind, options: { audioAssetId?: string | null } = {}) => {
blurActiveTextEntry(); beginCreation(
closeAddMenu();
store.setViewportToolPreview(toolPreview);
store.setToolMode("place");
setStatusMessage(status);
};
const beginEntityPlacement = (kind: EntityKind, options: { audioAssetId?: string | null } = {}) => {
beginPlacement(
{ {
kind: "placement", kind: "create",
sourcePanelId: activePanelId, sourcePanelId: activePanelId,
target: { target: {
kind: "entity", kind: "entity",
@@ -1534,7 +1520,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
); );
}; };
const beginModelInstancePlacement = (assetId: string) => { const beginModelInstanceCreation = (assetId: string) => {
const asset = editorState.document.assets[assetId]; const asset = editorState.document.assets[assetId];
if (asset === undefined || asset.kind !== "model") { if (asset === undefined || asset.kind !== "model") {
@@ -1542,9 +1528,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
return; return;
} }
beginPlacement( beginCreation(
{ {
kind: "placement", kind: "create",
sourcePanelId: activePanelId, sourcePanelId: activePanelId,
target: { target: {
kind: "model-instance", kind: "model-instance",
@@ -1556,10 +1542,24 @@ export function App({ store, initialStatusMessage }: AppProps) {
); );
}; };
const handleCommitPlacement = (placementPreview: PlacementViewportToolPreview) => { const handleCommitCreation = (creationPreview: CreationViewportToolPreview) => {
try { try {
if (placementPreview.target.kind === "model-instance") { if (creationPreview.target.kind === "box-brush") {
const asset = editorState.document.assets[placementPreview.target.assetId]; const center = creationPreview.center === null ? undefined : creationPreview.center;
store.executeCommand(
createCreateBoxBrushCommand(center === undefined ? {} : { center })
);
setStatusMessage(
center === undefined
? `Created a box brush snapped to the ${DEFAULT_GRID_SIZE}m grid.`
: `Created a box brush at snapped center ${formatVec3(center)}.`
);
return;
}
if (creationPreview.target.kind === "model-instance") {
const asset = editorState.document.assets[creationPreview.target.assetId];
if (asset === undefined || asset.kind !== "model") { if (asset === undefined || asset.kind !== "model") {
setStatusMessage("Select a model asset before placing a model instance."); setStatusMessage("Select a model asset before placing a model instance.");
@@ -1569,7 +1569,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
const nextModelInstance = createModelInstance({ const nextModelInstance = createModelInstance({
assetId: asset.id, assetId: asset.id,
position: position:
placementPreview.center === null ? createModelInstancePlacementPosition(asset, null) : placementPreview.center, creationPreview.center === null ? createModelInstancePlacementPosition(asset, null) : creationPreview.center,
rotationDegrees: DEFAULT_MODEL_INSTANCE_ROTATION_DEGREES, rotationDegrees: DEFAULT_MODEL_INSTANCE_ROTATION_DEGREES,
scale: DEFAULT_MODEL_INSTANCE_SCALE scale: DEFAULT_MODEL_INSTANCE_SCALE
}); });
@@ -1584,9 +1584,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
return; return;
} }
const position = placementPreview.center ?? DEFAULT_ENTITY_POSITION; const position = creationPreview.center ?? DEFAULT_ENTITY_POSITION;
switch (placementPreview.target.entityKind) { switch (creationPreview.target.entityKind) {
case "pointLight": case "pointLight":
store.executeCommand( store.executeCommand(
createUpsertEntityCommand({ createUpsertEntityCommand({
@@ -1621,7 +1621,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
setStatusMessage("Placed Player Start."); setStatusMessage("Placed Player Start.");
return; return;
case "soundEmitter": { case "soundEmitter": {
const placedAudioAssetId = placementPreview.target.audioAssetId ?? audioAssetList[0]?.id ?? null; const placedAudioAssetId = creationPreview.target.audioAssetId ?? audioAssetList[0]?.id ?? null;
store.executeCommand( store.executeCommand(
createUpsertEntityCommand({ createUpsertEntityCommand({