cffa66c6df
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
3.5 KiB
3.5 KiB
Modo Posicionar (desktop)
Permite que, antes de entrar no AR, o usuário mova e gire a peça ativa com o mouse — exatamente como faria com o controle no AR. As outras peças permanecem travadas. Ao desativar o botão, todas ficam fixas nas posições atuais e o estado persiste (já temos savePlacement por fileName).
Comportamento
- Botão Posicionar (ícone Move3D) na barra
ViewerControls, ao lado de Medir. - Quando ativo:
OrbitControlsé desabilitado (não conflitar com o arrasto da peça).- Cursor vira
move. - Apenas a peça com
activeModelIdresponde ao mouse. Clicar em outra peça troca a ativa e passa a manipulá-la (as outras voltam a ficar travadas). - Arrastar com botão esquerdo → translada no plano da câmera (X/Y da tela projetados para o mundo).
- Shift + arrastar esquerdo ou arrastar com botão do meio → translada no eixo Z (profundidade) usando o movimento vertical do mouse.
- Arrastar com botão direito → rotaciona: movimento horizontal = rotY (yaw), movimento vertical = rotX (pitch). Shift + direito = rotZ (roll).
- Cada movimento atualiza
fineTuningviasetFineTuningda peça ativa, o que já disparasavePlacement(persistência entre sessões/entrar-sair do AR — mesma chave usada hoje).
- Quando desativado: tudo volta ao normal (Orbit ativo, peças travadas onde foram deixadas). Modo Medir e Posicionar são mutuamente exclusivos.
Arquivos a alterar
-
src/stores/useModelStore.ts- Adicionar
positionMode: boolean+setPositionMode(on). - Em
setPositionMode(true)desligarmeasureMode; e vice-versa emsetMeasureMode.
- Adicionar
-
src/components/three/ModelViewer.tsx- Novo componente
PositionDragHandler(dentro do Canvas) que:- Escuta
pointerdown/move/upnogl.domElementquandopositionModeestá on e existeactiveModelId. - Converte delta de pixels em delta de mundo usando a distância câmera↔peça e o FOV (
2 * dist * tan(fov/2) / canvasHeight), depois divide peloscaleRatio.factorpara gravar em coordenadas locais coerentes comfineTuning. - Aplica via
setFineTuning({ posX: ..., posY: ..., posZ: ..., rotX: ..., rotY: ..., rotZ: ... }).
- Escuta
- Em
OrbitControls, definirenabled={!positionMode && !measureMode}(medir já não rotaciona hoje só por cursor, mas reforça). - Cursor: quando
positionMode, setargl.domElement.style.cursor = 'move'.
- Novo componente
-
src/components/ViewerControls.tsx- Importar ícone
Move3Ddo lucide. - Novo botão Posicionar com
variant={positionMode ? 'default' : 'outline'}chamandosetPositionMode(!positionMode). Label dinâmica:Posicionar/Posicionando — [nome da peça ativa].
- Importar ícone
Detalhes técnicos
- A translação é gravada em
fineTuning.pos{X,Y,Z}(espaço local da peça, antes dorenderFactorda escala). Para que 1 pixel ↔ 1 mm visual fique coerente, o cálculo divide o delta-mundo porscaleRatio.factor(ex: em 1:50, mover 100 px arrasta o objeto 100 px de tela tanto na visualização quanto na coordenada interna). - Rotação em graus (já é o formato de
fineTuning.rotX/Y/Z), sensibilidade ~0.4°/px. - O bloqueio de outras peças é automático: o handler só atualiza a
activeModelId. Clicar em outra peça (handleronClickjá existente emGLBModel) muda a ativa. - Persistência:
setFineTuningjá chamasavePlacement(fileName, fineTuning), então sair/voltar do AR mantém posições. - Sem mudanças no AR; apenas no viewer desktop.