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

View file

@ -1,15 +1,15 @@
import React, { useMemo, memo } from "react";
import { useLoader } from "react-three-fiber";
import React, { memo, useEffect, useRef, useState } from "react";
import { useFrame, useLoader } from "react-three-fiber";
import * as THREE from "three";
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 longHudMirrored from "../../../static/sprite/long_hud_mirrored.png";
import boringHud from "../../../static/sprite/long_hud_boring.png";
import boringHudMirrored from "../../../static/sprite/long_hud_boring_mirrored.png";
import { a, useSpring } from "@react-spring/three";
import { a } from "@react-spring/three";
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 = {
mirrored: number;
@ -33,124 +33,153 @@ export type HUDType = {
};
const HUD = memo(() => {
const greenText = useStore((state) =>
state.activeNode.title.split("")
const greenText = ["d", "i"];
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({
bigHUDPositionX: active,
longHUDPositionX: active,
boringHUDPositionX: active,
greenTextPositionX: active,
config: { duration: 400 },
useFrame(() => {
if (
longHudRef.current &&
bigHudRef.current &&
boringHudRef.current &&
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(
[0, 1],
[currentHud.big.initial_position[0], currentHud.big.position[0]]
);
useEffect(() => {
if (activeRef.current) {
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(
[0, 1],
[currentHud.boring.initial_position[0], currentHud.boring.position[0]]
);
longHudRef.current.position.x = hud.long.initial_position[0];
boringHudRef.current.position.x = hud.boring.initial_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(
[0, 1],
[currentHud.long.initial_position[0], currentHud.long.position[0]]
);
if (hud.mirrored) {
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);
} 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(
[0, 1],
[
currentHud.medium_text.initial_position[0],
currentHud.medium_text.position[0],
]
);
const longHudRef = useRef<THREE.Object3D>();
const boringHudRef = useRef<THREE.Object3D>();
const bigHudRef = useRef<THREE.Object3D>();
const greenTextRef = useRef<THREE.Object3D>();
const longHudTex = useLoader(THREE.TextureLoader, longHud);
const longHudMirroredTex = useLoader(THREE.TextureLoader, longHudMirrored);
const boringHudTex = useLoader(THREE.TextureLoader, boringHud);
const boringHudMirroredTex = useLoader(
THREE.TextureLoader,
boringHudMirrored
);
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 (
<group position={[0, 0, 10]}>
<a.sprite
position-x={longHUDPosX}
position-y={currentHud.long.position[1]}
position-z={currentHud.long.position[2]}
<a.mesh
scale={[1, 0.03, 1]}
renderOrder={2}
ref={longHudRef}
position-z={-8.6}
>
<spriteMaterial
<planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material"
map={textures[0]}
map={longHudTex}
transparent={true}
depthTest={false}
/>
</a.sprite>
<a.sprite
position-x={boringHUDPosX}
position-y={currentHud.boring.position[1]}
position-z={currentHud.boring.position[2]}
</a.mesh>
<a.mesh
scale={[1, 0.03, 1]}
renderOrder={2}
ref={boringHudRef}
position-z={-8.6}
>
<spriteMaterial
<planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material"
map={textures[1]}
map={boringHudTex}
transparent={true}
depthTest={false}
/>
</a.sprite>
<a.sprite
position-x={bigHUDPosX}
position-y={currentHud.big.position[1]}
position-z={currentHud.big.position[2]}
</a.mesh>
<a.mesh
scale={[0.5, 0.06, 1]}
renderOrder={2}
ref={bigHudRef}
position-z={-8.6}
>
<spriteMaterial
<planeBufferGeometry attach="geometry" />
<meshBasicMaterial
attach="material"
map={textures[2]}
map={bigHudTex}
transparent={true}
depthTest={false}
/>
</a.sprite>
<a.group
position-x={greenTextPosX}
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.mesh>
<a.group position-z={-8.7} scale={[0.02, 0.035, 0.02]} ref={greenTextRef}>
<GreenTextRenderer />
</a.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

@ -1,7 +1,7 @@
import { useCallback, useEffect } from "react";
import { useStore } from "../../../store";
import { StateManagerProps } from "../EventManager";
import {HUDType} from "../../../components/MainScene/SyncedComponents/HUD";
import { HUDType } from "../../../components/MainScene/SyncedComponents/HUD";
const NodeHUDManager = (props: StateManagerProps) => {
const set = useStore((state) => state.setHud);
@ -19,18 +19,6 @@ const NodeHUDManager = (props: StateManagerProps) => {
[set, toggleActive]
);
const changeNode = useCallback(
(hud: HUDType) => {
toggleActive();
setTimeout(() => {
set(hud);
toggleActive();
}, 500);
},
[set, toggleActive]
);
const selectLevelAnimation = useCallback(
(hud: HUDType) => {
setTimeout(() => {
@ -52,11 +40,6 @@ const NodeHUDManager = (props: StateManagerProps) => {
action: moveAndChangeNode,
value: [eventState.hud],
};
case "change_node":
return {
action: changeNode,
value: [eventState.hud],
};
case "toggle_level_selection":
case "level_selection_back":
return {
@ -70,7 +53,7 @@ const NodeHUDManager = (props: StateManagerProps) => {
};
}
},
[changeNode, moveAndChangeNode, selectLevelAnimation, toggleActive]
[moveAndChangeNode, selectLevelAnimation, toggleActive]
);
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 NodeNameContainer from "../components/MediaScene/NodeNameContainer";
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 MediaSceneEventManager from "../core/StateManagers/MediaSceneEventManager";
const MediaScene = () => {
const nodeNameText = useStore(
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
);
const activeNodeMedia = useStore((state) => state.activeNode.media_file);
useEffect(() => {
document.getElementsByTagName("canvas")[0].className =
@ -46,7 +32,7 @@ const MediaScene = () => {
<NodeNameContainer />
</group>
<group scale={[0.06, 0.12, 0]} position={[0.8, 1.37, 0]}>
{nodeNameText}
<GreenTextRenderer />
</group>
<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 = {
currentScene: string;