optimized hud a bit more

This commit is contained in:
ad044 2021-01-25 21:07:59 +04:00
parent 5e804c51a0
commit abbd510941
9 changed files with 238 additions and 301 deletions

View file

@ -8,7 +8,6 @@ import authorizeInactiveLetters from "../../static/sprite/authorize_inactive_let
import authorizeActiveLetters from "../../static/sprite/authorize_active_letters.png"; import authorizeActiveLetters from "../../static/sprite/authorize_active_letters.png";
import { useLoader } from "react-three-fiber"; import { useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import { useAuthorizeUserStore } from "../../store";
import { OrbitControls } from "@react-three/drei"; import { OrbitControls } from "@react-three/drei";
type BootAuthorizeUserProps = { type BootAuthorizeUserProps = {
@ -42,19 +41,15 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
authorizeActiveLetters authorizeActiveLetters
); );
const backgroundLettersPos = useAuthorizeUserStore( const backgroundLettersPos = 1;
(state) => state.bgLettersPos const activeLetterTextureOffset = 2;
);
const activeLetterTextureOffset = useAuthorizeUserStore(
(state) => state.activeLetterTextureOffset
);
const authorizeActiveLettersMap = useMemo(() => { const authorizeActiveLettersMap = useMemo(() => {
authorizeActiveLettersTex.wrapT = authorizeActiveLettersTex.wrapS = authorizeActiveLettersTex.wrapT = authorizeActiveLettersTex.wrapS =
THREE.RepeatWrapping; THREE.RepeatWrapping;
authorizeActiveLettersTex.repeat.set(0.06, 0.2); authorizeActiveLettersTex.repeat.set(0.06, 0.2);
authorizeActiveLettersTex.offset.x = activeLetterTextureOffset.x; authorizeActiveLettersTex.offset.x = 1;
authorizeActiveLettersTex.offset.y = activeLetterTextureOffset.y; authorizeActiveLettersTex.offset.y = 2;
return authorizeActiveLettersTex; return authorizeActiveLettersTex;
}, [activeLetterTextureOffset, authorizeActiveLettersTex]); }, [activeLetterTextureOffset, authorizeActiveLettersTex]);
@ -129,7 +124,7 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
<mesh <mesh
scale={[4, 1.28, 0]} scale={[4, 1.28, 0]}
renderOrder={-1} renderOrder={-1}
position={[backgroundLettersPos.x, backgroundLettersPos.y, 0]} position={[1, 2, 0]}
> >
<planeBufferGeometry attach="geometry" /> <planeBufferGeometry attach="geometry" />
<meshBasicMaterial <meshBasicMaterial

View file

@ -1,15 +1,15 @@
import React, { useMemo, memo } from "react"; import React, { memo, useEffect, useRef, useState } from "react";
import { useLoader } from "react-three-fiber"; import { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three"; import * as THREE from "three";
import bigHud from "../../../static/sprite/big_hud.png"; import bigHud from "../../../static/sprite/big_hud.png";
import bigHudMirrored from "../../../static/sprite/big_hud_mirrored.png";
import longHud from "../../../static/sprite/long_hud.png"; import longHud from "../../../static/sprite/long_hud.png";
import longHudMirrored from "../../../static/sprite/long_hud_mirrored.png";
import boringHud from "../../../static/sprite/long_hud_boring.png"; import boringHud from "../../../static/sprite/long_hud_boring.png";
import boringHudMirrored from "../../../static/sprite/long_hud_boring_mirrored.png"; import { a } from "@react-spring/three";
import { a, useSpring } from "@react-spring/three";
import { useStore } from "../../../store"; import { useStore } from "../../../store";
import MediumLetter from "../../TextRenderer/MediumLetter"; import { getNodeHud } from "../../../core/nodeSelector";
import lerp from "../../../core/utils/lerp";
import GreenTextRenderer from "../../TextRenderer/GreenTextRenderer";
import MediaSceneEventManager from "../../../core/StateManagers/MediaSceneEventManager";
export type HUDType = { export type HUDType = {
mirrored: number; mirrored: number;
@ -33,124 +33,153 @@ export type HUDType = {
}; };
const HUD = memo(() => { const HUD = memo(() => {
const greenText = useStore((state) => const greenText = ["d", "i"];
state.activeNode.title.split("") const activeRef = useRef(true);
const currentHudRef = useRef(
getNodeHud(useStore.getState().activeNodeMatrixIndices)
);
const activeNodeMatrixIndices = useStore(
(state) => state.activeNodeMatrixIndices
); );
const active = useStore((state) => Number(state.hudActive));
const currentHud = useStore((state) => state.hud);
const hudElementState = useSpring({ useFrame(() => {
bigHUDPositionX: active, if (
longHUDPositionX: active, longHudRef.current &&
boringHUDPositionX: active, bigHudRef.current &&
greenTextPositionX: active, boringHudRef.current &&
config: { duration: 400 }, greenTextRef.current
) {
longHudRef.current.position.x = lerp(
longHudRef.current.position.x,
!activeRef.current
? currentHudRef.current.long.initial_position[0]
: currentHudRef.current.long.position[0],
0.12
);
boringHudRef.current.position.x = lerp(
boringHudRef.current.position.x,
!activeRef.current
? currentHudRef.current.boring.initial_position[0]
: currentHudRef.current.boring.position[0],
0.12
);
bigHudRef.current.position.x = lerp(
bigHudRef.current.position.x,
!activeRef.current
? currentHudRef.current.big.initial_position[0]
: currentHudRef.current.big.position[0],
0.12
);
greenTextRef.current.position.x = lerp(
greenTextRef.current.position.x,
!activeRef.current
? currentHudRef.current.medium_text.initial_position[0]
: currentHudRef.current.medium_text.position[0],
0.12
);
}
}); });
const bigHUDPosX = hudElementState.bigHUDPositionX.to( useEffect(() => {
[0, 1], if (activeRef.current) {
[currentHud.big.initial_position[0], currentHud.big.position[0]] activeRef.current = false;
); setTimeout(() => {
const hud = getNodeHud(activeNodeMatrixIndices);
if (
longHudRef.current &&
bigHudRef.current &&
boringHudRef.current &&
greenTextRef.current
) {
longHudRef.current.position.y = hud.long.position[1];
boringHudRef.current.position.y = hud.boring.position[1];
bigHudRef.current.position.y = hud.big.position[1];
greenTextRef.current.position.y = hud.medium_text.position[1];
const boringHUDPosX = hudElementState.boringHUDPositionX.to( longHudRef.current.position.x = hud.long.initial_position[0];
[0, 1], boringHudRef.current.position.x = hud.boring.initial_position[0];
[currentHud.boring.initial_position[0], currentHud.boring.position[0]] bigHudRef.current.position.x = hud.big.initial_position[0];
); greenTextRef.current.position.x = hud.medium_text.initial_position[0];
const longHUDPosX = hudElementState.longHUDPositionX.to( if (hud.mirrored) {
[0, 1], longHudRef.current.scale.x = -Math.abs(longHudRef.current.scale.x);
[currentHud.long.initial_position[0], currentHud.long.position[0]] boringHudRef.current.scale.x = -Math.abs(
boringHudRef.current.scale.x
); );
bigHudRef.current.scale.x = -Math.abs(bigHudRef.current.scale.x);
} else {
longHudRef.current.scale.x = Math.abs(longHudRef.current.scale.x);
boringHudRef.current.scale.x = Math.abs(
boringHudRef.current.scale.x
);
bigHudRef.current.scale.x = Math.abs(bigHudRef.current.scale.x);
}
currentHudRef.current = hud;
activeRef.current = true;
}
}, 500);
}
}, [activeNodeMatrixIndices]);
const greenTextPosX = hudElementState.greenTextPositionX.to( const longHudRef = useRef<THREE.Object3D>();
[0, 1], const boringHudRef = useRef<THREE.Object3D>();
[ const bigHudRef = useRef<THREE.Object3D>();
currentHud.medium_text.initial_position[0], const greenTextRef = useRef<THREE.Object3D>();
currentHud.medium_text.position[0],
]
);
const longHudTex = useLoader(THREE.TextureLoader, longHud); const longHudTex = useLoader(THREE.TextureLoader, longHud);
const longHudMirroredTex = useLoader(THREE.TextureLoader, longHudMirrored);
const boringHudTex = useLoader(THREE.TextureLoader, boringHud); const boringHudTex = useLoader(THREE.TextureLoader, boringHud);
const boringHudMirroredTex = useLoader(
THREE.TextureLoader,
boringHudMirrored
);
const bigHudTex = useLoader(THREE.TextureLoader, bigHud); const bigHudTex = useLoader(THREE.TextureLoader, bigHud);
const bigHudMirroredTex = useLoader(THREE.TextureLoader, bigHudMirrored);
const textures = useMemo(
() =>
currentHud.mirrored === 0
? [longHudTex, boringHudTex, bigHudTex]
: [longHudMirroredTex, boringHudMirroredTex, bigHudMirroredTex],
[
bigHudMirroredTex,
bigHudTex,
boringHudMirroredTex,
boringHudTex,
currentHud.mirrored,
longHudMirroredTex,
longHudTex,
]
);
// console.log("rend");
return ( return (
<group position={[0, 0, 10]}> <group position={[0, 0, 10]}>
<a.sprite <a.mesh
position-x={longHUDPosX}
position-y={currentHud.long.position[1]}
position-z={currentHud.long.position[2]}
scale={[1, 0.03, 1]} scale={[1, 0.03, 1]}
renderOrder={2} renderOrder={2}
ref={longHudRef}
position-z={-8.6}
> >
<spriteMaterial <planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material" attach="material"
map={textures[0]} map={longHudTex}
transparent={true} transparent={true}
depthTest={false} depthTest={false}
/> />
</a.sprite> </a.mesh>
<a.sprite <a.mesh
position-x={boringHUDPosX}
position-y={currentHud.boring.position[1]}
position-z={currentHud.boring.position[2]}
scale={[1, 0.03, 1]} scale={[1, 0.03, 1]}
renderOrder={2} renderOrder={2}
ref={boringHudRef}
position-z={-8.6}
> >
<spriteMaterial <planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material" attach="material"
map={textures[1]} map={boringHudTex}
transparent={true} transparent={true}
depthTest={false} depthTest={false}
/> />
</a.sprite> </a.mesh>
<a.sprite <a.mesh
position-x={bigHUDPosX}
position-y={currentHud.big.position[1]}
position-z={currentHud.big.position[2]}
scale={[0.5, 0.06, 1]} scale={[0.5, 0.06, 1]}
renderOrder={2} renderOrder={2}
ref={bigHudRef}
position-z={-8.6}
> >
<spriteMaterial <planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material" attach="material"
map={textures[2]} map={bigHudTex}
transparent={true} transparent={true}
depthTest={false} depthTest={false}
/> />
</a.sprite> </a.mesh>
<a.group <a.group position-z={-8.7} scale={[0.02, 0.035, 0.02]} ref={greenTextRef}>
position-x={greenTextPosX} <GreenTextRenderer />
position-y={currentHud.medium_text.position[1]}
position-z={-8.7}
scale={[0.02, 0.035, 0.02]}
>
{greenText.map((letter: string, idx: number) => (
<MediumLetter letter={letter} letterIdx={idx} key={idx} />
))}
</a.group> </a.group>
</group> </group>
); );

View file

@ -0,0 +1,106 @@
import { useLoader } from "react-three-fiber";
import * as THREE from "three";
import greenFont from "../../static/sprite/white_and_green_texture.png";
import medium_font_json from "../../resources/font_data/medium_font.json";
import { a } from "@react-spring/three";
import React, { memo, useCallback, useMemo } from "react";
import { useStore } from "../../store";
const GreenTextRenderer = memo(() => {
const textToRender = useStore(
useCallback(
(state) =>
(state.currentScene === "main"
? state.activeNode.title
: state.activeNode.node_name
).split(""),
[]
)
);
const colorTexture = useLoader(THREE.TextureLoader, greenFont);
const getLineYOffset = (letter: string) => {
const lineOne = "ABCDEFGHIJKLMNOPQQRSTUVW";
const lineTwo = "XYZ0123456789abcdefghij";
const lineThree = "klmnopqrstuvwxyz,.*";
let lineNum: number;
if (letter === " ") {
lineNum = 5;
} else {
if (lineOne.includes(letter)) {
lineNum = 1;
} else if (lineTwo.includes(letter)) {
lineNum = 2;
} else if (lineThree.includes(letter)) {
lineNum = 3;
} else {
lineNum = 4;
}
}
const offsets = {
1: 0.355,
2: 0.297,
3: 0.238,
4: 0.18,
5: 1,
};
return offsets[lineNum as keyof typeof offsets];
};
const text = useMemo(() => {
const getGeom = (letter: string, letterData: number[]) => {
const geometry = new THREE.PlaneBufferGeometry();
const uvAttribute = geometry.attributes.uv;
for (let i = 0; i < uvAttribute.count; i++) {
let u = uvAttribute.getX(i);
let v = uvAttribute.getY(i);
u = (u * letterData[2]) / 256 + letterData[0] / 256;
v =
(v * letterData[3]) / 136 +
getLineYOffset(letter) -
letterData[4] / 136;
uvAttribute.setXY(i, u, v);
}
return geometry;
};
return textToRender.map((letter, idx) => {
const letterData =
medium_font_json.glyphs[letter as keyof typeof medium_font_json.glyphs];
const geom = getGeom(letter, letterData);
return (
<a.mesh
position-x={idx * 1.6}
position-y={0 - letterData[4] / 12.5}
scale={[1.7, 1, 1.7]}
geometry={geom}
renderOrder={100}
key={idx}
>
<meshBasicMaterial
map={colorTexture}
attach="material"
transparent={true}
depthTest={false}
/>
</a.mesh>
);
});
}, [colorTexture, textToRender]);
console.log("rend");
return <>{text}</>;
});
export default GreenTextRenderer;

View file

@ -1,86 +0,0 @@
import { useLoader } from "react-three-fiber";
import * as THREE from "three";
import greenFont from "../../static/sprite/white_and_green_texture.png";
import medium_font_json from "../../resources/font_data/medium_font.json";
import { a } from "@react-spring/three";
import React, { useMemo, memo } from "react";
const MediumLetter = memo((props: { letter: string; letterIdx: number }) => {
const colorTexture = useLoader(THREE.TextureLoader, greenFont);
const lineYOffset = useMemo(() => {
const lineOne = "ABCDEFGHIJKLMNOPQQRSTUVW";
const lineTwo = "XYZ0123456789abcdefghij";
const lineThree = "klmnopqrstuvwxyz,.*";
let lineNum: number;
if (props.letter === " ") {
lineNum = 5;
} else {
if (lineOne.includes(props.letter)) {
lineNum = 1;
} else if (lineTwo.includes(props.letter)) {
lineNum = 2;
} else if (lineThree.includes(props.letter)) {
lineNum = 3;
} else {
lineNum = 4;
}
}
const offsets = {
1: 0.355,
2: 0.297,
3: 0.238,
4: 0.18,
5: 1,
};
return offsets[lineNum as keyof typeof offsets];
}, [props.letter]);
const letterData = useMemo(
() =>
medium_font_json.glyphs[
props.letter as keyof typeof medium_font_json.glyphs
],
[props.letter]
);
const geom = useMemo(() => {
const geometry = new THREE.PlaneBufferGeometry();
const uvAttribute = geometry.attributes.uv;
for (let i = 0; i < uvAttribute.count; i++) {
let u = uvAttribute.getX(i);
let v = uvAttribute.getY(i);
u = (u * letterData[2]) / 256 + letterData[0] / 256;
v = (v * letterData[3]) / 136 + lineYOffset - letterData[4] / 136;
uvAttribute.setXY(i, u, v);
}
return geometry;
}, [letterData, lineYOffset]);
return (
<a.mesh
position-x={props.letterIdx * 1.6}
position-y={0 - letterData[4] / 12.5}
scale={[1.7, 1, 1.7]}
geometry={geom}
renderOrder={100}
>
<meshBasicMaterial
map={colorTexture}
attach="material"
transparent={true}
depthTest={false}
/>
</a.mesh>
);
});
export default MediumLetter;

View file

@ -1,64 +0,0 @@
import { useCallback, useEffect } from "react";
import { StateManagerProps } from "../EventManager";
import { useAuthorizeUserStore } from "../../../store";
const BootAuthorizeUserManager = (props: StateManagerProps) => {
const setActiveLetterTextureOffset = useAuthorizeUserStore(
(state) => state.setActiveLetterTexOffset
);
const setBgLettersPos = useAuthorizeUserStore(
(state) => state.setBgLettersPos
);
const updateAuthorizeUser = useCallback(
(
newBgLettersPos: { x: number; y: number },
newActiveLetterTexOffset: { x: number; y: number }
) => {
setActiveLetterTextureOffset(newActiveLetterTexOffset);
setBgLettersPos(newBgLettersPos);
},
[setActiveLetterTextureOffset, setBgLettersPos]
);
const dispatchObject = useCallback(
(
event: string,
newBgLettersPos: { x: number; y: number },
newActiveLetterTexOffset: { x: number; y: number }
) => {
switch (event) {
case "authorize_user_left":
case "authorize_user_up":
case "authorize_user_down":
case "authorize_user_right":
return {
action: updateAuthorizeUser,
value: [newBgLettersPos, newActiveLetterTexOffset],
};
}
},
[updateAuthorizeUser]
);
useEffect(() => {
if (props.eventState) {
const eventAction = props.eventState.event;
const newBgLettersPos = props.eventState.newBgLettersPos;
const newActiveLetterTexOffset =
props.eventState.newActiveLetterTexOffset;
const dispatchedObject = dispatchObject(
eventAction,
newBgLettersPos,
newActiveLetterTexOffset
);
if (dispatchedObject) {
dispatchedObject.action.apply(null, dispatchedObject.value as any);
}
}
}, [dispatchObject, props.eventState]);
return null;
};
export default BootAuthorizeUserManager;

View file

@ -19,18 +19,6 @@ const NodeHUDManager = (props: StateManagerProps) => {
[set, toggleActive] [set, toggleActive]
); );
const changeNode = useCallback(
(hud: HUDType) => {
toggleActive();
setTimeout(() => {
set(hud);
toggleActive();
}, 500);
},
[set, toggleActive]
);
const selectLevelAnimation = useCallback( const selectLevelAnimation = useCallback(
(hud: HUDType) => { (hud: HUDType) => {
setTimeout(() => { setTimeout(() => {
@ -52,11 +40,6 @@ const NodeHUDManager = (props: StateManagerProps) => {
action: moveAndChangeNode, action: moveAndChangeNode,
value: [eventState.hud], value: [eventState.hud],
}; };
case "change_node":
return {
action: changeNode,
value: [eventState.hud],
};
case "toggle_level_selection": case "toggle_level_selection":
case "level_selection_back": case "level_selection_back":
return { return {
@ -70,7 +53,7 @@ const NodeHUDManager = (props: StateManagerProps) => {
}; };
} }
}, },
[changeNode, moveAndChangeNode, selectLevelAnimation, toggleActive] [moveAndChangeNode, selectLevelAnimation, toggleActive]
); );
useEffect(() => { useEffect(() => {

3
src/core/utils/lerp.ts Normal file
View file

@ -0,0 +1,3 @@
const lerp = (x: number, y: number, a: number) => x * (1 - a) + y * a;
export default lerp;

View file

@ -6,26 +6,12 @@ import AudioVisualizer from "../components/MediaScene/AudioVisualizer/AudioVisua
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 Images from "../components/MediaScene/Images"; import Images from "../components/MediaScene/Images";
import MediumLetter from "../components/TextRenderer/MediumLetter"; import GreenTextRenderer from "../components/TextRenderer/GreenTextRenderer";
import MediaYellowTextAnimator from "../components/TextRenderer/MediaYellowTextAnimator"; import MediaYellowTextAnimator from "../components/TextRenderer/MediaYellowTextAnimator";
import MediaSceneEventManager from "../core/StateManagers/MediaSceneEventManager"; import MediaSceneEventManager from "../core/StateManagers/MediaSceneEventManager";
const MediaScene = () => { const MediaScene = () => {
const nodeNameText = useStore( const activeNodeMedia = useStore((state) => state.activeNode.media_file);
useCallback(
(state) =>
state.activeNode.node_name
.split("")
.map((letter: string, idx: number) => (
<MediumLetter letter={letter} letterIdx={idx} key={idx} />
)),
[]
)
);
const activeNodeMedia = useStore(
(state) => state.activeNode.media_file
);
useEffect(() => { useEffect(() => {
document.getElementsByTagName("canvas")[0].className = document.getElementsByTagName("canvas")[0].className =
@ -46,7 +32,7 @@ const MediaScene = () => {
<NodeNameContainer /> <NodeNameContainer />
</group> </group>
<group scale={[0.06, 0.12, 0]} position={[0.8, 1.37, 0]}> <group scale={[0.06, 0.12, 0]} position={[0.8, 1.37, 0]}>
{nodeNameText} <GreenTextRenderer />
</group> </group>
<MediaYellowTextAnimator /> <MediaYellowTextAnimator />

View file

@ -25,21 +25,6 @@ type SiteSaveState = {
}; };
}; };
export const useAuthorizeUserStore = create<any>((set) => ({
bgLettersPos: {
x: 3.35,
y: -0.7,
},
activeLetterTextureOffset: {
x: 0,
y: -0.2,
},
setBgLettersPos: (to: { x: number; y: number }) =>
set(() => ({ bgLettersPos: to })),
setActiveLetterTexOffset: (to: { x: number; y: number }) =>
set(() => ({ activeLetterTextureOffset: to })),
}));
type State = { type State = {
currentScene: string; currentScene: string;