From 1a7107249796f3821311ac76616969f83873bc78 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 8 Apr 2026 18:10:36 +0800 Subject: [PATCH] fix: improve world 3d controls and restore mesh selection --- app/canvas/[id]/model3d/page.tsx | 146 +++++++++++++++----- components/canvas/model3d/Model3DViewer.tsx | 17 ++- components/canvas/world3d/World3DViewer.tsx | 52 ++++--- 3 files changed, 159 insertions(+), 56 deletions(-) diff --git a/app/canvas/[id]/model3d/page.tsx b/app/canvas/[id]/model3d/page.tsx index 86c55c5b8..21e3e256a 100644 --- a/app/canvas/[id]/model3d/page.tsx +++ b/app/canvas/[id]/model3d/page.tsx @@ -630,6 +630,7 @@ export default function CanvasModel3DPage() { ); const [worldViewportMode, setWorldViewportMode] = useState("world"); + const [viewerResetToken, setViewerResetToken] = useState(0); const [taskHistory, setTaskHistory] = useState([]); const [currentTask, setCurrentTask] = useState(null); @@ -991,7 +992,7 @@ export default function CanvasModel3DPage() { [taskHistory, workspaceMode] ); - const currentModelUrl = currentTask?.modelUrl || null; + const currentModelUrl = resolveTaskModelUrl(currentTask); const currentPreviewImage = currentTask?.previewImageUrl || (workspaceMode === "model" @@ -2184,6 +2185,11 @@ export default function CanvasModel3DPage() { workspaceMode === "world" ? "3D 世界工作台" : "3D 工作台"; const viewerEmptyStateTitle = workspaceMode === "world" ? "准备生成 3D 世界" : "准备生成 3D 资产"; + + useEffect(() => { + setViewerResetToken((prev) => prev + 1); + }, [currentTask?.taskId, workspaceMode, worldViewportMode]); + useEffect(() => { if (workspaceMode !== "world") return; setWorldViewportMode(preferredWorldViewportMode); @@ -3262,39 +3268,99 @@ export default function CanvasModel3DPage() { {/* 3. Main Viewer Area */}
{workspaceMode === "world" && ( -
- {[ - { - id: "splat" as WorldViewportMode, - label: "World", - icon: Sparkles, - disabled: !currentPrimarySpzUrl, - }, - { - id: "imagery" as WorldViewportMode, - label: "图像", - icon: ImageIcon, - disabled: !currentWorldImageUrl, - }, - { - id: "mesh" as WorldViewportMode, - label: "Mesh", - icon: Box, - disabled: !currentModelUrl, - }, - ].map((view) => ( +
+
+
+
+ Viewer Controls +
+

+ 3D 世界控制 +

+
- ))} +
+ +
+ {[ + { + id: "splat" as WorldViewportMode, + label: "World", + icon: Sparkles, + disabled: !currentPrimarySpzUrl, + }, + { + id: "imagery" as WorldViewportMode, + label: "图像", + icon: ImageIcon, + disabled: !currentWorldImageUrl, + }, + { + id: "mesh" as WorldViewportMode, + label: "Mesh", + icon: Box, + disabled: !currentModelUrl, + }, + ].map((view) => ( + + ))} +
+ +
+ {worldViewportMode === "splat" ? ( + <> +
+ 鼠标拖拽会围绕场景原点旋转 +
+
+ 左键拖拽旋转,滚轮缩放;已关闭横向平移。需要切换模型时,直接点击右侧资产卡片。 +
+ + ) : worldViewportMode === "mesh" ? ( + <> +
+ Mesh 视图已恢复 +
+
+ 当前世界关联的 Mesh 会在这里直接显示,也可以从右侧资产库点击缩略图切换当前模型。 +
+ + ) : ( + <> +
+ 当前为图像预览 +
+
+ 可以切回 World 查看空间结果,或切到 Mesh 继续检查几何结构。 +
+ + )} +
)} @@ -3309,6 +3375,7 @@ export default function CanvasModel3DPage() { onMeshLayersChange={handleLayersChange} onMeshStatsChange={setViewerStats} previewImageUrl={currentPreviewImage} + resetViewToken={viewerResetToken} semanticsMetadata={currentWorldAsset?.semanticsMetadata} splatUrl={currentPrimarySpzUrl} worldUrl={currentWorldAsset?.worldUrl} @@ -3321,6 +3388,7 @@ export default function CanvasModel3DPage() { onLayersChange={handleLayersChange} onStatsChange={setViewerStats} previewImageUrl={currentPreviewImage} + resetViewToken={viewerResetToken} settings={viewerSettings} /> )} @@ -3390,9 +3458,14 @@ export default function CanvasModel3DPage() { {/* 4. Right Assets Panel */}
-

- {workspaceMode === "world" ? "世界资产库" : "模型资产库"} -

+
+

+ {workspaceMode === "world" ? "世界资产库" : "模型资产库"} +

+

+ 点击缩略图切换当前{workspaceMode === "world" ? "世界 / 模型" : "模型"} +

+
@@ -1135,6 +1146,7 @@ export function World3DViewer({ onHotspotSelect={onHotspotSelect} onPick={onPick} previewImageUrl={previewImageUrl} + resetViewToken={resetViewToken} semanticsMetadata={semanticsMetadata} splatUrl={splatUrl} />