feat: shade interaction
This commit is contained in:
68
src/App.tsx
68
src/App.tsx
@@ -1,3 +1,5 @@
|
||||
// TODO: handle moving the camera vs actual click
|
||||
|
||||
import { useRef, useState, type ComponentRef } from "react";
|
||||
import {
|
||||
Canvas,
|
||||
@@ -7,20 +9,23 @@ import {
|
||||
useLoader,
|
||||
} from "@react-three/fiber";
|
||||
import { OrbitControls, useAnimations } from "@react-three/drei";
|
||||
import { FBXLoader } from "three/examples/jsm/Addons.js";
|
||||
import { GLTFLoader } from "three/examples/jsm/Addons.js";
|
||||
import { LoopOnce, Vector3 } from "three";
|
||||
|
||||
import "./App.css";
|
||||
|
||||
const Room = () => {
|
||||
const controls = useRef<ComponentRef<typeof OrbitControls>>(null);
|
||||
const room = useLoader(FBXLoader, "/room.fbx");
|
||||
const { mixer } = useAnimations(room.animations, room);
|
||||
const room = useLoader(GLTFLoader, "/room.glb");
|
||||
const { mixer } = useAnimations(room.animations, room.scene);
|
||||
const [focus, setFocus] = useState<string | null>(null);
|
||||
|
||||
const cameraPosition = useRef<Vector3 | null>(null);
|
||||
const cameraTarget = useRef<Vector3>(new Vector3(0, 1, 0));
|
||||
const [windowState, setWindowState] = useState(false);
|
||||
const [shadeState, setShadeState] = useState(false);
|
||||
|
||||
const pointerDownCameraPos = useRef(new Vector3());
|
||||
|
||||
const { camera } = useThree();
|
||||
|
||||
@@ -42,22 +47,20 @@ const Room = () => {
|
||||
controls.current.target.lerp(cameraTarget.current, 0.1);
|
||||
});
|
||||
|
||||
const handleClick = (e: ThreeEvent<MouseEvent>) => {
|
||||
const handlePointerUp = (e: ThreeEvent<MouseEvent>) => {
|
||||
if (!controls.current) return;
|
||||
if (pointerDownCameraPos.current.distanceTo(camera.position) >= 0.3) return;
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
if (e.object.name.includes("Window")) {
|
||||
const clip = room.animations.find(
|
||||
(x) => x.name === "LowerWindow|LowerWindowAction",
|
||||
);
|
||||
const clip = room.animations.find((x) => x.name === "LowerWindowAction");
|
||||
if (!clip) throw "no animation";
|
||||
|
||||
const action = mixer.clipAction(clip);
|
||||
if (action.isRunning()) return;
|
||||
action.clampWhenFinished = true;
|
||||
action.setLoop(LoopOnce, 1);
|
||||
action.timeScale = windowState ? -1 : 1;
|
||||
action.timeScale = (windowState ? -1 : 1) * 1.5;
|
||||
if (windowState) {
|
||||
action.paused = false;
|
||||
action.time = action.getClip().duration;
|
||||
@@ -69,6 +72,46 @@ const Room = () => {
|
||||
setWindowState(!windowState);
|
||||
}
|
||||
|
||||
if (e.object.name.includes("Shade")) {
|
||||
{
|
||||
const clip = room.animations.find((x) => x.name === "Cube.010Action");
|
||||
if (!clip) throw "no animation";
|
||||
|
||||
const action = mixer.clipAction(clip);
|
||||
if (action.isRunning()) return;
|
||||
action.clampWhenFinished = true;
|
||||
action.setLoop(LoopOnce, 1);
|
||||
action.timeScale = (shadeState ? -1 : 1) * 1.5;
|
||||
if (shadeState) {
|
||||
action.paused = false;
|
||||
action.time = action.getClip().duration;
|
||||
} else {
|
||||
action.reset();
|
||||
}
|
||||
action.play();
|
||||
}
|
||||
{
|
||||
const clip = room.animations.find(
|
||||
(x) => x.name === "ShadeHandleAction",
|
||||
);
|
||||
if (!clip) throw "no animation";
|
||||
|
||||
const action = mixer.clipAction(clip);
|
||||
if (action.isRunning()) return;
|
||||
action.clampWhenFinished = true;
|
||||
action.setLoop(LoopOnce, 1);
|
||||
action.timeScale = (shadeState ? -1 : 1) * 1.5;
|
||||
if (shadeState) {
|
||||
action.paused = false;
|
||||
action.time = action.getClip().duration;
|
||||
} else {
|
||||
action.reset();
|
||||
}
|
||||
action.play();
|
||||
}
|
||||
setShadeState(!shadeState);
|
||||
}
|
||||
|
||||
if (e.object.name.includes("Poster") && e.object.name !== focus) {
|
||||
const objectPos = new Vector3();
|
||||
const objectDir = new Vector3();
|
||||
@@ -106,8 +149,11 @@ const Room = () => {
|
||||
enablePan={false}
|
||||
/>
|
||||
|
||||
<mesh onClick={handleClick}>
|
||||
<primitive object={room} />
|
||||
<mesh
|
||||
onPointerDown={() => pointerDownCameraPos.current.copy(camera.position)}
|
||||
onPointerUp={handlePointerUp}
|
||||
>
|
||||
<primitive object={room.scene} />
|
||||
</mesh>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user