import { useState } from 'react'; import { Eye, LayoutGrid, Grid3X3, Box, Ruler, Trash2, Camera, Move, RotateCw, RefreshCw, ChevronUp, ChevronDown, Grip, ClipboardCheck, X, Crosshair, Magnet, HelpCircle, Maximize2, MousePointerClick, EyeOff, Focus, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Slider } from '@/components/ui/slider'; import { ScrollArea } from '@/components/ui/scroll-area'; import { useModelStore } from '@/stores/useModelStore'; import { InspectionChecklist } from '@/components/InspectionChecklist'; import { ScaleSelector } from '@/components/ScaleSelector'; import { CloudLoader } from '@/components/CloudLoader'; import { ShareButton } from '@/components/ShareButton'; import { SceneModelList } from '@/components/SceneModelList'; import { toast } from 'sonner'; const POSITION_STEP = 0.001; const ROTATION_STEP = 0.1; interface XRHudProps { freeMove: boolean; onToggleFreeMove: () => void; placementMode?: boolean; onTogglePlacement?: () => void; snapToPlanes?: boolean; onToggleSnap?: () => void; allowScale?: boolean; onToggleAllowScale?: () => void; } const helpItems = [ { title: 'Grip (1 mão) — Pan', icon: '✊', desc: 'Aperte UM grip lateral e mova o controle: a peça é arrastada (translação) sem rotacionar. Solte para fixar.', }, { title: 'Grip (2 mãos) — Zoom + Orbit', icon: '🤲', desc: 'Aperte o grip dos DOIS controles. AFASTE/APROXIME as mãos para dar ZOOM. Gire os punhos em direções opostas para ORBITAR a peça pelo eixo entre as mãos.', }, { title: 'Trigger — Selecionar / Medir', icon: '🔫', desc: 'O gatilho NÃO move a peça. Ele só age dentro dos modos Selecionar, Medir ou Posicionar — escolhendo elementos, marcando pontos ou colocando o modelo na superfície.', }, { title: 'Thumbstick — Locomoção', icon: '🕹️', desc: 'Para FRENTE e solte: teletransporta para o ponto apontado. Para os LADOS: snap-rotate de ±30° na câmera. Para TRÁS: passo de 0,3 m no sentido oposto ao olhar.', }, { title: 'Posicionar (Hit-Test)', icon: '🎯', desc: 'Ative para reposicionar o modelo. Aponte o controle para uma superfície real e aperte o TRIGGER no retículo para fixar o modelo ali.', }, { title: 'Snap (Planos)', icon: '🧲', desc: 'Quando ON, o modelo se alinha automaticamente aos planos detectados (chão, parede, mesa). Retículo azul indica snap ativo.', }, { title: 'Grid', icon: '📐', desc: 'Exibe/oculta a grade de referência para alinhar o modelo com o ambiente.', }, { title: 'Sólido / Wire / Bordas', icon: '🔲', desc: 'Alterna modos de renderização: Sólido (preenchido), Wireframe (malha), Bordas (apenas contornos).', }, { title: 'Medir', icon: '📏', desc: 'Ative e toque o TRIGGER em dois pontos da peça para medir a distância em milímetros. O snap de vértice auxilia a precisão.', }, { title: 'Screenshot', icon: '📸', desc: 'Captura uma imagem da visão AR atual. As capturas ficam na galeria do viewer.', }, { title: 'Inspeção', icon: '📋', desc: 'Abre o checklist para aprovar ou rejeitar itens (dimensões, furos, soldas, posição das chapas).', }, { title: 'Opacidade', icon: '👁️', desc: 'Ajusta a transparência do modelo de 0% a 100% para ver através da peça.', }, { title: 'Ajuste fino (Posição/Rotação)', icon: '↔️', desc: 'Use os botões +/− do painel para ajustes finos em milímetros (posição) e décimos de grau (rotação). O joystick não faz mais ajuste fino — ele agora é só locomoção.', }, { title: 'Botões A/B (Touch Plus direito)', icon: '🎮', desc: 'No modo Medir: A = desfazer último ponto; B = limpar todas as medições. O botão Menu (esquerdo) abre o menu Universal do Quest.', }, ]; export function XRHud({ freeMove, onToggleFreeMove, placementMode = false, onTogglePlacement, snapToPlanes = true, onToggleSnap, allowScale = false, onToggleAllowScale }: XRHudProps) { const [expanded, setExpanded] = useState(false); const [checklistOpen, setChecklistOpen] = useState(false); const [helpOpen, setHelpOpen] = useState(false); const { opacity, setOpacity, renderMode, setRenderMode, showGrid, setShowGrid, measureMode, setMeasureMode, measurements, clearMeasurements, measurePoints, fineTuning, setFineTuning, resetFineTuning, addScreenshot, checklist, selectionMode, setSelectionMode, selectedElementKeys, hiddenElementKeys, isolatedElementKeys, hideSelectedElements, isolateSelectedElements, showAllElements, } = useModelStore(); const hasSelection = selectedElementKeys.size > 0; const hasHidden = hiddenElementKeys.size > 0 || isolatedElementKeys !== null; const approved = checklist.filter(i => i.status === 'approved').length; const rejected = checklist.filter(i => i.status === 'rejected').length; const total = checklist.length; const handleScreenshot = () => { const canvas = document.querySelector('canvas'); if (!canvas) return; const dataUrl = canvas.toDataURL('image/png'); addScreenshot(dataUrl); toast.success('Screenshot capturado!'); }; return ( <> {/* ── Slide-out checklist panel ── */}
Inspeção
{approved + rejected}/{total}
{/* ── Slide-out help panel ── */}
Ajuda — Ferramentas AR
{helpItems.map((item) => (
{item.icon} {item.title}

{item.desc}

))}
{/* ── Bottom HUD ── */}
{/* Expanded panel */} {expanded && (
{/* Scene models list */} {/* Opacity */}
Opacidade
{Math.round(opacity * 100)}%
setOpacity(v / 100)} />
{/* Fine Tuning */}
Posição (mm)
{(['posX', 'posY', 'posZ'] as const).map((axis) => (
{axis.slice(-1).toUpperCase()} {(fineTuning[axis] * 1000).toFixed(1)}
))}
{/* Rotation X, Y, Z */}
Rotação
{(['rotX', 'rotY', 'rotZ'] as const).map((axis) => (
{axis.slice(-1).toUpperCase()}° {fineTuning[axis].toFixed(1)}
))}
)} {/* Main toolbar */}
{/* Help button */} {/* Hit-test placement toggle */} {onTogglePlacement && ( )} {/* Snap to planes toggle */} {onToggleSnap && ( )} {/* Two-hand scale toggle */} {onToggleAllowScale && ( )} {/* Scale presets */} {/* Cloud loader (acessível também no AR) */} {/* Share live screen */} {measurements.length > 0 && ( )} {/* Selection */} {hasSelection && ( <> )} {hasHidden && ( )} {/* Checklist toggle */}
); }