Ajuste de posición

This commit is contained in:
2025-03-13 16:10:00 -06:00
parent 6dce45e88e
commit a004fce1e2

View File

@@ -2,19 +2,19 @@
import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib'; import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
import { Canvas } from "@react-three/fiber"; import { Canvas } from "@react-three/fiber";
import { useGLTF, useAnimations, Environment, Loader, OrbitControls, Bounds } from "@react-three/drei"; import { useGLTF, useAnimations, Environment, Loader, OrbitControls, Html, Bounds } from "@react-three/drei";
import { Suspense, useEffect, useRef, useState } from "react"; import { Suspense, useEffect, useRef, useState } from "react";
import { Play, Pause, Film, Expand, } from "lucide-react"; import { RotateCw, Play, Pause, Film, ListTree, Shrink, Expand } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from "@/components/ui/popover"; } from "@/components/ui/popover";
import { createXRStore, XR, XRControllerModel, XRHandModel } from "@react-three/xr";
import { ScrollArea } from "@/components/ui/scroll-area";
const store = createXRStore(); import { ScrollArea } from "@/components/ui/scroll-area";
import { useNavigate } from 'react-router';
// Model component // Model component
function Model({ url, onAnimationsLoaded, onNodesLoaded }: { function Model({ url, onAnimationsLoaded, onNodesLoaded }: {
@@ -44,8 +44,17 @@ function Model({ url, onAnimationsLoaded, onNodesLoaded }: {
return ( return (
<> <>
<Bounds fit margin={.9}> <Bounds fit margin={.9}>
{/* find the object in the perfect angle */}
<primitive object={scene} /> <primitive object={scene} />
</Bounds> </Bounds>
{/* {scene.children.map((node, index) => (
<Html key={index} position={[node.position.x, node.position.y + 0.5, node.position.z]}>
<div className="bg-blue-500 text-white px-2 py-1 rounded-md text-xs shadow-md">
{node.name}
</div>
</Html>
))} */}
</> </>
); );
} }
@@ -62,10 +71,19 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
const [_, setNodes] = useState<string[]>([]); const [_, setNodes] = useState<string[]>([]);
const [nodePositions, setNodePositions] = useState<Record<string, [number, number, number]>>({}); const [nodePositions, setNodePositions] = useState<Record<string, [number, number, number]>>({});
const [isFullscreen, setIsFullscreen] = useState(false);
const navigate = useNavigate();
nodePositions; nodePositions;
/* const resetView = () => {
if (controlsRef.current) {
controlsRef.current.reset();
}
}; */
const playAnimation = (name: string) => { const playAnimation = (name: string) => {
if (actions[name]) { if (actions[name]) {
Object.values(actions).forEach(action => action.stop()); // Stop other animations Object.values(actions).forEach(action => action.stop()); // Stop other animations
@@ -81,6 +99,24 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
} }
}; };
// Handle Fullscreen Mode
const toggleFullscreen = () => {
if (!document.fullscreenElement) {
containerRef.current?.requestFullscreen().then(() => {
setIsFullscreen(true);
}).catch(err => {
console.error("Error entering fullscreen:", err);
});
} else {
document.exitFullscreen().then(() => {
setIsFullscreen(false);
}).catch(err => {
console.error("Error exiting fullscreen:", err);
});
}
};
return ( return (
<div ref={containerRef} className="relative w-full grow bg-white/10 shadow-xl shadow-gray-300/25 rounded-lg p-6 backdrop-blur-lg h-100"> <div ref={containerRef} className="relative w-full grow bg-white/10 shadow-xl shadow-gray-300/25 rounded-lg p-6 backdrop-blur-lg h-100">
<div className="z-10 absolute top-4 w-100 flex wrap gap-5"> <div className="z-10 absolute top-4 w-100 flex wrap gap-5">
@@ -141,29 +177,37 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
</Popover> */} </Popover> */}
</div> </div>
<div className="absolute bottom-4 right-4 z-10 flex gap-4"> <div className="absolute bottom-4 right-4 z-10 flex gap-4">
{/* <Button
className="bg-gradient-to-r from-red-600 to-red-800 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-red-500 hover:to-red-700 active:scale-95 flex items-center gap-2 justify-center"
onClick={resetView}
>
<RotateCw className="w-5 h-5" />
Centrar cámara
</Button> */}
<Button
className="bg-gradient-to-r from-red-600 to-red-800 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-red-500 hover:to-red-700 active:scale-95 flex items-center gap-2 justify-center"
onClick={() => navigate("/")}
>
<RotateCw className="w-5 h-5" />
Regresar al menú
</Button>
{/* Botón de pantalla completa */} {/* Botón de pantalla completa */}
<Button <Button
className="bg-gradient-to-r from-gray-700 to-gray-900 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-gray-600 hover:to-gray-800 active:scale-95 flex items-center gap-2 justify-center" className="bg-gradient-to-r from-gray-700 to-gray-900 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-gray-600 hover:to-gray-800 active:scale-95 flex items-center gap-2 justify-center"
onClick={() => store.enterAR()}> onClick={toggleFullscreen} >
<Expand className="w-5 h-5" /> {isFullscreen ? <Shrink className="w-5 h-5" /> : <Expand className="w-5 h-5" />}
Entrar en AR {isFullscreen ? "Salir" : "Pantalla Completa"}
</Button>
<Button
className="bg-gradient-to-r from-gray-700 to-gray-900 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-gray-600 hover:to-gray-800 active:scale-95 flex items-center gap-2 justify-center"
onClick={() => store.enterVR()}>
<Expand className="w-5 h-5" />
Entrar en VR
</Button> </Button>
</div> </div>
<div className="w-full h-full"> <div className="w-full h-full">
<Suspense fallback={<Loader />}> <Suspense fallback={<Loader />}>
<Canvas className="w-full h-full"> <Canvas className="w-full h-full">
<XR store={store}>
<Environment preset="city" /> <Environment preset="city" />
<OrbitControls ref={controlsRef} /> <OrbitControls ref={controlsRef} minPolarAngle={Math.PI / 4} maxPolarAngle={Math.PI / 1.5} />
<Model <Model
url={modelUrl} url={modelUrl}
onAnimationsLoaded={(animNames, actionMap) => { onAnimationsLoaded={(animNames, actionMap) => {
setAnimations(animNames); setAnimations(animNames);
setActions(actionMap); setActions(actionMap);
@@ -173,11 +217,10 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
setNodePositions(nodePos); setNodePositions(nodePos);
}} }}
/> />
</XR>
</Canvas> </Canvas>
</Suspense> </Suspense>
</div> </div>
</div >
</div>
); );
} }