Ajuste de posición
This commit is contained in:
@@ -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,43 +177,50 @@ 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} minPolarAngle={Math.PI / 4} maxPolarAngle={Math.PI / 1.5} />
|
||||||
<OrbitControls ref={controlsRef} />
|
<Model
|
||||||
|
url={modelUrl}
|
||||||
|
|
||||||
<Model
|
onAnimationsLoaded={(animNames, actionMap) => {
|
||||||
url={modelUrl}
|
setAnimations(animNames);
|
||||||
onAnimationsLoaded={(animNames, actionMap) => {
|
setActions(actionMap);
|
||||||
setAnimations(animNames);
|
}}
|
||||||
setActions(actionMap);
|
onNodesLoaded={(nodeList, nodePos) => {
|
||||||
}}
|
setNodes(nodeList);
|
||||||
onNodesLoaded={(nodeList, nodePos) => {
|
setNodePositions(nodePos);
|
||||||
setNodes(nodeList);
|
}}
|
||||||
setNodePositions(nodePos);
|
/>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</XR>
|
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</div >
|
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user