649d4ecdca
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
3.2 KiB
3.2 KiB
Objetivo
Adicionar uma ferramenta de corte de seção (clipping planes) nos eixos X, Y e Z — padrão em viewers IFC/BIM. O usuário move sliders por eixo e a peça vai sendo cortada/revelada em tempo real. Implementada como janela pop-up flutuante sobre o viewer, com controle de opacidade da própria janela. Sem presets persistidos.
UX
Botões na barra ViewerControls
- "Cortes" (ícone
Scissors) — abre/fecha a janela pop-up. O estado dos cortes é independente da janela: fechar não reseta nada. - Lixeira ao lado, só fica habilitada quando há pelo menos um eixo de corte ativo. Clicar =
resetSection()(desliga e zera os 3 eixos). Único caminho para zerar. - Indicador visual no botão "Cortes" quando há corte ativo (badge ou variante
default).
Pop-up (componente SectionCutPanel)
- Janela flutuante sobre o viewer (canto superior-direito da área 3D), arrastável pelo header. Não-modal.
- Estilo:
bg-card/X+backdrop-blur, borda industrial, font-mono. - Header: título "Cortes de Seção", slider de opacidade da janela (20%–100%, default 90%), botão fechar (X).
- 3 blocos idênticos para X / Y / Z, cada um com controle individual:
- Switch on/off do eixo.
- Switch "Inverter" (flip do lado mantido).
- Slider do nível de corte mapeado ao bbox mundial da peça ativa naquele eixo, valor em mm.
- Mini-botões: Min · Centro · Max para saltar a posição.
- Botão "Recalcular limites" (re-amostra o bbox depois de calibração/fine-tuning).
- Sem botões de salvar/memória.
- Fechar a janela apenas oculta os controles. Reabrir mostra exatamente o estado dos cortes que o usuário deixou.
Comportamento técnico
gl.localClippingEnabled = truenoonCreateddo<Canvas>.- Novos campos em
useModelStore(não persistidos):sectionEnabled: { x: boolean; y: boolean; z: boolean }sectionInvert: { x: boolean; y: boolean; z: boolean }sectionLevel: { x: number; y: number; z: number }(em metros, mundo)sectionPanelOpen: booleansectionPanelOpacity: number(0.2–1)- Setters por eixo +
resetSection()(zera enabled, invert e leva level ao centro do bbox). - Helper
hasActiveSection()derivado desectionEnabled.
- Novo componente
<SectionClippingApplier>montado dentro do<Canvas>:- Mantém 3
THREE.Planereutilizáveis. A cada mudança nos campos do store, atualizaplane.normal(com sinal flipado seinvert) eplane.constant = -level(axis-aligned, mundo). - Aplica
material.clippingPlanes = ativosem cadaMeshdos grupos registrados emmodelTransforms. Restaura[]ao desligar todos os eixos.
- Mantém 3
- Limites dos sliders: bbox mundial agregado dos
getAllModelLocalGroups(). Calculado quando o painel abre e quando o usuário aciona "Recalcular limites".
Arquivos afetados
src/stores/useModelStore.ts— novos campos e setters de seção + painel.src/components/three/ModelViewer.tsx—localClippingEnabledno GL; monta<SectionClippingApplier>.src/components/SectionCutPanel.tsx(novo) — janela pop-up flutuante com 3 sliders, switches, opacidade.src/components/ViewerControls.tsx— botão "Cortes" + lixeira condicional.src/pages/Viewer.tsx— monta<SectionCutPanel />na área do viewer.