mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
refactored mediaplayer and fixed idles
This commit is contained in:
parent
f6ac61ff77
commit
47c65fd497
11 changed files with 206 additions and 246 deletions
|
@ -2,7 +2,7 @@ import React, { Suspense, useEffect, useMemo } from "react";
|
||||||
import MainScene from "./scenes/MainScene";
|
import MainScene from "./scenes/MainScene";
|
||||||
import "./static/css/page.css";
|
import "./static/css/page.css";
|
||||||
import { Canvas } from "react-three-fiber";
|
import { Canvas } from "react-three-fiber";
|
||||||
import MediaPlayer from "./components/MediaScene/MediaPlayer";
|
import MediaPlayer from "./components/MediaPlayer";
|
||||||
import MediaScene from "./scenes/MediaScene";
|
import MediaScene from "./scenes/MediaScene";
|
||||||
import { useStore } from "./store";
|
import { useStore } from "./store";
|
||||||
import GateScene from "./scenes/GateScene";
|
import GateScene from "./scenes/GateScene";
|
||||||
|
|
|
@ -28,6 +28,9 @@ import bootSubsceneManager from "../core/setters/boot/bootSubsceneManager";
|
||||||
import bootManager from "../core/setters/boot/bootManager";
|
import bootManager from "../core/setters/boot/bootManager";
|
||||||
import handleBootSceneKeyPress from "../core/scene-keypress-handlers/handleBootSceneKeyPress";
|
import handleBootSceneKeyPress from "../core/scene-keypress-handlers/handleBootSceneKeyPress";
|
||||||
import soundManager from "../core/setters/soundManager";
|
import soundManager from "../core/setters/soundManager";
|
||||||
|
import { useFrame } from "react-three-fiber";
|
||||||
|
import { getRandomIdleLainAnim, getRandomIdleMedia } from "../utils/idle-utils";
|
||||||
|
import idleManager from "../core/setters/main/idleManager";
|
||||||
|
|
||||||
const KeyPressHandler = () => {
|
const KeyPressHandler = () => {
|
||||||
const mediaSceneSetters = useMemo(
|
const mediaSceneSetters = useMemo(
|
||||||
|
@ -79,8 +82,36 @@ const KeyPressHandler = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const scene = useStore((state) => state.currentScene);
|
const scene = useStore((state) => state.currentScene);
|
||||||
|
const mainSubscene = useStore((state) => state.mainSubscene);
|
||||||
|
|
||||||
const timePassedSinceLastKeyPress = useRef(-1);
|
const lainIdleCounter = useRef(-1);
|
||||||
|
const idleSceneCounter = useRef(-1);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
if (
|
||||||
|
lainIdleCounter.current > -1 &&
|
||||||
|
idleSceneCounter.current > -1 &&
|
||||||
|
mainSubscene !== "pause" &&
|
||||||
|
mainSubscene !== "level_selection" &&
|
||||||
|
scene === "main"
|
||||||
|
) {
|
||||||
|
if (now > lainIdleCounter.current + 10000) {
|
||||||
|
lainManager({ event: getRandomIdleLainAnim() });
|
||||||
|
// after one idle animation plays, the second comes sooner than it would after a regular keypress
|
||||||
|
lainIdleCounter.current = now - 2500;
|
||||||
|
}
|
||||||
|
if (now > idleSceneCounter.current + 15000) {
|
||||||
|
idleManager(getRandomIdleMedia());
|
||||||
|
sceneManager({ event: "play_idle_media" });
|
||||||
|
// put it on lock until the next action, since while the idle media plays, the
|
||||||
|
// Date.now() value keeps increasing, which can result in another idle media playing right after one finishes
|
||||||
|
// one way to work around this would be to modify the value depending on the last played idle media's duration
|
||||||
|
// but i'm way too lazy for that
|
||||||
|
idleSceneCounter.current = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const handleKeyPress = useCallback(
|
const handleKeyPress = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
|
@ -91,7 +122,8 @@ const KeyPressHandler = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
if (keyPress) {
|
if (keyPress) {
|
||||||
timePassedSinceLastKeyPress.current = Date.now();
|
lainIdleCounter.current = now;
|
||||||
|
idleSceneCounter.current = now;
|
||||||
const sceneFns = (() => {
|
const sceneFns = (() => {
|
||||||
switch (scene) {
|
switch (scene) {
|
||||||
case "main":
|
case "main":
|
||||||
|
@ -120,7 +152,6 @@ const KeyPressHandler = () => {
|
||||||
};
|
};
|
||||||
case "gate":
|
case "gate":
|
||||||
case "polytan":
|
case "polytan":
|
||||||
case "about":
|
|
||||||
return {
|
return {
|
||||||
action: () => useStore.setState({ currentScene: "main" }),
|
action: () => useStore.setState({ currentScene: "main" }),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import TriangleNode from "./NodeRip/TriangleNode";
|
import TriangleNode from "./NodeRip/TriangleNode";
|
||||||
import { useStore } from "../../../../store";
|
import { useStore } from "../../../../store";
|
||||||
import RipLine from "./NodeRip/RipLine";
|
import RipLine from "./NodeRip/RipLine";
|
||||||
|
@ -13,7 +13,7 @@ const NodeRip = () => {
|
||||||
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);
|
||||||
|
|
||||||
const lcgInstance = LCG(1664525, 1013904223, 2 ** 32, 2);
|
const lcgInstance = useMemo(() => LCG(1664525, 1013904223, 2 ** 32, 2), []);
|
||||||
|
|
||||||
const firstLineSet = Array.from({ length: 25 }, (_, idx) => {
|
const firstLineSet = Array.from({ length: 25 }, (_, idx) => {
|
||||||
let coordSet = [lcgInstance() / 7000000000, lcgInstance() / 7000000000];
|
let coordSet = [lcgInstance() / 7000000000, lcgInstance() / 7000000000];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useState, memo } from "react";
|
import React, { useEffect, useState, memo, useMemo } from "react";
|
||||||
import Star from "./Starfield/Star";
|
import Star from "./Starfield/Star";
|
||||||
|
|
||||||
type StarfieldProps = {
|
type StarfieldProps = {
|
||||||
|
@ -10,7 +10,7 @@ const Starfield = memo((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);
|
||||||
|
|
||||||
const lcgInstance = LCG(1664525, 1013904223, 2 ** 32, 2);
|
const lcgInstance = useMemo(() => LCG(1664525, 1013904223, 2 ** 32, 2), []);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
posesBlueFromRight,
|
posesBlueFromRight,
|
||||||
|
|
67
src/components/MediaPlayer.tsx
Normal file
67
src/components/MediaPlayer.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import React, { createRef, useCallback, useEffect, useRef } from "react";
|
||||||
|
import { useStore } from "../store";
|
||||||
|
|
||||||
|
const MediaPlayer = () => {
|
||||||
|
const setPercentageElapsed = useStore((state) => state.setPercentageElapsed);
|
||||||
|
|
||||||
|
const requestRef = useRef();
|
||||||
|
const videoRef = createRef<HTMLVideoElement>();
|
||||||
|
const trackRef = createRef<HTMLTrackElement>();
|
||||||
|
const subtitleRef = createRef<HTMLParagraphElement>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleCueChange = (e: any) => {
|
||||||
|
const { track } = e.target;
|
||||||
|
const { activeCues } = track;
|
||||||
|
const text = [...activeCues].map(
|
||||||
|
(cue) => cue.getCueAsHTML().textContent
|
||||||
|
)[0];
|
||||||
|
if (subtitleRef.current && videoRef.current) {
|
||||||
|
if (!text || videoRef.current.currentTime === 0)
|
||||||
|
subtitleRef.current.textContent = text;
|
||||||
|
else subtitleRef.current.textContent = text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (trackRef.current) {
|
||||||
|
trackRef.current.addEventListener("cuechange", handleCueChange);
|
||||||
|
}
|
||||||
|
}, [subtitleRef, trackRef, videoRef]);
|
||||||
|
|
||||||
|
const updateTime = useCallback(() => {
|
||||||
|
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
||||||
|
if (videoRef.current) {
|
||||||
|
const timeElapsed = videoRef.current.currentTime;
|
||||||
|
const duration = videoRef.current.duration;
|
||||||
|
const percentageElapsed = Math.floor((timeElapsed / duration) * 100);
|
||||||
|
|
||||||
|
if (percentageElapsed % 5 === 0 && percentageElapsed !== 0) {
|
||||||
|
setPercentageElapsed(percentageElapsed);
|
||||||
|
if (percentageElapsed === 100 && videoRef.current)
|
||||||
|
videoRef.current.currentTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [setPercentageElapsed, videoRef]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
||||||
|
const curr = requestRef.current;
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(curr as any);
|
||||||
|
setPercentageElapsed(0);
|
||||||
|
};
|
||||||
|
}, [setPercentageElapsed, updateTime]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<video width="800" height="600" id="media" ref={videoRef} controls>
|
||||||
|
<track id={"track"} ref={trackRef} kind="captions" default />
|
||||||
|
</video>
|
||||||
|
<div id={"subtitle-container"}>
|
||||||
|
<p ref={subtitleRef} id={"subtitle"} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MediaPlayer;
|
|
@ -1,196 +0,0 @@
|
||||||
import React, {
|
|
||||||
createRef,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
} from "react";
|
|
||||||
import { useStore } from "../../store";
|
|
||||||
import endroll from "../../static/movie/ENDROLL1.STR[0].webm";
|
|
||||||
import xa0001 from "../../static/audio/Xa0001.mp4";
|
|
||||||
import xa0006 from "../../static/audio/Xa0006.mp4";
|
|
||||||
|
|
||||||
const MediaPlayer = () => {
|
|
||||||
const currentScene = useStore((state) => state.currentScene);
|
|
||||||
const setScene = useStore((state) => state.setScene);
|
|
||||||
|
|
||||||
const setPercentageElapsed = useStore((state) => state.setPercentageElapsed);
|
|
||||||
|
|
||||||
const nodeName = useStore((state) => state.activeNode.node_name);
|
|
||||||
const idleMedia = useStore((state) => state.idleMedia);
|
|
||||||
const nodeMedia = useStore((state) => state.activeNode.media_file);
|
|
||||||
|
|
||||||
const triggersFinalVideo = useStore(
|
|
||||||
(state) => state.activeNode.triggers_final_video
|
|
||||||
);
|
|
||||||
|
|
||||||
const requestRef = useRef();
|
|
||||||
const videoRef = createRef<HTMLVideoElement>();
|
|
||||||
const trackRef = createRef<HTMLTrackElement>();
|
|
||||||
const subtitleRef = createRef<HTMLParagraphElement>();
|
|
||||||
|
|
||||||
// end scene specific stuff
|
|
||||||
const endMediaPlayedCount = useStore((state) => state.endMediaPlayedCount);
|
|
||||||
const incrementEndMediaPlayedCount = useStore(
|
|
||||||
(state) => state.incrementEndMediaPlayedCount
|
|
||||||
);
|
|
||||||
const resetEndMediaPlayedCount = useStore(
|
|
||||||
(state) => state.resetEndMediaPlayedCount
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleCueChange = (e: any) => {
|
|
||||||
const { track } = e.target;
|
|
||||||
const { activeCues } = track;
|
|
||||||
const text = [...activeCues].map(
|
|
||||||
(cue) => cue.getCueAsHTML().textContent
|
|
||||||
)[0];
|
|
||||||
if (subtitleRef.current && videoRef.current) {
|
|
||||||
if (!text || videoRef.current.currentTime === 0)
|
|
||||||
subtitleRef.current.textContent = text;
|
|
||||||
else subtitleRef.current.textContent = text;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (trackRef.current) {
|
|
||||||
trackRef.current.addEventListener("cuechange", handleCueChange);
|
|
||||||
}
|
|
||||||
}, [subtitleRef, trackRef, videoRef]);
|
|
||||||
|
|
||||||
const updateTime = useCallback(() => {
|
|
||||||
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
|
||||||
if (videoRef.current) {
|
|
||||||
const timeElapsed = videoRef.current.currentTime;
|
|
||||||
const duration = videoRef.current.duration;
|
|
||||||
const percentageElapsed = Math.floor((timeElapsed / duration) * 100);
|
|
||||||
|
|
||||||
if (percentageElapsed % 5 === 0 && percentageElapsed !== 0) {
|
|
||||||
setPercentageElapsed(percentageElapsed);
|
|
||||||
if (percentageElapsed === 100) {
|
|
||||||
if (currentScene === "media") setPercentageElapsed(0);
|
|
||||||
videoRef.current.currentTime = 0;
|
|
||||||
if (currentScene === "idle_media") {
|
|
||||||
videoRef.current.pause();
|
|
||||||
setScene("main");
|
|
||||||
} else {
|
|
||||||
if (currentScene === "end") {
|
|
||||||
incrementEndMediaPlayedCount();
|
|
||||||
} else {
|
|
||||||
if (triggersFinalVideo === 1) {
|
|
||||||
resetEndMediaPlayedCount();
|
|
||||||
setScene("end");
|
|
||||||
} else {
|
|
||||||
videoRef.current.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
currentScene,
|
|
||||||
incrementEndMediaPlayedCount,
|
|
||||||
resetEndMediaPlayedCount,
|
|
||||||
setPercentageElapsed,
|
|
||||||
setScene,
|
|
||||||
triggersFinalVideo,
|
|
||||||
videoRef,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(requestRef.current as any) = requestAnimationFrame(updateTime);
|
|
||||||
const curr = requestRef.current;
|
|
||||||
return () => cancelAnimationFrame(curr as any);
|
|
||||||
}, [updateTime]);
|
|
||||||
|
|
||||||
const endMediaSource = useMemo(() => {
|
|
||||||
switch (endMediaPlayedCount) {
|
|
||||||
case 0:
|
|
||||||
return endroll;
|
|
||||||
case 1:
|
|
||||||
return xa0001;
|
|
||||||
case 2:
|
|
||||||
return xa0006;
|
|
||||||
}
|
|
||||||
}, [endMediaPlayedCount]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentScene === "end") {
|
|
||||||
if (endMediaPlayedCount === 0) {
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.load();
|
|
||||||
videoRef.current.play().catch((e) => {
|
|
||||||
console.log(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (endMediaPlayedCount === 1) {
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.load();
|
|
||||||
}
|
|
||||||
} else if (endMediaPlayedCount === 2) {
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.load();
|
|
||||||
videoRef.current.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
import("../../static/webvtt/" + nodeName + ".vtt").then((vtt) => {
|
|
||||||
if (trackRef.current) {
|
|
||||||
trackRef.current.src = vtt.default;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
currentScene === "media" ||
|
|
||||||
currentScene === "tak" ||
|
|
||||||
currentScene === "idle_media"
|
|
||||||
) {
|
|
||||||
if (currentScene === "media") setPercentageElapsed(0);
|
|
||||||
const mediaToPlay =
|
|
||||||
currentScene === "idle_media" ? idleMedia : nodeMedia;
|
|
||||||
if (mediaToPlay) {
|
|
||||||
if (mediaToPlay.includes("XA")) {
|
|
||||||
import("../../static/audio/" + mediaToPlay + ".ogg").then(
|
|
||||||
(media) => {
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.src = media.default;
|
|
||||||
videoRef.current.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
import("../../static/movie/" + mediaToPlay + "[0].webm").then(
|
|
||||||
(media) => {
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.src = media.default;
|
|
||||||
videoRef.current.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
currentScene,
|
|
||||||
endMediaPlayedCount,
|
|
||||||
idleMedia,
|
|
||||||
nodeMedia,
|
|
||||||
nodeName,
|
|
||||||
setPercentageElapsed,
|
|
||||||
trackRef,
|
|
||||||
videoRef,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<video width="800" height="600" id="media" ref={videoRef} controls>
|
|
||||||
<track ref={trackRef} kind="captions" default />
|
|
||||||
</video>
|
|
||||||
<div id={"subtitle-container"}>
|
|
||||||
<p ref={subtitleRef} id={"subtitle"} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MediaPlayer;
|
|
|
@ -1,27 +1,13 @@
|
||||||
import { useStore } from "../../../store";
|
import { useStore } from "../../../store";
|
||||||
|
|
||||||
const idleManager = (eventState: any) => {
|
const idleManager = (eventState: any) => {
|
||||||
|
const setIdleScene = useStore.getState().setIdleScene;
|
||||||
|
|
||||||
const dispatchAction = (eventState: {
|
const dispatchAction = (eventState: {
|
||||||
media: string;
|
media: string;
|
||||||
images?: { "1": string; "2": string; "3": string };
|
images: { "1": string; "2": string; "3": string } | undefined;
|
||||||
}) => {
|
nodeName: string | undefined;
|
||||||
if (eventState.images) {
|
}) => ({ action: () => setIdleScene(eventState) });
|
||||||
return {
|
|
||||||
action: () =>
|
|
||||||
useStore.setState({
|
|
||||||
idleMedia: eventState.media,
|
|
||||||
idleImages: eventState.images,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
action: () =>
|
|
||||||
useStore.setState({
|
|
||||||
idleMedia: eventState.media,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const { action } = { ...dispatchAction(eventState) };
|
const { action } = { ...dispatchAction(eventState) };
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,46 @@ import { useStore } from "../store";
|
||||||
import Images from "../components/MediaScene/Images";
|
import Images from "../components/MediaScene/Images";
|
||||||
|
|
||||||
const IdleMediaScene = () => {
|
const IdleMediaScene = () => {
|
||||||
|
const mediaPercentageElapsed = useStore(
|
||||||
|
(state) => state.mediaPercentageElapsed
|
||||||
|
);
|
||||||
|
const setScene = useStore((state) => state.setScene);
|
||||||
|
|
||||||
const idleMedia = useStore((state) => state.idleMedia);
|
const idleMedia = useStore((state) => state.idleMedia);
|
||||||
|
const idleNodeName = useStore((state) => state.idleNodeName);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mediaPercentageElapsed === 100) setScene("main");
|
||||||
|
}, [mediaPercentageElapsed, setScene]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||||
|
const trackElement = document.getElementById("track") as HTMLTrackElement;
|
||||||
|
|
||||||
if (mediaElement) {
|
if (mediaElement) {
|
||||||
mediaElement.currentTime = 0;
|
mediaElement.currentTime = 0;
|
||||||
mediaElement.play();
|
import("../static/webvtt/" + idleNodeName + ".vtt")
|
||||||
|
.then((vtt) => {
|
||||||
|
if (vtt) trackElement.src = vtt.default;
|
||||||
|
})
|
||||||
|
// some entries have no spoken words, so the file doesnt exist. we catch that here.
|
||||||
|
.catch((e) => console.log(e));
|
||||||
|
|
||||||
|
if (idleMedia.includes("XA")) {
|
||||||
|
import("../static/audio/" + idleMedia + ".ogg").then((media) => {
|
||||||
|
mediaElement.src = media.default;
|
||||||
|
mediaElement.load();
|
||||||
|
mediaElement.play();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
import("../static/movie/" + idleMedia + "[0].webm").then((media) => {
|
||||||
|
mediaElement.src = media.default;
|
||||||
|
mediaElement.load();
|
||||||
|
mediaElement.play();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, [idleMedia, idleNodeName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group visible={idleMedia.includes("XA")}>
|
<group visible={idleMedia.includes("XA")}>
|
||||||
|
|
|
@ -21,9 +21,36 @@ const MediaScene = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(()=> {
|
const nodeMedia = useStore((state) => state.activeNode.media_file);
|
||||||
console.log('rend')
|
const nodeName = useStore((state) => state.activeNode.node_name);
|
||||||
}, [])
|
|
||||||
|
useEffect(() => {
|
||||||
|
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||||
|
const trackElement = document.getElementById("track") as HTMLTrackElement;
|
||||||
|
|
||||||
|
if (mediaElement) {
|
||||||
|
mediaElement.currentTime = 0;
|
||||||
|
import("../static/webvtt/" + nodeName + ".vtt")
|
||||||
|
.then((vtt) => {
|
||||||
|
if (vtt) trackElement.src = vtt.default;
|
||||||
|
})
|
||||||
|
// some entries have no spoken words, so the file doesnt exist. we catch that here.
|
||||||
|
.catch((e) => console.log(e));
|
||||||
|
|
||||||
|
if (nodeMedia.includes("XA")) {
|
||||||
|
import("../static/audio/" + nodeMedia + ".ogg").then((media) => {
|
||||||
|
mediaElement.src = media.default;
|
||||||
|
mediaElement.load();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
import("../static/movie/" + nodeMedia + "[0].webm").then((media) => {
|
||||||
|
mediaElement.src = media.default;
|
||||||
|
mediaElement.load();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [nodeMedia, nodeName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<perspectiveCamera position-z={3}>
|
<perspectiveCamera position-z={3}>
|
||||||
<group position={[0.4, -0.3, 0]}>
|
<group position={[0.4, -0.3, 0]}>
|
||||||
|
|
22
src/store.ts
22
src/store.ts
|
@ -61,7 +61,8 @@ type State = {
|
||||||
|
|
||||||
// idle scene
|
// idle scene
|
||||||
idleMedia: string;
|
idleMedia: string;
|
||||||
idleImages: any;
|
idleImages: { "1": string; "2": string; "3": string } | undefined;
|
||||||
|
idleNodeName: string | undefined;
|
||||||
|
|
||||||
// sskn scene
|
// sskn scene
|
||||||
ssknComponentMatrix: ["ok", "cancel"];
|
ssknComponentMatrix: ["ok", "cancel"];
|
||||||
|
@ -122,7 +123,7 @@ export const useStore = create(
|
||||||
combine(
|
combine(
|
||||||
{
|
{
|
||||||
// scene data
|
// scene data
|
||||||
currentScene: "boot",
|
currentScene: "main",
|
||||||
|
|
||||||
// game progress
|
// game progress
|
||||||
gameProgress: game_progress,
|
gameProgress: game_progress,
|
||||||
|
@ -190,9 +191,10 @@ export const useStore = create(
|
||||||
wordSelected: false,
|
wordSelected: false,
|
||||||
|
|
||||||
// idle scene
|
// idle scene
|
||||||
idleMedia: "INS01.STR",
|
idleMedia: site_a["00"]["0000"].media_file,
|
||||||
|
idleNodeName: site_a["00"]["0000"].node_name,
|
||||||
// this may be undefined depending on whether or not the media is audio or not
|
// this may be undefined depending on whether or not the media is audio or not
|
||||||
idleImages: undefined,
|
idleImages: site_a["00"]["0000"].image_table_indices,
|
||||||
|
|
||||||
// sskn scene
|
// sskn scene
|
||||||
ssknComponentMatrix: ["ok", "cancel"],
|
ssknComponentMatrix: ["ok", "cancel"],
|
||||||
|
@ -346,8 +348,16 @@ export const useStore = create(
|
||||||
setWordSelected: (to: boolean) => set(() => ({ wordSelected: to })),
|
setWordSelected: (to: boolean) => set(() => ({ wordSelected: to })),
|
||||||
|
|
||||||
// idle media setters
|
// idle media setters
|
||||||
setIdleMedia: (to: any) => set(() => ({ idleMedia: to })),
|
setIdleScene: (to: {
|
||||||
setIdleImages: (to: any) => set(() => ({ idleImages: to })),
|
images: { "1": string; "2": string; "3": string } | undefined;
|
||||||
|
media: string | undefined;
|
||||||
|
nodeName: string | undefined;
|
||||||
|
}) =>
|
||||||
|
set(() => ({
|
||||||
|
idleMedia: to.media,
|
||||||
|
idleImages: to.images,
|
||||||
|
idleNodeName: to.nodeName,
|
||||||
|
})),
|
||||||
|
|
||||||
//polytan setters
|
//polytan setters
|
||||||
setPolytanPartUnlocked: (bodyPart: string) =>
|
setPolytanPartUnlocked: (bodyPart: string) =>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import site_b from "../resources/site_b.json";
|
||||||
import { SiteType } from "../components/MainScene/Site";
|
import { SiteType } from "../components/MainScene/Site";
|
||||||
import { useStore } from "../store";
|
import { useStore } from "../store";
|
||||||
|
|
||||||
export const getRandomIdleMedia = (site: string) => {
|
export const getRandomIdleMedia = () => {
|
||||||
const siteAIdleNodes = {
|
const siteAIdleNodes = {
|
||||||
audio: [
|
audio: [
|
||||||
"0000",
|
"0000",
|
||||||
|
@ -56,7 +56,9 @@ export const getRandomIdleMedia = (site: string) => {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const siteData = site === "a" ? site_a : site_b;
|
const site = useStore.getState().activeSite;
|
||||||
|
|
||||||
|
const siteData: SiteType = site === "a" ? site_a : site_b;
|
||||||
const idleNodes = site === "a" ? siteAIdleNodes : siteBIdleNodes;
|
const idleNodes = site === "a" ? siteAIdleNodes : siteBIdleNodes;
|
||||||
|
|
||||||
if (Math.random() < 0.5) {
|
if (Math.random() < 0.5) {
|
||||||
|
@ -65,19 +67,22 @@ export const getRandomIdleMedia = (site: string) => {
|
||||||
|
|
||||||
const level = nodeToPlay.substr(0, 2);
|
const level = nodeToPlay.substr(0, 2);
|
||||||
|
|
||||||
const images = (siteData as SiteType)[level][nodeToPlay]
|
const images = siteData[level][nodeToPlay].image_table_indices;
|
||||||
.image_table_indices;
|
const media = siteData[level][nodeToPlay].media_file;
|
||||||
const media = (siteData as SiteType)[level][nodeToPlay].media_file;
|
const nodeName = siteData[level][nodeToPlay].node_name;
|
||||||
|
|
||||||
useStore.setState({
|
return {
|
||||||
idleImages: images,
|
images: images,
|
||||||
idleMedia: media,
|
media: media,
|
||||||
});
|
nodeName: nodeName,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
useStore.setState({
|
return {
|
||||||
idleMedia:
|
media:
|
||||||
idleNodes.video[Math.floor(Math.random() * idleNodes.video.length)],
|
idleNodes.video[Math.floor(Math.random() * idleNodes.video.length)],
|
||||||
});
|
nodeName: undefined,
|
||||||
|
images: undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue