From d89040e9f1232d0e5449969fdcccf1de477d0839 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 26 May 2026 21:41:03 +0800 Subject: [PATCH] fix: simplify world controls and camera init --- components/canvas/nodes/World3DNode.tsx | 109 ++------------------ components/canvas/world3d/World3DViewer.tsx | 55 +++++++--- 2 files changed, 47 insertions(+), 117 deletions(-) diff --git a/components/canvas/nodes/World3DNode.tsx b/components/canvas/nodes/World3DNode.tsx index 2a4eefb2e..0d2b9b82a 100644 --- a/components/canvas/nodes/World3DNode.tsx +++ b/components/canvas/nodes/World3DNode.tsx @@ -6,15 +6,12 @@ import { Box, Camera, Copy, - Crosshair, - Cuboid, Download, ImageIcon, Loader2, MoreVertical, Sparkles, Trash2, - Waypoints, type LucideIcon, } from "lucide-react"; import { CanvasToolbarIcon } from "@/components/canvas/CanvasToolbarIcon"; @@ -51,7 +48,7 @@ import { worldLabsGenerationService, } from "@/services/canvas"; import { useCanvasStore } from "@/store/canvas"; -import type { CanvasNode, World3DHotspot, World3DNodeData, World3DViewMode } from "@/types/canvas"; +import type { CanvasNode, World3DNodeData, World3DViewMode } from "@/types/canvas"; import { cn, fetcher } from "@/lib/utils"; interface World3DNodeProps { @@ -68,7 +65,6 @@ const VIEW_META: Array<{ }> = [ { id: "image", label: "I", icon: ImageIcon, toolbarKey: "world3dViewImage" }, { id: "splat", label: "3D", icon: Box, toolbarKey: "world3dViewSplat" }, - { id: "mesh", label: "M", icon: Cuboid, toolbarKey: "world3dViewMesh" }, ]; const WORLD_ASSET_HYDRATION_INTERVAL_MS = 5000; @@ -188,6 +184,7 @@ function resolveActiveView(data: World3DNodeData) { const hasSplat = availableViews.includes("splat"); if ( data.activeView && + data.activeView !== "mesh" && availableViews.includes(data.activeView) ) { return data.activeView; @@ -255,7 +252,6 @@ export function World3DNode({ }: World3DNodeProps) { const data = node.data as World3DNodeData; const [isHovered, setIsHovered] = useState(false); - const [interactionMode, setInteractionMode] = useState<"navigate" | "hotspot">("navigate"); const [viewerCapture, setViewerCapture] = useState<(() => Promise) | null>( null ); @@ -272,14 +268,6 @@ export function World3DNode({ const projectId = useCanvasStore((state) => state.projectId); const getCanvasState = useCanvasStore((state) => state.getCanvasState); const viewportZoom = useCanvasStore((state) => state.viewport.zoom); - const world3dFirstPersonItem = getCanvasToolbarItem( - canvasToolbarConfig, - "world3dFirstPerson" - ); - const world3dHotspotItem = getCanvasToolbarItem( - canvasToolbarConfig, - "world3dHotspot" - ); const world3dMoreItem = getCanvasToolbarItem(canvasToolbarConfig, "world3dMore"); const world3dOpenMeshItem = getCanvasToolbarItem( canvasToolbarConfig, @@ -354,7 +342,7 @@ export function World3DNode({ ); const primaryUrl = resolvePrimaryUrl(data, activeView); const modelDownloadTarget = inferModelDownloadTarget(data); - const hotspotCount = data.hotspots?.length || 0; + const interactionMode = "navigate" as const; const placeholderSizeScale = useMemo( () => getNodeContentScale(node.size, { width: 420, height: 320 }, 0.76), [node.size.height, node.size.width] @@ -618,7 +606,7 @@ export function World3DNode({ modelVersion, status: "completed", activeView: splatUrl ? "splat" : meshUrl ? "mesh" : imageUrl ? "image" : "image", - firstPerson: data.firstPerson ?? false, + firstPerson: data.firstPerson ?? true, hotspots: data.hotspots || [], semanticsMetadata: assetPayload.semanticsMetadata && @@ -770,7 +758,7 @@ export function World3DNode({ : imageUrl ? "image" : data.activeView, - firstPerson: data.firstPerson ?? false, + firstPerson: data.firstPerson ?? true, semanticsMetadata: assetPayload.semanticsMetadata && typeof assetPayload.semanticsMetadata === "object" ? (assetPayload.semanticsMetadata as Record) @@ -820,55 +808,6 @@ export function World3DNode({ }); }; - const handleToggleFirstPerson = () => { - const nextFirstPerson = !data.firstPerson; - updateNode(node.id, { - data: { - ...data, - firstPerson: nextFirstPerson, - } as World3DNodeData, - }); - if (nextFirstPerson) { - setInteractionMode("navigate"); - } - }; - - const handleToggleHotspotMode = () => { - const nextMode = interactionMode === "hotspot" ? "navigate" : "hotspot"; - setInteractionMode(nextMode); - if (nextMode === "hotspot" && data.firstPerson) { - updateNode(node.id, { - data: { - ...data, - firstPerson: false, - } as World3DNodeData, - }); - } - }; - - const handlePick = (pick: { point: [number, number, number] }) => { - if (interactionMode !== "hotspot") return; - const nextHotspot: World3DHotspot = { - id: crypto.randomUUID(), - label: `热点 ${hotspotCount + 1}`, - position: { - x: pick.point[0], - y: pick.point[1], - z: pick.point[2], - }, - createdAt: new Date().toISOString(), - }; - - updateNode(node.id, { - data: { - ...data, - hotspots: [...(data.hotspots || []), nextHotspot], - } as World3DNodeData, - }); - setInteractionMode("navigate"); - toast.success("已添加世界热点"); - }; - const handleCopy = async () => { if (!primaryUrl) { toast.error("暂无可复制的世界地址"); @@ -1144,14 +1083,13 @@ export function World3DNode({ > - {activeView === "splat" ? ( -
- - -
- ) : null} - {captureEnabled ? (