mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
adding words...
This commit is contained in:
parent
813063953a
commit
04bb8972d4
11 changed files with 351 additions and 246 deletions
1
public/3d_fonts/MediaWord.blob
Normal file
1
public/3d_fonts/MediaWord.blob
Normal file
File diff suppressed because one or more lines are too long
|
@ -4,8 +4,8 @@ import "./static/css/hub.css";
|
|||
import "./static/css/main.css";
|
||||
import { Canvas } from "react-three-fiber";
|
||||
import Boot from "./components/Boot";
|
||||
import MediaPlayer from "./components/MediaPlayer";
|
||||
import MediaOverlay from "./components/MediaOverlay";
|
||||
import MediaPlayer from "./components/MediaScene/MediaPlayer";
|
||||
import MediaScene from "./components/MediaScene/MediaScene";
|
||||
import EventStateManager from "./components/StateManagers/EventStateManager";
|
||||
|
||||
const App = () => {
|
||||
|
@ -27,12 +27,12 @@ const App = () => {
|
|||
<EventStateManager />
|
||||
<Canvas concurrent>
|
||||
<Suspense fallback={null}>
|
||||
<MediaOverlay />
|
||||
<MediaScene />
|
||||
</Suspense>
|
||||
{/*<MainScene />*/}
|
||||
</Canvas>
|
||||
</span>
|
||||
<MediaPlayer />
|
||||
{/*<MediaPlayer />*/}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import grayTextureFile from "../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../static/sprite/dark_gray_box.png";
|
||||
import mediaOverlayHud from "../static/sprite/media_hud.png";
|
||||
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "drei";
|
||||
import { a, useTrail } from "@react-spring/three";
|
||||
import { useMediaStore } from "../store";
|
||||
import BigLetter from "./TextRenderer/BigLetter";
|
||||
import MediumLetter from "./TextRenderer/MediumLetter";
|
||||
import TextRenderer from "./TextRenderer/TextRenderer";
|
||||
|
||||
type ShapeProps = {
|
||||
position: number[];
|
||||
selectable?: boolean;
|
||||
active?: boolean;
|
||||
};
|
||||
|
||||
const GrayCube = (props: ShapeProps) => {
|
||||
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
||||
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
||||
|
||||
const cubeRef = useRef<THREE.Object3D>();
|
||||
|
||||
useFrame(() => {
|
||||
if (props.selectable && props.active) {
|
||||
cubeRef.current!.rotation.y -= 0.015;
|
||||
} else {
|
||||
cubeRef.current!.rotation.y = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
scale={[0.45, 0.5, 0.45]}
|
||||
position={props.position as [number, number, number]}
|
||||
rotation-y={0.15}
|
||||
rotation-z={-0.02}
|
||||
ref={cubeRef}
|
||||
>
|
||||
<boxBufferGeometry args={[1, 1, 1]} attach="geometry" />
|
||||
<meshLambertMaterial
|
||||
attach="material"
|
||||
map={props.active ? grayTex : darkGrayTex}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
};
|
||||
|
||||
const GrayTriangularPrism = (props: ShapeProps) => {
|
||||
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
||||
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
||||
|
||||
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(() => {
|
||||
if (props.selectable && props.active) {
|
||||
prismRef.current!.rotation.y -= 0.015;
|
||||
} else {
|
||||
prismRef.current!.rotation.y = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
scale={[0.45, 0.5, 0.45]}
|
||||
position={props.position as [number, number, number]}
|
||||
rotation-y={0.15}
|
||||
rotation-z={-0.02}
|
||||
ref={prismRef}
|
||||
>
|
||||
<boxBufferGeometry args={[1, 1, 1]} attach="geometry" />
|
||||
<meshLambertMaterial
|
||||
attach="material"
|
||||
map={props.active ? grayTex : darkGrayTex}
|
||||
/>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
||||
const MediaOverlay = () => {
|
||||
const [grayCubesActive, setGrayCubesActive] = useState(false);
|
||||
const mediaHudOverlayTex = useLoader(THREE.TextureLoader, mediaOverlayHud);
|
||||
|
||||
const activeMediaElement = useMediaStore((state) => state.activeMediaElement);
|
||||
|
||||
return (
|
||||
<>
|
||||
<OrbitControls />
|
||||
<sprite scale={[5, 1, 1]} position={[2.65, 2.5, 0]}>
|
||||
<spriteMaterial attach="material" map={mediaHudOverlayTex} />
|
||||
</sprite>
|
||||
<group position={[0.4, -0.3, 0]}>
|
||||
<group position={[0, 0, 13]} scale={[1, 1, 1]}>
|
||||
<TextRenderer />
|
||||
</group>
|
||||
|
||||
<pointLight intensity={1.2} color={0xffffff} position={[-2, 0, 3]} />
|
||||
|
||||
<GrayCube position={[-2.7, -1.6, 0.6]} active={grayCubesActive} />
|
||||
<GrayTriangularPrism
|
||||
position={[-3.5, -1.6, 0.6]}
|
||||
active={!grayCubesActive}
|
||||
/>
|
||||
<GrayCube position={[-3.5, -0.9, 0.6]} active={grayCubesActive} />
|
||||
<GrayTriangularPrism
|
||||
position={[-2.7, -0.9, 0.6]}
|
||||
active={!grayCubesActive}
|
||||
/>
|
||||
<GrayTriangularPrism
|
||||
position={[-3.5, -1.6, 1.2]}
|
||||
active={!grayCubesActive}
|
||||
/>
|
||||
<GrayCube position={[-3.5, -0.9, 1.2]} active={grayCubesActive} />
|
||||
<GrayCube
|
||||
position={[-2.7, -1.6, 1.2]}
|
||||
active={grayCubesActive}
|
||||
selectable={true}
|
||||
/>
|
||||
<GrayTriangularPrism
|
||||
position={[-2.7, -0.9, 1.2]}
|
||||
active={!grayCubesActive}
|
||||
selectable={true}
|
||||
/>
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MediaOverlay;
|
39
src/components/MediaScene/LeftSide/Cube.tsx
Normal file
39
src/components/MediaScene/LeftSide/Cube.tsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import grayTextureFile from "../../../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../static/sprite/dark_gray_box.png";
|
||||
import React, { useRef } from "react";
|
||||
import { ShapeProps } from "./LeftSide";
|
||||
|
||||
const Cube = (props: ShapeProps) => {
|
||||
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
||||
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
||||
|
||||
const cubeRef = useRef<THREE.Object3D>();
|
||||
|
||||
useFrame(() => {
|
||||
if (props.selectable && props.active) {
|
||||
cubeRef.current!.rotation.y -= 0.015;
|
||||
} else {
|
||||
cubeRef.current!.rotation.y = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
scale={[0.45, 0.5, 0.45]}
|
||||
position={props.position as [number, number, number]}
|
||||
rotation-y={0.15}
|
||||
rotation-z={-0.02}
|
||||
ref={cubeRef}
|
||||
>
|
||||
<boxBufferGeometry args={[1, 1, 1]} attach="geometry" />
|
||||
<meshLambertMaterial
|
||||
attach="material"
|
||||
map={props.active ? grayTex : darkGrayTex}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cube;
|
43
src/components/MediaScene/LeftSide/LeftSide.tsx
Normal file
43
src/components/MediaScene/LeftSide/LeftSide.tsx
Normal file
|
@ -0,0 +1,43 @@
|
|||
import React from "react";
|
||||
import TriangularPrism from "./TriangularPrism";
|
||||
import Cube from "./Cube";
|
||||
|
||||
type LeftSideShapesProps = {
|
||||
active: "cube" | "triangle" | "";
|
||||
};
|
||||
|
||||
export type ShapeProps = {
|
||||
position: number[];
|
||||
selectable?: boolean;
|
||||
active?: boolean;
|
||||
};
|
||||
|
||||
const LeftSide = (props: LeftSideShapesProps) => {
|
||||
const cubesActive = props.active === "cube";
|
||||
const trianglesActive = props.active === "triangle";
|
||||
|
||||
return (
|
||||
<>
|
||||
<Cube position={[-2.7, -1.6, 0.6]} active={cubesActive} />
|
||||
<TriangularPrism position={[-3.5, -1.6, 0.6]} active={!trianglesActive} />
|
||||
<Cube position={[-3.5, -0.9, 0.6]} active={cubesActive} />
|
||||
<TriangularPrism position={[-2.7, -0.9, 0.6]} active={trianglesActive} />
|
||||
<Cube position={[-3.5, -0.9, 1.2]} active={cubesActive} />
|
||||
<TriangularPrism position={[-3.5, -1.6, 1.2]} active={trianglesActive} />
|
||||
|
||||
{/*main two*/}
|
||||
<Cube
|
||||
position={[-2.7, -1.6, 1.2]}
|
||||
active={cubesActive}
|
||||
selectable={true}
|
||||
/>
|
||||
<TriangularPrism
|
||||
position={[-2.7, -0.9, 1.2]}
|
||||
active={trianglesActive}
|
||||
selectable={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LeftSide;
|
147
src/components/MediaScene/LeftSide/TriangularPrism.tsx
Normal file
147
src/components/MediaScene/LeftSide/TriangularPrism.tsx
Normal file
|
@ -0,0 +1,147 @@
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import grayTextureFile from "../../../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../static/sprite/dark_gray_box.png";
|
||||
import React, { useRef } from "react";
|
||||
import { ShapeProps } from "./LeftSide";
|
||||
|
||||
const TriangularPrism = (props: ShapeProps) => {
|
||||
const grayTex = useLoader(THREE.TextureLoader, grayTextureFile);
|
||||
const darkGrayTex = useLoader(THREE.TextureLoader, darkGrayTextureFile);
|
||||
|
||||
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(() => {
|
||||
if (props.selectable && props.active) {
|
||||
prismRef.current!.rotation.y -= 0.015;
|
||||
} else {
|
||||
prismRef.current!.rotation.y = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
scale={[0.45, 0.5, 0.45]}
|
||||
position={props.position as [number, number, number]}
|
||||
rotation-y={0.15}
|
||||
rotation-z={-0.02}
|
||||
ref={prismRef}
|
||||
>
|
||||
<boxBufferGeometry args={[1, 1, 1]} attach="geometry" />
|
||||
<meshLambertMaterial
|
||||
attach="material"
|
||||
map={props.active ? grayTex : darkGrayTex}
|
||||
/>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
||||
export default TriangularPrism;
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import ReactPlayer from "react-player";
|
||||
import test from "../static/movie/test.webm";
|
||||
import test from "../../static/movie/test.webm";
|
||||
|
||||
const MediaPlayer = () => {
|
||||
return (
|
43
src/components/MediaScene/MediaScene.tsx
Normal file
43
src/components/MediaScene/MediaScene.tsx
Normal file
|
@ -0,0 +1,43 @@
|
|||
import React, { useRef, useState } from "react";
|
||||
|
||||
import grayTextureFile from "../../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../../static/sprite/dark_gray_box.png";
|
||||
import mediaOverlayHud from "../../static/sprite/media_hud.png";
|
||||
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "drei";
|
||||
import { useMediaStore, useMediaWordStore } from "../../store";
|
||||
import TextRenderer from "../TextRenderer/TextRenderer";
|
||||
import LeftSide from "./LeftSide/LeftSide";
|
||||
import Word from "./Word";
|
||||
|
||||
const MediaScene = () => {
|
||||
const [grayCubesActive, setGrayCubesActive] = useState(false);
|
||||
const mediaHudOverlayTex = useLoader(THREE.TextureLoader, mediaOverlayHud);
|
||||
const words = useMediaWordStore((state) => state.words);
|
||||
|
||||
const activeMediaElement = useMediaStore((state) => state.activeMediaElement);
|
||||
|
||||
return (
|
||||
<>
|
||||
<OrbitControls />
|
||||
<sprite scale={[5, 1, 1]} position={[2.65, 2.5, 0]}>
|
||||
<spriteMaterial attach="material" map={mediaHudOverlayTex} />
|
||||
</sprite>
|
||||
<group position={[0.4, -0.3, 0]}>
|
||||
<group position={[0, 0, 13]} scale={[1, 1, 1]}>
|
||||
<TextRenderer />
|
||||
</group>
|
||||
|
||||
<pointLight intensity={1.2} color={0xffffff} position={[-2, 0, 3]} />
|
||||
<LeftSide active={"cube"} />
|
||||
<Word word={words[0]} posX={1} posY={1} />
|
||||
<Word word={words[1]} posX={0} posY={0} />
|
||||
<Word word={words[2]} posX={-1} posY={-1} />
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MediaScene;
|
49
src/components/MediaScene/Word.tsx
Normal file
49
src/components/MediaScene/Word.tsx
Normal file
|
@ -0,0 +1,49 @@
|
|||
import React, { useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import wordInactiveTexture from "../../static/sprite/word_background.png";
|
||||
import wordActiveTexture from "../../static/sprite/word_background_active.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
|
||||
type WordProps = {
|
||||
word: string;
|
||||
posX: number;
|
||||
posY: number;
|
||||
};
|
||||
|
||||
const Word = (props: WordProps) => {
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d_fonts/MediaWord.blob");
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
font: wordFont,
|
||||
size: 1,
|
||||
}),
|
||||
[wordFont]
|
||||
);
|
||||
|
||||
const wordInactiveTex = useLoader(THREE.TextureLoader, wordInactiveTexture);
|
||||
const wordActiveTex = useLoader(THREE.TextureLoader, wordActiveTexture);
|
||||
|
||||
return (
|
||||
<group position-x={props.posX} position-y={props.posY}>
|
||||
<mesh scale={[0.4, 0.4, 0]} position={[-3.9, 1.915, 0]} renderOrder={3}>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<textGeometry attach="geometry" args={[props.word, config]} />
|
||||
<meshBasicMaterial
|
||||
attach="material"
|
||||
color={0x000000}
|
||||
transparent={true}
|
||||
/>
|
||||
</mesh>
|
||||
|
||||
<sprite scale={[4.2, 0.45, 1]} position={[-2, 2, 0]} renderOrder={2}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={wordInactiveTex}
|
||||
alphaTest={0.01}
|
||||
/>
|
||||
</sprite>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
export default Word;
|
2
src/react-app-env.d.ts
vendored
2
src/react-app-env.d.ts
vendored
|
@ -8,3 +8,5 @@ declare module "threejs-slice-geometry" {
|
|||
const src: any;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.ttf';
|
||||
|
|
22
src/store.ts
22
src/store.ts
|
@ -85,6 +85,17 @@ type MiddleRingState = {
|
|||
setMiddleRingAnimDuration: (to: number) => void;
|
||||
};
|
||||
|
||||
type MediaWordState = {
|
||||
words: string[];
|
||||
fstWordPos: number[];
|
||||
sndWordPos: number[];
|
||||
thirdWordPos: number[];
|
||||
setWords: (to: string[]) => void;
|
||||
setFstWordPos: (to: number[]) => void;
|
||||
setSndWordPos: (to: number[]) => void;
|
||||
setThirdWordPos: (to: number[]) => void;
|
||||
};
|
||||
|
||||
type MediaState = {
|
||||
activeMediaElement: string;
|
||||
leftColActiveMediaElement: string;
|
||||
|
@ -244,3 +255,14 @@ export const useMediaStore = create<MediaState>((set) => ({
|
|||
setLeftColActiveMediaElementTextPos: (to) =>
|
||||
set(() => ({ leftColActiveMediaElementTextPos: to })),
|
||||
}));
|
||||
|
||||
export const useMediaWordStore = create<MediaWordState>((set) => ({
|
||||
words: ["eye", "quiet", "hallucination"],
|
||||
fstWordPos: [0, 0, 0],
|
||||
sndWordPos: [0, 0, 0],
|
||||
thirdWordPos: [0, 0, 0],
|
||||
setWords: (to) => set(() => ({ words: to })),
|
||||
setFstWordPos: (to) => set(() => ({ fstWordPos: to })),
|
||||
setSndWordPos: (to) => set(() => ({ sndWordPos: to })),
|
||||
setThirdWordPos: (to) => set(() => ({ thirdWordPos: to })),
|
||||
}));
|
||||
|
|
Loading…
Reference in a new issue