Files
SteelXR2/.lovable/plan.md
T
gpt-engineer-app[bot] 174d36e3b3 Changes
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
2026-05-12 11:00:31 +00:00

5.9 KiB

Objetivo

Construir uma "giga de teste" (DevKit) que vista o app com simulação completa de XR + instrumentação, permitindo:

  1. Você (sem Quest): validar quase 100% do fluxo direto no navegador, incluindo grab, posicionamento e medição.
  2. Testador (com Quest): receber um build com painel de diagnóstico visível e log persistente, devolvendo feedback objetivo.
  3. Remoção limpa: quando o app estiver maduro, apagar 1 pasta + remover 3 imports + apagar 1 flag → app puro restaurado.

Princípios de isolamento

  • Todo código do DevKit vive em src/devkit/ (pasta nova). Nada de código de simulação espalhado pelo app.
  • Ativação por flag única ?devkit=1 na URL OU localStorage.setItem('devkit', '1'). Sem flag → app roda exatamente como hoje.
  • Componentes do DevKit são montados condicionalmente em 3 pontos de injeção apenas (todos em XRSession.tsx). Esses pontos ficam marcados com comentário // DEVKIT: remove this block para facilitar a limpeza futura.
  • Zero alteração de lógica de negócio. Tudo que o DevKit faz é observar (logger), simular (fake inputs) ou adicionar UI extra (painel).

Componentes do DevKit

1. devkit/DevKitFlag.ts — detector de modo

Hook useDevKit() retorna boolean. Lê URLSearchParams + localStorage. Se true, ativa todo o resto.

2. devkit/SimXRSession.tsx — modo "Faux-XR" pra desktop

Resolve seu problema #1: validar tudo sem headset.

Quando ativado (botão "🧪 Simular XR" no header, só aparece com ?devkit=1):

  • Não chama store.enterAR() (que falha sem HTTPS/headset compatível).
  • Em vez disso, força inXR=true num estado paralelo simXR.
  • Renderiza a árvore XRGrabbable + XRModel sem XRHitTestPlacement (auto-posiciona em [0,0,-1.5]).
  • Substitui leitura de session.inputSources por uma fonte fake (ver #3).
  • Câmera fica controlável por OrbitControls (você navega como quiser).

3. devkit/FakeControllers.tsx — controles virtuais com mouse/teclado

Resolve seu problema #2: testar grab sem Touch Plus.

  • Desenha 2 esferas coloridas (L=azul, R=vermelho) na cena, posicionáveis por arrastar com mouse.
  • Atalhos teclado:
    • Q / W → segurar grip esquerdo / direito (analógico simulado em 1.0)
    • A / S → segurar trigger esquerdo / direito
    • Setas → mover controle ativo
    • Shift + Setas → mover controle no eixo Z
  • Expõe um FakeInputProvider (Context) que useControllerGrab consome quando em modo DevKit. Sem DevKit, hook continua lendo session.inputSources real.
  • Mudança mínima em useControllerGrab.ts: uma linha checando if (devkit) return useFakeInputs(). Removível.

4. devkit/DevPanel.tsx — painel de diagnóstico flutuante

Painel HTML overlay (canto direito), só visível com ?devkit=1:

  • Aba "Inputs": valores ao vivo de cada controle (real ou fake) — grip, trigger, axes, hasPose
  • Aba "Cena": posição/rotação/escala do grupo grabável, contagem de meshes, bbox
  • Aba "XR": session?.mode, hit-test ativo, planos detectados (count + labels), FPS
  • Aba "Logs": últimos 100 console.logs com timestamp, filtro por tag ([XR], [grab], [HitTest])
  • Botão "Exportar relatório" → baixa JSON com snapshot atual + screenshot do canvas. Você pede pro testador clicar isso e te enviar o arquivo.

5. devkit/XRDevHud.tsx — HUD in-world expandido (substitui o XRDebugHud atual quando ativo)

Painel 3D maior, ancorado no pulso esquerdo (não na câmera, pra não atrapalhar). Mostra mesmas infos da aba "Inputs" + "XR" do DevPanel. Visível dentro do headset, essencial pro testador.

6. devkit/SmokeTest.tsx — roteiro automático

Rota nova /devkit/smoke (só roteada com ?devkit=1):

  • Sequência scriptada: carrega demo → simula grip esquerdo → move 50cm → solta → mede 2 pontos → screenshot → checklist.
  • Cada passo mostra / + tempo.
  • Você roda antes de mandar build pro testador.

7. devkit/RecordSession.tsx — gravador de "macros"

Botão "Gravar" no DevPanel: captura por 30s todos inputs + posições da cena num JSON. Botão "Reproduzir": replay do macro. Útil pra reproduzir um bug que o testador relatou ("clico aqui, viro assim, peça desaparece").

Pontos de injeção em XRSession.tsx

Apenas 3 blocos curtos, todos cercados por {devkit && <... />}:

// DEVKIT: remove this block
{devkit && <SimXRButton onActivate={setSimXR} />}

// DEVKIT: remove this block  
{devkit && simXR && <FakeControllers />}

// DEVKIT: remove this block
{devkit && <DevPanel />}

E uma linha em useControllerGrab.ts:

// DEVKIT: remove this conditional
if (typeof window !== 'undefined' && useDevKitFake()) return fakeRef;

Como remover o DevKit no futuro (1 minuto)

  1. rm -rf src/devkit/
  2. Em XRSession.tsx: deletar 3 blocos marcados // DEVKIT: + import.
  3. Em useControllerGrab.ts: deletar linha marcada // DEVKIT:.
  4. Pronto — app puro, zero resíduo.

Entregas desta primeira leva (priorizadas)

Pra não fazer tudo de uma vez, proponho entregar nesta ordem, validando cada etapa antes da próxima:

Fase 1 (essencial — destrava você hoje):

  • DevKitFlag + SimXRSession + FakeControllers + DevPanel (aba Inputs + Logs)

Fase 2 (essencial — instrumenta o testador):

  • XRDevHud expandido + DevPanel aba Cena/XR + Exportar relatório

Fase 3 (qualidade de vida):

  • SmokeTest + RecordSession

Posso entregar a Fase 1 inteira agora numa única leva, e as fases 2 e 3 sob demanda quando você validar que a 1 te serve. Cabe?

Detalhes técnicos

  • Sem novas dependências. Tudo com Three.js, R3F, Zustand já presentes.
  • TypeScript rigoroso. Tipos compartilhados entre real e fake (mesma interface ControllerGrabSnapshot).
  • Zero impacto em produção: sem flag, bundle do DevKit nem é importado se usarmos React.lazy() na entrada.
  • Hot-swappable: ligar/desligar o DevKit não recarrega a página (estado da cena preservado).