mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
adding endroll
This commit is contained in:
parent
b2ce4b74bf
commit
aafcd90c35
16 changed files with 302 additions and 173 deletions
|
@ -12,6 +12,7 @@ import SSknScene from "./scenes/SSknScene";
|
||||||
import PolytanScene from "./scenes/PolytanScene";
|
import PolytanScene from "./scenes/PolytanScene";
|
||||||
import TaKScene from "./scenes/TaKScene";
|
import TaKScene from "./scenes/TaKScene";
|
||||||
import ChangeDiscScene from "./scenes/ChangeDiscScene";
|
import ChangeDiscScene from "./scenes/ChangeDiscScene";
|
||||||
|
import EndScene from "./scenes/EndScene";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const currentScene = useSceneStore((state) => state.currentScene);
|
const currentScene = useSceneStore((state) => state.currentScene);
|
||||||
|
@ -30,6 +31,7 @@ const App = () => {
|
||||||
polytan: <PolytanScene />,
|
polytan: <PolytanScene />,
|
||||||
tak: <TaKScene />,
|
tak: <TaKScene />,
|
||||||
change_disc: <ChangeDiscScene />,
|
change_disc: <ChangeDiscScene />,
|
||||||
|
end: <EndScene />,
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ const App = () => {
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</span>
|
</span>
|
||||||
<MediaPlayer />
|
{/*<MediaPlayer />*/}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
59
src/components/EndScene/EndCylinder.tsx
Normal file
59
src/components/EndScene/EndCylinder.tsx
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import React from "react";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useLoader } from "react-three-fiber";
|
||||||
|
import mainCylinder from "../../static/sprite/end_cylinder_1.png";
|
||||||
|
|
||||||
|
const EndCylinder = () => {
|
||||||
|
const mainCylinderTex = useLoader(THREE.TextureLoader, mainCylinder);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<mesh position={[0, 2.5, 0]} renderOrder={4}>
|
||||||
|
<cylinderBufferGeometry
|
||||||
|
args={[1.5, 2, 1.5, 64, 64, true]}
|
||||||
|
attach="geometry"
|
||||||
|
/>
|
||||||
|
<meshStandardMaterial
|
||||||
|
attach="material"
|
||||||
|
map={mainCylinderTex}
|
||||||
|
color={0xffffff}
|
||||||
|
transparent={true}
|
||||||
|
side={THREE.DoubleSide}
|
||||||
|
depthTest={false}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
|
||||||
|
<mesh position={[0, 0.8, 0]} renderOrder={4}>
|
||||||
|
<cylinderBufferGeometry
|
||||||
|
args={[2, 2, 1.2, 64, 64, true]}
|
||||||
|
attach="geometry"
|
||||||
|
/>
|
||||||
|
<meshStandardMaterial
|
||||||
|
attach="material"
|
||||||
|
map={mainCylinderTex}
|
||||||
|
color={0xffffff}
|
||||||
|
transparent={true}
|
||||||
|
depthTest={false}
|
||||||
|
side={THREE.DoubleSide}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
|
||||||
|
<mesh position={[0, -0.9, 0]} renderOrder={4}>
|
||||||
|
<cylinderBufferGeometry
|
||||||
|
args={[2, 1.5, 1.5, 64, 64, true]}
|
||||||
|
attach="geometry"
|
||||||
|
/>
|
||||||
|
<meshStandardMaterial
|
||||||
|
attach="material"
|
||||||
|
map={mainCylinderTex}
|
||||||
|
color={0xffffff}
|
||||||
|
transparent={true}
|
||||||
|
depthTest={false}
|
||||||
|
side={THREE.DoubleSide}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EndCylinder;
|
37
src/components/EndScene/EndSphere.tsx
Normal file
37
src/components/EndScene/EndSphere.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import React, { useRef } from "react";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useFrame, useLoader } from "react-three-fiber";
|
||||||
|
import secondCylinder from "../../static/sprite/end_cylinder_2.png";
|
||||||
|
|
||||||
|
type EndSphereProps = {
|
||||||
|
position: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const EndSphere = (props: EndSphereProps) => {
|
||||||
|
const secondCylinderTex = useLoader(THREE.TextureLoader, secondCylinder);
|
||||||
|
|
||||||
|
const meshRef = useRef<THREE.Object3D>();
|
||||||
|
useFrame(() => {
|
||||||
|
if (meshRef.current) meshRef.current.rotation.y += 0.005;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<mesh
|
||||||
|
position={props.position as [number, number, number]}
|
||||||
|
ref={meshRef}
|
||||||
|
renderOrder={3}
|
||||||
|
>
|
||||||
|
<sphereBufferGeometry args={[1, 16, 16]} attach="geometry" />
|
||||||
|
<meshStandardMaterial
|
||||||
|
attach="material"
|
||||||
|
map={secondCylinderTex}
|
||||||
|
color={0xffffff}
|
||||||
|
transparent={true}
|
||||||
|
side={THREE.DoubleSide}
|
||||||
|
depthTest={false}
|
||||||
|
opacity={0.7}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EndSphere;
|
|
@ -1,21 +1,21 @@
|
||||||
import React, { useMemo, useRef } from "react";
|
import React, { useMemo, useRef } from "react";
|
||||||
import { useFrame, useLoader } from "react-three-fiber";
|
import { useFrame, useLoader } from "react-three-fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import takIntro from "../../static/sprite/tak_intro.png";
|
import takIntro from "../static/sprite/tak_intro.png";
|
||||||
import takOutro from "../../static/sprite/tak_outro.png";
|
import takOutro from "../static/sprite/tak_outro.png";
|
||||||
import mouth1 from "../../static/sprite/mouth_1.png";
|
import mouth1 from "../static/sprite/mouth_1.png";
|
||||||
import mouth2 from "../../static/sprite/mouth_2.png";
|
import mouth2 from "../static/sprite/mouth_2.png";
|
||||||
import mouth3 from "../../static/sprite/mouth_3.png";
|
import mouth3 from "../static/sprite/mouth_3.png";
|
||||||
import mouth4 from "../../static/sprite/mouth_4.png";
|
import mouth4 from "../static/sprite/mouth_4.png";
|
||||||
import { useMediaStore } from "../../store";
|
import { useMediaStore } from "../store";
|
||||||
import { LainConstructor } from "../MainScene/Lain";
|
import { LainConstructor } from "./MainScene/Lain";
|
||||||
|
|
||||||
type LainTaKProps = {
|
type LainTaKProps = {
|
||||||
intro: boolean;
|
intro: boolean;
|
||||||
outro: boolean;
|
outro: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LainTaK = (props: LainTaKProps) => {
|
const LainSpeak = (props: LainTaKProps) => {
|
||||||
const mouth1Tex = useLoader(THREE.TextureLoader, mouth1);
|
const mouth1Tex = useLoader(THREE.TextureLoader, mouth1);
|
||||||
const mouth2Tex = useLoader(THREE.TextureLoader, mouth2);
|
const mouth2Tex = useLoader(THREE.TextureLoader, mouth2);
|
||||||
const mouth3Tex = useLoader(THREE.TextureLoader, mouth3);
|
const mouth3Tex = useLoader(THREE.TextureLoader, mouth3);
|
||||||
|
@ -80,10 +80,11 @@ const LainTaK = (props: LainTaKProps) => {
|
||||||
map={mouth4Tex}
|
map={mouth4Tex}
|
||||||
alphaTest={0.01}
|
alphaTest={0.01}
|
||||||
ref={mouthRef}
|
ref={mouthRef}
|
||||||
|
depthTest={false}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LainTaK;
|
export default LainSpeak;
|
|
@ -135,7 +135,7 @@ const Lain = (props: LainProps) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIntroFinished(true);
|
setIntroFinished(true);
|
||||||
}, 4000);
|
}, 3900);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const stopIntroAnim = useMemo(() => {
|
const stopIntroAnim = useMemo(() => {
|
||||||
|
|
|
@ -17,10 +17,17 @@ const SyncedComponentLoader = (props: SyncedComponentLoaderProps) => {
|
||||||
const [introFinished, setIntroFinished] = useState(false);
|
const [introFinished, setIntroFinished] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!props.shouldIntro) {
|
||||||
|
document.getElementsByTagName("canvas")[0].className =
|
||||||
|
"main-scene-background";
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIntroFinished(true);
|
setIntroFinished(true);
|
||||||
|
document.getElementsByTagName("canvas")[0].className =
|
||||||
|
"main-scene-background";
|
||||||
}, 4000);
|
}, 4000);
|
||||||
}, []);
|
|
||||||
|
}, [props.shouldIntro]);
|
||||||
|
|
||||||
const visible = useMemo(() => {
|
const visible = useMemo(() => {
|
||||||
if (props.paused) {
|
if (props.paused) {
|
||||||
|
@ -40,7 +47,10 @@ const SyncedComponentLoader = (props: SyncedComponentLoaderProps) => {
|
||||||
<LevelSelection />
|
<LevelSelection />
|
||||||
<GrayPlanes />
|
<GrayPlanes />
|
||||||
</group>
|
</group>
|
||||||
<Starfield />
|
<Starfield
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
introFinished={introFinished}
|
||||||
|
/>
|
||||||
<Site shouldIntro={props.shouldIntro} introFinished={introFinished} />
|
<Site shouldIntro={props.shouldIntro} introFinished={introFinished} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Star from "./Starfield/Star";
|
import Star from "./Starfield/Star";
|
||||||
|
|
||||||
const Starfield = () => {
|
type StarfieldProps = {
|
||||||
|
shouldIntro: boolean;
|
||||||
|
introFinished: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Starfield = (props: StarfieldProps) => {
|
||||||
const LCG = (a: number, c: number, m: number, s: number) => () =>
|
const LCG = (a: number, c: number, m: number, s: number) => () =>
|
||||||
(s = (s * a + c) % m);
|
(s = (s * a + c) % m);
|
||||||
|
|
||||||
|
@ -23,65 +28,103 @@ const Starfield = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const [posesBlueFromBottom, posesCyanFromBottom, posesWhiteFromBottom] = [
|
const [posesBlueFromBottom, posesCyanFromBottom, posesWhiteFromBottom] = [
|
||||||
60,
|
80,
|
||||||
60,
|
80,
|
||||||
60,
|
80,
|
||||||
].map((x) =>
|
].map((x) =>
|
||||||
Array.from({ length: x }, () => [
|
Array.from({ length: x }, () => [
|
||||||
lcgInstance() / 1000000050,
|
lcgInstance() / 1000000050,
|
||||||
lcgInstance() / 100000099 - 10,
|
lcgInstance() / 100000099 - 15,
|
||||||
lcgInstance() / 1000000050,
|
lcgInstance() / 1000000050,
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
const [mainVisible, setMainVisible] = useState(false);
|
const [mainVisible, setMainVisible] = useState(false);
|
||||||
|
const [introVisible, setIntroVisible] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setMainVisible(true);
|
setMainVisible(true);
|
||||||
}, 3700);
|
}, 2800);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIntroVisible(false);
|
||||||
|
}, 3200);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<group position={[0, -1, 2]} visible={mainVisible}>
|
<group
|
||||||
|
position={[0, -1, 2]}
|
||||||
|
visible={props.shouldIntro ? mainVisible : true}
|
||||||
|
>
|
||||||
<group rotation={[0, 0.75, Math.PI / 2]} position={[-0.7, -1, -5]}>
|
<group rotation={[0, 0.75, Math.PI / 2]} position={[-0.7, -1, -5]}>
|
||||||
{posesBlueFromLeft.map((poses, idx) => (
|
{posesBlueFromLeft.map((poses, idx) => (
|
||||||
<Star position={poses} color={"blue"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"blue"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
{posesWhiteFromLeft.map((poses, idx) => (
|
{posesWhiteFromLeft.map((poses, idx) => (
|
||||||
<Star position={poses} color={"white"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"white"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
{posesCyanFromLeft.map((poses, idx) => (
|
{posesCyanFromLeft.map((poses, idx) => (
|
||||||
<Star position={poses} color={"cyan"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"cyan"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</group>
|
</group>
|
||||||
<group rotation={[0, 2.5, Math.PI / 2]} position={[-0.7, -1, -1]}>
|
<group rotation={[0, 2.5, Math.PI / 2]} position={[-0.7, -1, -1]}>
|
||||||
{posesBlueFromRight.map((poses, idx) => (
|
{posesBlueFromRight.map((poses, idx) => (
|
||||||
<Star position={poses} color={"blue"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"blue"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
{posesWhiteFromRight.map((poses, idx) => (
|
{posesWhiteFromRight.map((poses, idx) => (
|
||||||
<Star position={poses} color={"white"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"white"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
{posesCyanFromRight.map((poses, idx) => (
|
{posesCyanFromRight.map((poses, idx) => (
|
||||||
<Star position={poses} color={"cyan"} key={idx} />
|
<Star
|
||||||
|
position={poses}
|
||||||
|
color={"cyan"}
|
||||||
|
key={idx}
|
||||||
|
shouldIntro={props.shouldIntro}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group
|
{introVisible && props.shouldIntro ? (
|
||||||
position={[-2, -15, -19]}
|
<group position={[-2, -15, -30]} rotation={[Math.PI / 3, 0, 0]}>
|
||||||
rotation={[Math.PI / 4, 0, 0]}
|
{posesBlueFromBottom.map((poses, idx) => (
|
||||||
>
|
<Star position={poses} color={"blue"} key={idx} introStar={true} />
|
||||||
{posesBlueFromBottom.map((poses, idx) => (
|
))}
|
||||||
<Star position={poses} color={"blue"} key={idx} introStar={true} />
|
{posesWhiteFromBottom.map((poses, idx) => (
|
||||||
))}
|
<Star position={poses} color={"white"} key={idx} introStar={true} />
|
||||||
{posesWhiteFromBottom.map((poses, idx) => (
|
))}
|
||||||
<Star position={poses} color={"white"} key={idx} introStar={true} />
|
{posesCyanFromBottom.map((poses, idx) => (
|
||||||
))}
|
<Star position={poses} color={"cyan"} key={idx} introStar={true} />
|
||||||
{posesCyanFromBottom.map((poses, idx) => (
|
))}
|
||||||
<Star position={poses} color={"cyan"} key={idx} introStar={true} />
|
</group>
|
||||||
))}
|
) : (
|
||||||
</group>
|
<></>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@ type StarProps = {
|
||||||
position: number[];
|
position: number[];
|
||||||
color: string;
|
color: string;
|
||||||
introStar?: boolean;
|
introStar?: boolean;
|
||||||
|
shouldIntro?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Star = (props: StarProps) => {
|
const Star = (props: StarProps) => {
|
||||||
|
@ -49,7 +50,7 @@ const Star = (props: StarProps) => {
|
||||||
|
|
||||||
const amp = useRef(Math.random() / 10);
|
const amp = useRef(Math.random() / 10);
|
||||||
|
|
||||||
const introAmpRef = useRef(1);
|
const introAmpRef = useRef(props.shouldIntro ? 1 : 0);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (starRef.current) {
|
if (starRef.current) {
|
||||||
|
@ -61,7 +62,7 @@ const Star = (props: StarProps) => {
|
||||||
}
|
}
|
||||||
starRef.current.position.y += 0.01 + amp.current + introAmpRef.current;
|
starRef.current.position.y += 0.01 + amp.current + introAmpRef.current;
|
||||||
if (introAmpRef.current > 0) {
|
if (introAmpRef.current > 0) {
|
||||||
introAmpRef.current -= 0.003;
|
introAmpRef.current -= 0.004;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,11 +57,9 @@ const Images = () => {
|
||||||
"../../static/media_images/" + currentSite + "/" + img[1] + ".png"
|
"../../static/media_images/" + currentSite + "/" + img[1] + ".png"
|
||||||
).then((imageSrc: { default: string }) => {
|
).then((imageSrc: { default: string }) => {
|
||||||
imgArr.splice(parseInt(img[0]), 0, imageSrc);
|
imgArr.splice(parseInt(img[0]), 0, imageSrc);
|
||||||
console.log(imgTries);
|
|
||||||
if (imgTries === 3) {
|
if (imgTries === 3) {
|
||||||
setSceneImages(imgArr);
|
setSceneImages(imgArr);
|
||||||
new THREE.TextureLoader().load(imgArr[0].default, setActiveImage);
|
new THREE.TextureLoader().load(imgArr[0].default, setActiveImage);
|
||||||
console.log(imgArr);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, {
|
||||||
createRef,
|
createRef,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
|
@ -21,6 +22,8 @@ const MediaPlayer = () => {
|
||||||
const [mediaSource, setMediaSource] = useState<any>();
|
const [mediaSource, setMediaSource] = useState<any>();
|
||||||
|
|
||||||
const currentScene = useSceneStore((state) => state.currentScene);
|
const currentScene = useSceneStore((state) => state.currentScene);
|
||||||
|
const setScene = useSceneStore((state) => state.setScene);
|
||||||
|
|
||||||
const setPercentageElapsed = useMediaStore(
|
const setPercentageElapsed = useMediaStore(
|
||||||
(state) => state.setPercentageElapsed
|
(state) => state.setPercentageElapsed
|
||||||
);
|
);
|
||||||
|
@ -33,7 +36,9 @@ const MediaPlayer = () => {
|
||||||
|
|
||||||
const currentSite = useSiteStore((state) => state.currentSite);
|
const currentSite = useSiteStore((state) => state.currentSite);
|
||||||
|
|
||||||
const siteData = currentSite === "a" ? site_a : site_b;
|
const siteData = useMemo(() => (currentSite === "a" ? site_a : site_b), [
|
||||||
|
currentSite,
|
||||||
|
]);
|
||||||
|
|
||||||
const updateTime = useCallback(() => {
|
const updateTime = useCallback(() => {
|
||||||
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
||||||
|
@ -45,12 +50,26 @@ const MediaPlayer = () => {
|
||||||
if (percentageElapsed % 5 === 0) {
|
if (percentageElapsed % 5 === 0) {
|
||||||
setPercentageElapsed(percentageElapsed);
|
setPercentageElapsed(percentageElapsed);
|
||||||
if (percentageElapsed === 100) {
|
if (percentageElapsed === 100) {
|
||||||
videoRef.current.pause();
|
|
||||||
videoRef.current.currentTime = 0;
|
videoRef.current.currentTime = 0;
|
||||||
|
if (
|
||||||
|
(siteData as SiteType)[activeLevel][activeNodeId]
|
||||||
|
.triggers_final_video === 1
|
||||||
|
) {
|
||||||
|
setScene("end");
|
||||||
|
} else {
|
||||||
|
videoRef.current.pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [setPercentageElapsed, videoRef]);
|
}, [
|
||||||
|
activeLevel,
|
||||||
|
activeNodeId,
|
||||||
|
setPercentageElapsed,
|
||||||
|
setScene,
|
||||||
|
siteData,
|
||||||
|
videoRef,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
||||||
|
@ -59,7 +78,15 @@ const MediaPlayer = () => {
|
||||||
}, [updateTime]);
|
}, [updateTime]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentScene === "media" || currentScene === "tak") {
|
if (currentScene === "end") {
|
||||||
|
import("../../static/movie/b/ENDROLL1.STR[0].webm").then((media) => {
|
||||||
|
setMediaSource(media.default);
|
||||||
|
if (videoRef.current) {
|
||||||
|
videoRef.current.load();
|
||||||
|
videoRef.current.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (currentScene === "media" || currentScene === "tak") {
|
||||||
const nodeMedia = (siteData as SiteType)[activeLevel][activeNodeId]
|
const nodeMedia = (siteData as SiteType)[activeLevel][activeNodeId]
|
||||||
.media_file;
|
.media_file;
|
||||||
if (nodeMedia.includes("XA")) {
|
if (nodeMedia.includes("XA")) {
|
||||||
|
@ -98,7 +125,11 @@ const MediaPlayer = () => {
|
||||||
controls
|
controls
|
||||||
id="media"
|
id="media"
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
style={{ display: currentScene === "media" ? "block" : "none" }}
|
style={{
|
||||||
|
display: ["media", "tak", "end"].includes(currentScene)
|
||||||
|
? "block"
|
||||||
|
: "none",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<source src={mediaSource} />
|
<source src={mediaSource} />
|
||||||
<track src={t} kind="captions" default />
|
<track src={t} kind="captions" default />
|
||||||
|
|
|
@ -4,99 +4,25 @@ import grayTextureFile from "../../../../static/sprite/gray_box.png";
|
||||||
import darkGrayTextureFile from "../../../../static/sprite/dark_gray_box.png";
|
import darkGrayTextureFile from "../../../../static/sprite/dark_gray_box.png";
|
||||||
import React, { useRef } from "react";
|
import React, { useRef } from "react";
|
||||||
import { ShapeProps } from "../LeftSide";
|
import { ShapeProps } from "../LeftSide";
|
||||||
|
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||||
|
|
||||||
|
type GLTFResult = GLTF & {
|
||||||
|
nodes: {
|
||||||
|
Cube001: THREE.Mesh;
|
||||||
|
};
|
||||||
|
materials: {
|
||||||
|
["Material.001"]: THREE.MeshStandardMaterial;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const TriangularPrism = (props: ShapeProps) => {
|
const TriangularPrism = (props: ShapeProps) => {
|
||||||
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
||||||
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
||||||
|
|
||||||
|
const { nodes } = useLoader<GLTFResult>(GLTFLoader, "models/cutcube.glb");
|
||||||
|
|
||||||
const prismRef = useRef<THREE.Object3D>();
|
const prismRef = useRef<THREE.Object3D>();
|
||||||
|
|
||||||
const verts = new Float32Array([
|
|
||||||
// Top
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
|
|
||||||
// Sides
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
|
|
||||||
// Hypotenuse
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (props.selectable && props.active) {
|
if (props.selectable && props.active) {
|
||||||
prismRef.current!.rotation.y -= 0.015;
|
prismRef.current!.rotation.y -= 0.015;
|
||||||
|
@ -107,40 +33,18 @@ const TriangularPrism = (props: ShapeProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<mesh
|
<mesh
|
||||||
scale={[0.45, 0.5, 0.45]}
|
scale={[0.45/2, 0.5/2, 0.45/2]}
|
||||||
position={props.position as [number, number, number]}
|
position={props.position as [number, number, number]}
|
||||||
rotation-y={0.15}
|
rotation-y={0.15}
|
||||||
rotation-z={-0.02}
|
rotation-z={-0.02}
|
||||||
ref={prismRef}
|
ref={prismRef}
|
||||||
|
geometry={nodes["Cube001"].geometry}
|
||||||
>
|
>
|
||||||
<boxBufferGeometry args={[1, 1, 1]} attach="geometry" />
|
|
||||||
<meshLambertMaterial
|
<meshLambertMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={props.active ? grayTex : darkGrayTex}
|
map={props.active ? grayTex : darkGrayTex}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
|
|
||||||
// <mesh
|
|
||||||
// scale={[0.45, 0.5, 0.45]}
|
|
||||||
// position={props.position as [number, number, number]}
|
|
||||||
// rotation-y={0.15}
|
|
||||||
// rotation-x={-1.45}
|
|
||||||
// ref={prismRef}
|
|
||||||
// >
|
|
||||||
// <bufferGeometry attach="geometry">
|
|
||||||
// <bufferAttribute
|
|
||||||
// array={verts}
|
|
||||||
// itemSize={3}
|
|
||||||
// count={verts.length / 3}
|
|
||||||
// attachObject={["attributes", "position"]}
|
|
||||||
// />
|
|
||||||
// </bufferGeometry>
|
|
||||||
// <meshBasicMaterial
|
|
||||||
// side={THREE.DoubleSide}
|
|
||||||
// attach="material"
|
|
||||||
// map={props.active ? grayTex : darkGrayTex}
|
|
||||||
// />
|
|
||||||
// </mesh>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
38
src/scenes/EndScene.tsx
Normal file
38
src/scenes/EndScene.tsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import React, { useRef, useState } from "react";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useFrame } from "react-three-fiber";
|
||||||
|
import EndCylinder from "../components/EndScene/EndCylinder";
|
||||||
|
import EndSphere from "../components/EndScene/EndSphere";
|
||||||
|
import LainSpeak from "../components/LainSpeak";
|
||||||
|
|
||||||
|
const EndScene = () => {
|
||||||
|
const mainCylinderRef = useRef<THREE.Object3D>();
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (mainCylinderRef.current) {
|
||||||
|
mainCylinderRef.current.rotation.y -= 0.01;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [isIntro, setIsIntro] = useState(true);
|
||||||
|
const [isOutro, setIsOutro] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<pointLight position={[0, 0, 5]} intensity={0.9} />
|
||||||
|
<pointLight position={[0, 0, -5]} intensity={0.9} />
|
||||||
|
|
||||||
|
<group ref={mainCylinderRef} position={[0, -1, 2.2]}>
|
||||||
|
<EndCylinder />
|
||||||
|
</group>
|
||||||
|
<EndSphere position={[-1.8, -1.6, 1.4]} />
|
||||||
|
<EndSphere position={[1.8, -0.5, 0]} />
|
||||||
|
<EndSphere position={[2, -1.7, 1]} />
|
||||||
|
<EndSphere position={[-1.6, 1.4, 1.5]} />
|
||||||
|
<EndSphere position={[2, 1.7, -0.5]} />
|
||||||
|
<LainSpeak intro={isIntro} outro={isOutro} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EndScene;
|
|
@ -18,12 +18,10 @@ const MainScene = () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.getElementsByTagName("body")[0].className = "main-body";
|
|
||||||
return () => {
|
return () => {
|
||||||
document.getElementsByTagName("body")[0].className = "";
|
document.getElementsByTagName("canvas")[0].className = "";
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<perspectiveCamera position-z={3}>
|
<perspectiveCamera position-z={3}>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import {useLevelStore, useMediaStore, useNodeStore, useSiteStore} from "../store";
|
import {
|
||||||
|
useLevelStore,
|
||||||
|
useMediaStore,
|
||||||
|
useNodeStore,
|
||||||
|
useSiteStore,
|
||||||
|
} from "../store";
|
||||||
import LeftSide from "../components/MediaScene/Selectables/LeftSide";
|
import LeftSide from "../components/MediaScene/Selectables/LeftSide";
|
||||||
import RightSide from "../components/MediaScene/Selectables/RightSide";
|
import RightSide from "../components/MediaScene/Selectables/RightSide";
|
||||||
import AudioVisualizer from "../components/MediaScene/AudioVisualizer/AudioVisualizer";
|
import AudioVisualizer from "../components/MediaScene/AudioVisualizer/AudioVisualizer";
|
||||||
import MediaLoadingBar from "../components/MediaScene/MediaLoadingBar";
|
import MediaLoadingBar from "../components/MediaScene/MediaLoadingBar";
|
||||||
import NodeNameContainer from "../components/MediaScene/NodeNameContainer";
|
import NodeNameContainer from "../components/MediaScene/NodeNameContainer";
|
||||||
import Lof from "../components/MediaScene/Lof";
|
import Lof from "../components/MediaScene/Lof";
|
||||||
import { OrbitControls } from "@react-three/drei";
|
|
||||||
import Images from "../components/MediaScene/Images";
|
import Images from "../components/MediaScene/Images";
|
||||||
import MediumLetter from "../components/TextRenderer/MediumLetter";
|
import MediumLetter from "../components/TextRenderer/MediumLetter";
|
||||||
import site_a from "../resources/site_a.json";
|
import site_a from "../resources/site_a.json";
|
||||||
|
@ -45,12 +49,15 @@ const MediaScene = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.getElementsByTagName("canvas")[0].className =
|
document.getElementsByTagName("canvas")[0].className =
|
||||||
"media-scene-background";
|
"media-scene-background";
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.getElementsByTagName("canvas")[0].className = "";
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<perspectiveCamera position-z={3}>
|
<perspectiveCamera position-z={3}>
|
||||||
<group position={[0.4, -0.3, 0]}>
|
<group position={[0.4, -0.3, 0]}>
|
||||||
<OrbitControls />
|
|
||||||
<pointLight intensity={1.2} color={0xffffff} position={[-2, 0, 0]} />
|
<pointLight intensity={1.2} color={0xffffff} position={[-2, 0, 0]} />
|
||||||
<LeftSide activeMediaComponent={activeMediaComponent} />
|
<LeftSide activeMediaComponent={activeMediaComponent} />
|
||||||
<group position={[0, 0.5, -3]}>
|
<group position={[0, 0.5, -3]}>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import LainTaK from "../components/TaKScene/LainTaK";
|
import LainSpeak from "../components/LainSpeak";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useMediaStore, useSceneStore } from "../store";
|
import { useMediaStore, useSceneStore } from "../store";
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const TaKScene = () => {
|
||||||
const setAudioAnalyser = useMediaStore((state) => state.setAudioAnalyser);
|
const setAudioAnalyser = useMediaStore((state) => state.setAudioAnalyser);
|
||||||
const setScene = useSceneStore((state) => state.setScene);
|
const setScene = useSceneStore((state) => state.setScene);
|
||||||
|
|
||||||
const [isIntro, setIntro] = useState(true);
|
const [isIntro, setIsIntro] = useState(true);
|
||||||
const [isOutro, setIsOutro] = useState(false);
|
const [isOutro, setIsOutro] = useState(false);
|
||||||
|
|
||||||
const percentageElapsed = useMediaStore(
|
const percentageElapsed = useMediaStore(
|
||||||
|
@ -36,12 +36,12 @@ const TaKScene = () => {
|
||||||
|
|
||||||
if (mediaElement) {
|
if (mediaElement) {
|
||||||
mediaElement.play();
|
mediaElement.play();
|
||||||
setIntro(false);
|
setIsIntro(false);
|
||||||
}
|
}
|
||||||
}, 3800);
|
}, 3800);
|
||||||
}, [setAudioAnalyser]);
|
}, [setAudioAnalyser]);
|
||||||
|
|
||||||
return <LainTaK intro={isIntro} outro={isOutro} />;
|
return <LainSpeak intro={isIntro} outro={isOutro} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TaKScene;
|
export default TaKScene;
|
||||||
|
|
|
@ -444,7 +444,7 @@ export const useSSknStore = create<SSknState>((set) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSceneStore = create<SceneState>((set) => ({
|
export const useSceneStore = create<SceneState>((set) => ({
|
||||||
currentScene: "main",
|
currentScene: "end",
|
||||||
setScene: (to) => set(() => ({ currentScene: to })),
|
setScene: (to) => set(() => ({ currentScene: to })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue