From 408eba84e02fb5e66c48cbb49abb687d7358a0bd Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Mon, 25 May 2026 01:10:53 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Auto-deploy:=20melhoria=20no=20s?= =?UTF-8?q?nap=20e=20medi=C3=A7=C3=A3o=20AR=20em=2025/05/2026=2001:10:53?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MeetingRoom.tsx | 293 ++++++++++++++++++++------------------ 1 file changed, 153 insertions(+), 140 deletions(-) diff --git a/src/pages/MeetingRoom.tsx b/src/pages/MeetingRoom.tsx index 91a0211..754e277 100644 --- a/src/pages/MeetingRoom.tsx +++ b/src/pages/MeetingRoom.tsx @@ -43,7 +43,7 @@ import { toast } from 'sonner'; import { Users, MessageSquare, Mic, MicOff, Home, Send, ArrowRight, ChevronLeft, ChevronRight, Share2, LogOut, - RotateCw, Award, ShieldAlert + RotateCw, Award, ShieldAlert, Maximize2, Minimize2 } from 'lucide-react'; // Interfaces tipadas para evitar any @@ -381,10 +381,21 @@ function HologramModel({ model, presentationState }: { model: { url: string }; p const { scene } = useGLTF(model.url); const clone = useMemo(() => scene.clone(), [scene]); const groupRef = useRef(null); + const baseScaleRef = useRef(1); + const centerOffsetRef = useRef(new THREE.Vector3()); - // Calcula escala de aproximadamente 1 metro para caber na mesa + // Calcula escala de aproximadamente 1 metro para caber na mesa (apenas UMA vez no carregamento) useEffect(() => { if (!groupRef.current) return; + + // Salva transformações antigas + const oldRot = clone.rotation.clone(); + const oldScale = clone.scale.clone(); + + // Reseta temporariamente para obter o bounding box original + clone.rotation.set(0, 0, 0); + clone.scale.setScalar(1); + const box = new THREE.Box3().setFromObject(clone); const size = new THREE.Vector3(); box.getSize(size); @@ -393,12 +404,19 @@ function HologramModel({ model, presentationState }: { model: { url: string }; p if (maxDim > 0) { const targetSize = 0.95; const scaleFactor = targetSize / maxDim; - groupRef.current.scale.setScalar(scaleFactor); + baseScaleRef.current = scaleFactor; + const center = new THREE.Vector3(); box.getCenter(center); - clone.position.copy(center).multiplyScalar(-scaleFactor); - clone.position.y += 0.02; + centerOffsetRef.current.copy(center).multiplyScalar(-scaleFactor); + centerOffsetRef.current.y += 0.02; + + clone.position.copy(centerOffsetRef.current); } + + // Restaura + clone.rotation.copy(oldRot); + clone.scale.copy(oldScale); }, [clone]); // Aplica transformações de Rotação e Escala compartilhadas @@ -411,14 +429,7 @@ function HologramModel({ model, presentationState }: { model: { url: string }; p groupRef.current.rotation.z = rotation[2]; } if (scale) { - const box = new THREE.Box3().setFromObject(clone); - const size = new THREE.Vector3(); - box.getSize(size); - const maxDim = Math.max(size.x, size.y, size.z); - if (maxDim > 0) { - const baseScale = 0.95 / maxDim; - groupRef.current.scale.setScalar(baseScale * scale); - } + groupRef.current.scale.setScalar(baseScaleRef.current * scale); } } }); @@ -473,131 +484,114 @@ function HologramModel({ model, presentationState }: { model: { url: string }; p } // Cenário da Sala de Reunião Clara -function ThreeMeetingRoomScene({ currentActiveModel, presentationState }: { currentActiveModel: { url: string; fileName: string } | null; presentationState: PresentationState }) { - const tableGeom = useMemo(() => { - // Geometria da mesa em U - const shape = new THREE.Shape(); - shape.moveTo(-1.6, -1.1); - shape.lineTo(1.6, -1.1); - shape.quadraticCurveTo(1.9, -1.1, 1.9, -0.8); - shape.lineTo(1.9, 0.8); - shape.quadraticCurveTo(1.9, 1.1, 1.6, 1.1); - shape.lineTo(-1.6, 1.1); - shape.quadraticCurveTo(-1.9, 1.1, -1.9, 0.8); - shape.lineTo(-1.9, -0.8); - shape.quadraticCurveTo(-1.9, -1.1, -1.6, -1.1); - - const hole = new THREE.Path(); - hole.absellipse(0, 0, 0.9, 0.45, 0, Math.PI * 2, true); - shape.holes.push(hole); - - return new THREE.ExtrudeGeometry(shape, { depth: 0.06, bevelEnabled: true, bevelThickness: 0.01, bevelSize: 0.01, bevelSegments: 3 }); - }, []); - +function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode }: { currentActiveModel: { url: string; fileName: string } | null; presentationState: PresentationState; isFocusMode: boolean }) { return ( - {/* Piso Clara */} - - - - + {/* Luzes da Sala / Foco */} + + - {/* Tapete Central */} - - - - - - {/* Paredes Claras */} - - - - - {/* Janelas Panorâmicas */} - - - - - - - - - - {/* Mesa Elíptica em U (Madeira Mel Carvalho Clara) */} - - - - - - - {/* Pés da mesa (Cromados) */} - {[-1.3, 1.3].map((x) => - [-0.7, 0.7].map((z) => ( - - - - - )) + {isFocusMode && ( + )} - {/* Projetor de Holograma (Centro da mesa) */} - - - - - - - - - - - - - - - {/* Modelo 3D da Maquete Holográfica */} - - - - - - - - - - - + {!isFocusMode && ( + <> + {/* Piso Clara */} + + + + + + {/* Tapete Central */} + + + + + + {/* Paredes Claras */} + + + + + {/* Janelas Panorâmicas */} + + + + + + + + + + {/* Mesa Cilíndrica Central de 1m de diâmetro (raio 0.5) */} + + {/* Base no chão */} + + + + + {/* Coluna / Pé da mesa */} + + + + + {/* Tampo da mesa (Diâmetro 1m, altura 0.9m) */} + + + + + {/* Projetor de Holograma (Centro da mesa) */} + + + + + + + )} + + {/* Modelo 3D da Maquete Holográfica */} + + + + + + + + + + + + }> + + + + }> - - - - - }> - {currentActiveModel ? ( - - ) : ( - // Holograma Padrão Geométrico se não houver maquete carregada - - - - - - - - - - - )} - - - + {currentActiveModel ? ( + + ) : ( + // Holograma Padrão Geométrico se não houver maquete carregada + + + + + + + + + + + )} + + - {/* Renderizar as Cadeiras Físicas da mesa */} - {CHAIRS.map((chair) => ( + {/* Renderizar as Cadeiras Físicas da mesa - Ocultadas no Modo Foco */} + {!isFocusMode && CHAIRS.map((chair) => ( {/* Base giratória metálica */} @@ -622,11 +616,15 @@ function ThreeMeetingRoomScene({ currentActiveModel, presentationState }: { curr ))} - {/* Iluminação Clara da Sala */} - - - - + {/* Iluminação Clara da Sala - Ocultada no Modo Foco */} + {!isFocusMode && ( + <> + + + + + + )} ); } @@ -641,6 +639,7 @@ export default function MeetingRoom() { // Estados do Lobby const [inRoom, setInRoom] = useState(false); const [isConnecting, setIsConnecting] = useState(false); + const [isFocusMode, setIsFocusMode] = useState(false); const [name, setName] = useState(''); const [cargo, setCargo] = useState(''); const [empresa, setEmpresa] = useState(''); @@ -1131,10 +1130,10 @@ export default function MeetingRoom() { {/* 3D Canvas - Sala Clara */}
- + - {/* Renderizar avatares de TODOS na sala */} - {Object.keys(peers).map((chairKey) => { + {/* Renderizar avatares de TODOS na sala - Ocultados se modo foco */} + {!isFocusMode && Object.keys(peers).map((chairKey) => { const peer = peers[chairKey]; const chairConf = CHAIRS.find((c) => c.id === peer.chairId); if (!chairConf) return null; @@ -1160,7 +1159,7 @@ export default function MeetingRoom() { minDistance={0.5} maxDistance={8} maxPolarAngle={Math.PI / 2 - 0.05} - target={[0, 0.95, 0]} + target={isFocusMode ? [0, 0, 0] : [0, 0.95, 0]} /> @@ -1334,7 +1333,7 @@ export default function MeetingRoom() {
- {/* HUD Inferior - Controles de Áudio */} + {/* HUD Inferior - Controles de Áudio & Modo Foco */}
+ +
{isPresenter ? 'Apresentação Ativa' : 'Observador'}