From 58ac69ba18fcaedcdc719e5dcb329c44af31385f Mon Sep 17 00:00:00 2001 From: Marcos Date: Sun, 12 Jul 2026 17:11:46 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Auto-deploy:=20BrainWind=20atual?= =?UTF-8?q?izado=20em=2012/07/2026=2017:11:46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- add_module_ids.js | 28 +++++++ app/src/components/SceneCanvas.tsx | 76 ++++++++++++------- app/src/components/Warehouse3D.tsx | 2 +- app/src/components/three/Bar3D.tsx | 2 +- app/src/components/three/Bridge3D.tsx | 2 +- app/src/components/three/Cylinder3D.tsx | 2 +- app/src/components/three/Dome3D.tsx | 2 +- app/src/components/three/Dynamics3D.tsx | 2 +- app/src/components/three/IsolatedRoof3D.tsx | 47 ++++++++++-- app/src/components/three/Sign3D.tsx | 9 +-- app/src/components/three/Tower3D.tsx | 2 +- app/src/components/three/Vault3D.tsx | 2 +- .../components/three/ViewerOrbitControls.tsx | 46 ++++++++++- app/src/store/viewerStore.ts | 36 +++++++-- 14 files changed, 198 insertions(+), 60 deletions(-) create mode 100644 add_module_ids.js diff --git a/add_module_ids.js b/add_module_ids.js new file mode 100644 index 0000000..1dc5e52 --- /dev/null +++ b/add_module_ids.js @@ -0,0 +1,28 @@ +const fs = require('fs'); +const path = require('path'); + +const dir = path.join(__dirname, 'app/src/components/three'); +const pagesDir = path.join(__dirname, 'app/src/pages'); + +// For components that return inside them +const componentsToUpdate = [ + { file: 'app/src/components/three/Sign3D.tsx', id: 'muro_placa' }, + { file: 'app/src/components/three/IsolatedRoof3D.tsx', id: 'cobertura_isolada' }, + { file: 'app/src/components/three/Bridge3D.tsx', id: 'ponte' }, + { file: 'app/src/components/three/Vault3D.tsx', id: 'abobada' }, + { file: 'app/src/components/three/Dome3D.tsx', id: 'cupula' }, + { file: 'app/src/components/three/Cylinder3D.tsx', id: 'cilindro' }, + { file: 'app/src/components/three/Tower3D.tsx', id: 'torre' }, + { file: 'app/src/components/Warehouse3D.tsx', id: 'galpao' }, + { file: 'app/src/components/three/BarSelector3D.tsx', id: 'barras' } +]; + +for (const comp of componentsToUpdate) { + const filePath = path.join(__dirname, comp.file); + if (!fs.existsSync(filePath)) continue; + + let content = fs.readFileSync(filePath, 'utf8'); + content = content.replace(/(undefined); + interface SceneCanvasProps extends CanvasProps { fallback: ReactNode; + moduleId?: string; } function CanvasInner({ fallback: _, shadows, ...canvasProps }: SceneCanvasProps) { @@ -48,7 +51,7 @@ function CanvasInner({ fallback: _, shadows, ...canvasProps }: SceneCanvasProps) ); } -export default function SceneCanvas({ fallback, style, className, ...rest }: SceneCanvasProps) { +export default function SceneCanvas({ fallback, style, className, moduleId, ...rest }: SceneCanvasProps) { if (!isWebGLSupported()) { return (
{ + if (moduleId) { + toggleLock(moduleId); + } + }; return ( -
- - - - -
- - - - - - -

{isLocked ? 'Destravar rotação' : 'Travar rotação'}

-
-
-
+ +
+ + + + + {moduleId && ( +
+ + + + + + +

{isLocked ? 'Destravar rotação' : 'Travar rotação'}

+
+
+
+
+ )}
-
+ ); } diff --git a/app/src/components/Warehouse3D.tsx b/app/src/components/Warehouse3D.tsx index 57ba833..c5b3f14 100644 --- a/app/src/components/Warehouse3D.tsx +++ b/app/src/components/Warehouse3D.tsx @@ -370,7 +370,7 @@ export default function Warehouse3DViewer() { const maxDimension = Math.max(width, length, height); return ( - vermelho - return new THREE.Color(`hsl(${h}, 75%, 50%)`); +function pressureColor(cpe: number, isDark: boolean): THREE.Color { + if (Math.abs(cpe) < 0.05) return new THREE.Color(isDark ? '#475569' : '#cbd5e1'); + if (cpe > 0) { + // Sucção (Vermelho) + const intensity = Math.min(1, cpe / 2.0); + return new THREE.Color(`hsl(0, ${60 + intensity * 30}%, ${50 - intensity * 10}%)`); + } else { + // Pressão (Azul) + const intensity = Math.min(1, Math.abs(cpe) / 2.0); + return new THREE.Color(`hsl(210, ${60 + intensity * 30}%, ${50 - intensity * 10}%)`); + } } function IsolatedRoofModel({ @@ -56,8 +62,8 @@ function IsolatedRoofModel({ const halfDepth = depth / 2; const halfWidth = width / 2; - const windwardColor = useMemo(() => pressureColor(cpeWindward), [cpeWindward]); - const leewardColor = useMemo(() => pressureColor(cpeLeeward), [cpeLeeward]); + const windwardColor = useMemo(() => pressureColor(cpeWindward, isDark), [cpeWindward, isDark]); + const leewardColor = useMemo(() => pressureColor(cpeLeeward, isDark), [cpeLeeward, isDark]); const h_diff = depth * Math.tan(thetaRad); const h_half = (depth / 2) * Math.tan(thetaRad); @@ -214,6 +220,31 @@ function IsolatedRoofModel({ + {/* Cota de Largura (b) */} + + + + + + + + + + + + + + + b = {width}m + + + {/* Rótulo Superior */} { const intensity = Math.min(1, Math.abs(cf) / 2.0); - const hue = 220 - intensity * 220; // azul → vermelho - return new THREE.Color(`hsl(${hue}, ${60 + intensity * 30}%, ${50 - intensity * 10}%)`); + return new THREE.Color(`hsl(210, ${60 + intensity * 30}%, ${50 - intensity * 10}%)`); }, [cf]); // Pontas de extremidade (placas de extremidade opcionais) @@ -185,7 +184,7 @@ function SignModel({ {/* Texto Informativo Superior */} ; export const ViewerOrbitControls: React.FC = (props) => { - const isLocked = useViewerStore((state) => state.isLocked); + const moduleId = useContext(ViewerModuleContext); + const { locks, cameras, saveCamera } = useViewerStore(); + const { camera } = useThree(); + const controlsRef = useRef(null); - return ; + const isLocked = moduleId ? !!locks[moduleId] : false; + + // Carrega a posição salva da câmera se existir + useEffect(() => { + if (moduleId && cameras[moduleId] && controlsRef.current) { + const saved = cameras[moduleId]; + camera.position.set(saved.position[0], saved.position[1], saved.position[2]); + controlsRef.current.target.set(saved.target[0], saved.target[1], saved.target[2]); + controlsRef.current.update(); + } + }, [moduleId, camera]); // executado uma vez por módulo + + const handleEnd = () => { + if (moduleId && controlsRef.current) { + saveCamera(moduleId, { + position: [camera.position.x, camera.position.y, camera.position.z], + target: [ + controlsRef.current.target.x, + controlsRef.current.target.y, + controlsRef.current.target.z + ] + }); + } + if (props.onEnd) { + props.onEnd(undefined as any); + } + }; + + return ( + + ); }; diff --git a/app/src/store/viewerStore.ts b/app/src/store/viewerStore.ts index af78bdc..8583854 100644 --- a/app/src/store/viewerStore.ts +++ b/app/src/store/viewerStore.ts @@ -1,11 +1,33 @@ import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; -interface ViewerState { - isLocked: boolean; - toggleLock: () => void; +interface CameraState { + position: [number, number, number]; + target: [number, number, number]; } -export const useViewerStore = create((set) => ({ - isLocked: false, - toggleLock: () => set((state) => ({ isLocked: !state.isLocked })), -})); +interface ViewerState { + locks: Record; + toggleLock: (moduleId: string) => void; + cameras: Record; + saveCamera: (moduleId: string, camera: CameraState) => void; +} + +export const useViewerStore = create()( + persist( + (set) => ({ + locks: {}, + toggleLock: (moduleId) => set((state) => ({ + locks: { ...state.locks, [moduleId]: !state.locks[moduleId] } + })), + cameras: {}, + saveCamera: (moduleId, camera) => set((state) => ({ + cameras: { ...state.cameras, [moduleId]: camera } + })) + }), + { + name: 'brainwind-viewer-storage', + partialize: (state) => ({ locks: state.locks, cameras: state.cameras }), + } + ) +);