🚀 Auto-deploy: melhoria no snap e medição AR em 30/05/2026 12:24:45
This commit is contained in:
+33
-13
@@ -32,7 +32,7 @@ class ModelErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBounda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
import { Canvas, useFrame } from '@react-three/fiber';
|
import { Canvas, useFrame } from '@react-three/fiber';
|
||||||
import { OrbitControls, Text, useGLTF, Billboard, Html } from '@react-three/drei';
|
import { OrbitControls, Text, useGLTF, Billboard, Html, TransformControls } from '@react-three/drei';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { useModelStore, type SceneModel } from '@/stores/useModelStore';
|
import { useModelStore, type SceneModel } from '@/stores/useModelStore';
|
||||||
@@ -527,12 +527,13 @@ function RealMiiAvatar({
|
|||||||
|
|
||||||
// Carregador e Escalador Inteligente da Maquete Holográfica
|
// Carregador e Escalador Inteligente da Maquete Holográfica
|
||||||
// Carregador e Escalador Inteligente da Maquete Holográfica
|
// Carregador e Escalador Inteligente da Maquete Holográfica
|
||||||
function HologramModel({ model, presentationState }: { model: SceneModel; presentationState: PresentationState }) {
|
function HologramModel({ model, presentationState, isPresenter, onPresentationChange }: { model: SceneModel; presentationState: PresentationState; isPresenter: boolean; onPresentationChange: (state: Partial<PresentationState>) => void }) {
|
||||||
const { scene } = useGLTF(model.url);
|
const { scene } = useGLTF(model.url);
|
||||||
const clone = useMemo(() => scene.clone(), [scene]);
|
const clone = useMemo(() => scene.clone(), [scene]);
|
||||||
const presentationGroupRef = useRef<THREE.Group>(null);
|
const presentationGroupRef = useRef<THREE.Group>(null);
|
||||||
const baseScaleRef = useRef<number>(1);
|
const baseScaleRef = useRef<number>(1);
|
||||||
const centerRef = useRef<THREE.Vector3>(new THREE.Vector3());
|
const centerRef = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||||
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
|
||||||
// Calcula escala de aproximadamente 1 metro para caber na mesa (apenas UMA vez no carregamento)
|
// Calcula escala de aproximadamente 1 metro para caber na mesa (apenas UMA vez no carregamento)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -589,12 +590,10 @@ function HologramModel({ model, presentationState }: { model: SceneModel; presen
|
|||||||
|
|
||||||
// Aplica transformações de Rotação e Escala compartilhadas no grupo externo de apresentação
|
// Aplica transformações de Rotação e Escala compartilhadas no grupo externo de apresentação
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (presentationGroupRef.current && presentationState) {
|
if (presentationGroupRef.current && presentationState && !isDragging) {
|
||||||
const { rotation, scale } = presentationState;
|
const { rotation, scale } = presentationState;
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
presentationGroupRef.current.rotation.x = rotation[0];
|
presentationGroupRef.current.rotation.set(rotation[0], rotation[1], rotation[2]);
|
||||||
presentationGroupRef.current.rotation.y = rotation[1];
|
|
||||||
presentationGroupRef.current.rotation.z = rotation[2];
|
|
||||||
}
|
}
|
||||||
if (scale) {
|
if (scale) {
|
||||||
presentationGroupRef.current.scale.setScalar(baseScaleRef.current * scale);
|
presentationGroupRef.current.scale.setScalar(baseScaleRef.current * scale);
|
||||||
@@ -666,15 +665,35 @@ function HologramModel({ model, presentationState }: { model: SceneModel; presen
|
|||||||
}, [calQuatArr]);
|
}, [calQuatArr]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// Grupo Externo de Apresentação Compartilhada
|
<>
|
||||||
|
{isPresenter && (
|
||||||
|
<TransformControls
|
||||||
|
object={presentationGroupRef}
|
||||||
|
mode="rotate"
|
||||||
|
size={0.6}
|
||||||
|
onDraggingChanged={(e) => setIsDragging(!!e?.value)}
|
||||||
|
onChange={() => {
|
||||||
|
if (isDragging && presentationGroupRef.current) {
|
||||||
|
onPresentationChange({
|
||||||
|
rotation: [
|
||||||
|
presentationGroupRef.current.rotation.x,
|
||||||
|
presentationGroupRef.current.rotation.y,
|
||||||
|
presentationGroupRef.current.rotation.z
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{/* Grupo Externo de Apresentação Compartilhada */}
|
||||||
<group ref={presentationGroupRef}>
|
<group ref={presentationGroupRef}>
|
||||||
{/* Grupo de Translação Fina */}
|
{/* Ignoramos fineTuning.posX/Y/Z para ancorar perfeitamente à mesa */}
|
||||||
<group position={[fineTuning.posX, fineTuning.posY, fineTuning.posZ]}>
|
<group>
|
||||||
{/* Grupo de Rotação Fina e Escala Fina */}
|
{/* Grupo de Rotação Fina e Escala Fina */}
|
||||||
<group rotation={[rotXRad, rotYRad, rotZRad]} scale={[s, s, s]}>
|
<group rotation={[rotXRad, rotYRad, rotZRad]} scale={[s, s, s]}>
|
||||||
{/* Grupo de Calibração */}
|
{/* Grupo de Calibração */}
|
||||||
<group quaternion={calQuat}>
|
<group quaternion={calQuat}>
|
||||||
{/* Grupo de Centralização do Bounding Box (para girar em torno do seu centro geométrico) */}
|
{/* Grupo de Centralização do Bounding Box */}
|
||||||
<group position={[-centerRef.current.x, -centerRef.current.y, -centerRef.current.z]}>
|
<group position={[-centerRef.current.x, -centerRef.current.y, -centerRef.current.z]}>
|
||||||
<primitive object={clone} />
|
<primitive object={clone} />
|
||||||
</group>
|
</group>
|
||||||
@@ -682,11 +701,12 @@ function HologramModel({ model, presentationState }: { model: SceneModel; presen
|
|||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cenário da Sala de Reunião Clara
|
// Cenário da Sala de Reunião Clara
|
||||||
function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode }: { currentActiveModel: SceneModel | null; presentationState: PresentationState; isFocusMode: boolean }) {
|
function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode, isPresenter, onPresentationChange }: { currentActiveModel: SceneModel | null; presentationState: PresentationState; isFocusMode: boolean; isPresenter: boolean; onPresentationChange: (state: Partial<PresentationState>) => void }) {
|
||||||
const tableGeom = useMemo(() => {
|
const tableGeom = useMemo(() => {
|
||||||
// Geometria da mesa em U / Retangular de cantos arredondados
|
// Geometria da mesa em U / Retangular de cantos arredondados
|
||||||
const shape = new THREE.Shape();
|
const shape = new THREE.Shape();
|
||||||
@@ -793,7 +813,7 @@ function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusM
|
|||||||
</mesh>
|
</mesh>
|
||||||
}>
|
}>
|
||||||
{currentActiveModel ? (
|
{currentActiveModel ? (
|
||||||
<HologramModel model={currentActiveModel} presentationState={presentationState} />
|
<HologramModel model={currentActiveModel} presentationState={presentationState} isPresenter={isPresenter} onPresentationChange={onPresentationChange} />
|
||||||
) : (
|
) : (
|
||||||
// Holograma Padrão Geométrico se não houver maquete carregada
|
// Holograma Padrão Geométrico se não houver maquete carregada
|
||||||
<group rotation={[0, Date.now() * 0.00012, 0]}>
|
<group rotation={[0, Date.now() * 0.00012, 0]}>
|
||||||
@@ -1717,7 +1737,7 @@ export default function MeetingRoom() {
|
|||||||
<div className="flex-1 h-full relative">
|
<div className="flex-1 h-full relative">
|
||||||
{isWebGLSupported ? (
|
{isWebGLSupported ? (
|
||||||
<Canvas camera={{ position: [0, 2.5, 2.8], fov: 45 }} shadows gl={{ localClippingEnabled: true }}>
|
<Canvas camera={{ position: [0, 2.5, 2.8], fov: 45 }} shadows gl={{ localClippingEnabled: true }}>
|
||||||
<ThreeMeetingRoomScene currentActiveModel={activeModel} presentationState={presentationState} isFocusMode={isFocusMode} />
|
<ThreeMeetingRoomScene currentActiveModel={activeModel} presentationState={presentationState} isFocusMode={isFocusMode} isPresenter={isPresenter} onPresentationChange={handlePresentationChange} />
|
||||||
|
|
||||||
{/* Renderizar avatares de TODOS na sala - Ocultados se modo foco */}
|
{/* Renderizar avatares de TODOS na sala - Ocultados se modo foco */}
|
||||||
{!isFocusMode && Object.keys(mergedPeers).map((chairKey) => {
|
{!isFocusMode && Object.keys(mergedPeers).map((chairKey) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user