🚀 Auto-deploy: melhoria no snap e medição AR em 25/05/2026 01:28:33
This commit is contained in:
+75
-35
@@ -538,6 +538,26 @@ function HologramModel({ model, presentationState }: { model: SceneModel; presen
|
||||
|
||||
// Cenário da Sala de Reunião Clara
|
||||
function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode }: { currentActiveModel: SceneModel | null; presentationState: PresentationState; isFocusMode: boolean }) {
|
||||
const tableGeom = useMemo(() => {
|
||||
// Geometria da mesa em U / Retangular de cantos arredondados
|
||||
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 });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<group>
|
||||
{/* Luzes da Sala / Foco */}
|
||||
@@ -577,29 +597,28 @@ function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusM
|
||||
<meshStandardMaterial color="#bae6fd" roughness={0.1} emissive="#bae6fd" emissiveIntensity={0.4} />
|
||||
</mesh>
|
||||
|
||||
{/* Mesa Cilíndrica Central de 1m de diâmetro (raio 0.5) */}
|
||||
<group position={[0, 0, 0]}>
|
||||
{/* Base no chão */}
|
||||
<mesh position={[0, 0.01, 0]} castShadow receiveShadow>
|
||||
<cylinderGeometry args={[0.25, 0.25, 0.02, 32]} />
|
||||
<meshStandardMaterial color="#475569" metalness={0.7} roughness={0.2} />
|
||||
</mesh>
|
||||
{/* Coluna / Pé da mesa */}
|
||||
<mesh position={[0, 0.45, 0]} castShadow receiveShadow>
|
||||
<cylinderGeometry args={[0.06, 0.06, 0.9, 32]} />
|
||||
<meshStandardMaterial color="#64748b" metalness={0.8} roughness={0.1} />
|
||||
</mesh>
|
||||
{/* Tampo da mesa (Diâmetro 1m, altura 0.9m) */}
|
||||
<mesh position={[0, 0.9, 0]} castShadow receiveShadow>
|
||||
<cylinderGeometry args={[0.5, 0.5, 0.06, 48]} />
|
||||
<meshStandardMaterial color="#d97706" roughness={0.4} metalness={0.1} />
|
||||
</mesh>
|
||||
{/* Projetor de Holograma (Centro da mesa) */}
|
||||
<mesh position={[0, 0.931, 0]} rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<ringGeometry args={[0.22, 0.25, 32]} />
|
||||
<meshBasicMaterial color="#0ea5e9" transparent opacity={0.6} />
|
||||
{/* Mesa Elíptica/Retangular com furo central (Madeira Mel Carvalho Clara) */}
|
||||
<group position={[0, 0.8, 0]} rotation={[Math.PI / 2, 0, 0]}>
|
||||
<mesh geometry={tableGeom} castShadow receiveShadow>
|
||||
<meshStandardMaterial color="#d97706" roughness={0.2} metalness={0.1} />
|
||||
</mesh>
|
||||
</group>
|
||||
|
||||
{/* Pés da mesa (Cromados) */}
|
||||
{[-1.3, 1.3].map((x) =>
|
||||
[-0.7, 0.7].map((z) => (
|
||||
<mesh key={`${x}-${z}`} position={[x, 0.4, z]} castShadow receiveShadow>
|
||||
<cylinderGeometry args={[0.035, 0.035, 0.8]} />
|
||||
<meshStandardMaterial color="#d4d4d8" metalness={0.9} roughness={0.1} />
|
||||
</mesh>
|
||||
))
|
||||
)}
|
||||
|
||||
{/* Projetor de Holograma / Círculo centralizado desenhado na mesa */}
|
||||
<mesh position={[0, 0.861, 0]} rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<ringGeometry args={[0.22, 0.25, 32]} />
|
||||
<meshBasicMaterial color="#0ea5e9" transparent opacity={0.6} />
|
||||
</mesh>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -787,18 +806,28 @@ export default function MeetingRoom() {
|
||||
tempChannel
|
||||
.on('presence', { event: 'sync' }, () => {
|
||||
const state = tempChannel.presenceState();
|
||||
console.log("👥 [Lobby Watcher Sync] Estado de presença bruto:", state);
|
||||
const formattedPeers: Record<string, PeerData> = {};
|
||||
|
||||
Object.keys(state).forEach((chairKey) => {
|
||||
// Ignora outros watchers do lobby
|
||||
if (chairKey.startsWith('lobby_watcher_')) return;
|
||||
|
||||
const presences = state[chairKey] as unknown as PeerData[];
|
||||
Object.keys(state).forEach((key) => {
|
||||
if (key.startsWith('lobby_watcher_')) return;
|
||||
const presences = state[key] as unknown as PeerData[];
|
||||
if (presences && presences.length > 0) {
|
||||
formattedPeers[chairKey] = presences[0];
|
||||
presences.forEach((presence) => {
|
||||
if (presence && presence.chairId && presence.username) {
|
||||
formattedPeers[presence.chairId] = {
|
||||
...presence,
|
||||
avatarId: Number(presence.avatarId) || 1,
|
||||
cargo: presence.cargo || 'Colaborador',
|
||||
empresa: presence.empresa || 'SteelXR Corp',
|
||||
role: presence.role || 'guest'
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log("👥 [Lobby Watcher Sync] Peers formatados:", formattedPeers);
|
||||
setPeers(formattedPeers);
|
||||
})
|
||||
.subscribe();
|
||||
@@ -862,28 +891,39 @@ export default function MeetingRoom() {
|
||||
|
||||
const channel = supabase.channel(`meeting_room_${finalRoomId}`, {
|
||||
config: {
|
||||
broadcast: { self: true },
|
||||
presence: { key: selectedChair },
|
||||
broadcast: { self: true }
|
||||
},
|
||||
});
|
||||
|
||||
channelRef.current = channel;
|
||||
|
||||
// Sincroniza participantes online
|
||||
// Sincroniza participantes online com tolerância a múltiplos formatos e falhas de conexão
|
||||
channel
|
||||
.on('presence', { event: 'sync' }, () => {
|
||||
const state = channel.presenceState();
|
||||
console.log("👥 [Presence Sync] Estado de presença bruto da reunião:", state);
|
||||
const formattedPeers: Record<string, PeerData> = {};
|
||||
let count = 0;
|
||||
|
||||
Object.keys(state).forEach((chairKey) => {
|
||||
if (chairKey.startsWith('lobby_watcher_')) return;
|
||||
const presences = state[chairKey] as unknown as PeerData[];
|
||||
Object.keys(state).forEach((key) => {
|
||||
if (key.startsWith('lobby_watcher_')) return;
|
||||
const presences = state[key] as unknown as PeerData[];
|
||||
if (presences && presences.length > 0) {
|
||||
formattedPeers[chairKey] = presences[0];
|
||||
count++;
|
||||
presences.forEach((presence) => {
|
||||
if (presence && presence.chairId && presence.username) {
|
||||
formattedPeers[presence.chairId] = {
|
||||
...presence,
|
||||
avatarId: Number(presence.avatarId) || 1,
|
||||
cargo: presence.cargo || 'Colaborador',
|
||||
empresa: presence.empresa || 'SteelXR Corp',
|
||||
role: presence.role || 'guest'
|
||||
};
|
||||
count++;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log("👥 [Presence Sync] Peers formatados:", formattedPeers);
|
||||
setPeers(formattedPeers);
|
||||
setActiveUsersCount(count);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user