mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
fixed bugs, optimized node generation
This commit is contained in:
parent
acceaa149a
commit
51cbd41c93
10 changed files with 294 additions and 108 deletions
|
@ -1,14 +1,17 @@
|
|||
import React, { useCallback } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import level_selection_font from "../../../static/sprite/select_level_font.png";
|
||||
import verticalHud from "../../../static/sprite/select_level_hud_vertical.png";
|
||||
import horizontalHud from "../../../static/sprite/select_level_hud_horizontal.png";
|
||||
import levelSelectionText from "../../../static/sprite/select_level_text.png";
|
||||
import upArrow from "../../../static/sprite/select_level_up_arrow.png";
|
||||
import downArrow from "../../../static/sprite/select_level_down_arrow.png";
|
||||
import upArrowActive from "../../../static/sprite/select_level_up_arrow_active.png";
|
||||
import downArrowActive from "../../../static/sprite/select_level_down_arrow_active.png";
|
||||
import { useStore } from "../../../store";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
|
||||
const LevelSelection = () => {
|
||||
const levelSelectionFontTex = useLoader(
|
||||
|
@ -23,47 +26,108 @@ const LevelSelection = () => {
|
|||
);
|
||||
const upArrowTex = useLoader(THREE.TextureLoader, upArrow);
|
||||
const downArrowTex = useLoader(THREE.TextureLoader, downArrow);
|
||||
|
||||
const toggled = useStore(
|
||||
useCallback((state) => Number(state.mainSubscene === "level_selection"), [])
|
||||
);
|
||||
const upArrowActiveTex = useLoader(THREE.TextureLoader, upArrowActive);
|
||||
const downArrowActiveTex = useLoader(THREE.TextureLoader, downArrowActive);
|
||||
|
||||
const selectedLevel = useStore((state) => state.selectedLevel)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const activeLevel = useStore((state) => state.activeLevel);
|
||||
const subscene = useStore((state) => state.mainSubscene);
|
||||
const prevData = usePrevious({ subscene, selectedLevel });
|
||||
|
||||
const { levelSelectionToggle } = useSpring({
|
||||
levelSelectionToggle: toggled,
|
||||
const [pos, set] = useSpring(() => ({
|
||||
vertPosY: -2.5,
|
||||
horizPosX: -4,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
}));
|
||||
|
||||
const verticalHudPosY = levelSelectionToggle.to([0, 1], [-2.5, 0]);
|
||||
const horizontalHudPosX = levelSelectionToggle.to([0, 1], [-4, -0.6]);
|
||||
const fstNumberRef = useRef<THREE.Mesh>();
|
||||
const sndNumberRef = useRef<THREE.Mesh>();
|
||||
const upArrowRef = useRef<THREE.Sprite>();
|
||||
const downArrowRef = useRef<THREE.Sprite>();
|
||||
|
||||
const generateGeom = useCallback((number: number) => {
|
||||
const geometry = new THREE.PlaneBufferGeometry();
|
||||
useEffect(() => {
|
||||
const generateGeom = (number: number) => {
|
||||
const geometry = new THREE.PlaneBufferGeometry();
|
||||
|
||||
const uvAttribute = geometry.attributes.uv;
|
||||
const uvAttribute = geometry.attributes.uv;
|
||||
|
||||
for (let i = 0; i < uvAttribute.count; i++) {
|
||||
let u = uvAttribute.getX(i);
|
||||
let v = uvAttribute.getY(i);
|
||||
for (let i = 0; i < uvAttribute.count; i++) {
|
||||
let u = uvAttribute.getX(i);
|
||||
let v = uvAttribute.getY(i);
|
||||
|
||||
u = (u * 22) / 240 + number / 10;
|
||||
u = (u * 22) / 240 + number / 10;
|
||||
|
||||
uvAttribute.setXY(i, u, v);
|
||||
uvAttribute.setXY(i, u, v);
|
||||
}
|
||||
return geometry;
|
||||
};
|
||||
|
||||
if (subscene === "level_selection") {
|
||||
set({ vertPosY: 0, horizPosX: -0.6 });
|
||||
if (fstNumberRef.current && sndNumberRef.current) {
|
||||
fstNumberRef.current.geometry = generateGeom(parseInt(activeLevel[0]));
|
||||
sndNumberRef.current.geometry = generateGeom(parseInt(activeLevel[1]));
|
||||
}
|
||||
} else if (
|
||||
subscene === "site" &&
|
||||
prevData?.subscene === "level_selection"
|
||||
) {
|
||||
set({ vertPosY: -2.5, horizPosX: -4 });
|
||||
}
|
||||
return geometry;
|
||||
}, []);
|
||||
if (selectedLevel !== prevData?.selectedLevel) {
|
||||
if (fstNumberRef.current && sndNumberRef.current) {
|
||||
fstNumberRef.current.geometry = generateGeom(
|
||||
parseInt(selectedLevel[0])
|
||||
);
|
||||
sndNumberRef.current.geometry = generateGeom(
|
||||
parseInt(selectedLevel[1])
|
||||
);
|
||||
|
||||
if (
|
||||
prevData?.selectedLevel &&
|
||||
upArrowRef.current &&
|
||||
downArrowRef.current
|
||||
) {
|
||||
if (selectedLevel > prevData?.selectedLevel) {
|
||||
upArrowRef.current.material.map = upArrowActiveTex;
|
||||
upArrowRef.current.material.needsUpdate = true;
|
||||
setTimeout(() => {
|
||||
upArrowRef.current!.material.map = upArrowTex;
|
||||
upArrowRef.current!.material.needsUpdate = true;
|
||||
}, 100);
|
||||
} else if (selectedLevel < prevData?.selectedLevel) {
|
||||
downArrowRef.current.material.map = downArrowActiveTex;
|
||||
downArrowRef.current.material.needsUpdate = true;
|
||||
setTimeout(() => {
|
||||
downArrowRef.current!.material.map = downArrowTex;
|
||||
downArrowRef.current!.material.needsUpdate = true;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [
|
||||
activeLevel,
|
||||
downArrowActiveTex,
|
||||
prevData?.selectedLevel,
|
||||
prevData?.subscene,
|
||||
selectedLevel,
|
||||
set,
|
||||
subscene,
|
||||
upArrowActiveTex,
|
||||
upArrowTex,
|
||||
]);
|
||||
|
||||
return (
|
||||
<group>
|
||||
<a.group position-y={verticalHudPosY} renderOrder={5}>
|
||||
<a.group position-y={pos.vertPosY} renderOrder={5}>
|
||||
<mesh
|
||||
scale={[0.3, 0.4, 0]}
|
||||
position={[0.95, 0, 0]}
|
||||
renderOrder={5}
|
||||
geometry={generateGeom(parseInt(selectedLevel[0]))}
|
||||
ref={fstNumberRef}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={levelSelectionFontTex}
|
||||
|
@ -76,7 +140,7 @@ const LevelSelection = () => {
|
|||
scale={[0.3, 0.4, 0]}
|
||||
position={[1.23, 0, 0]}
|
||||
renderOrder={5}
|
||||
geometry={generateGeom(parseInt(selectedLevel[1]))}
|
||||
ref={sndNumberRef}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={levelSelectionFontTex}
|
||||
|
@ -106,20 +170,28 @@ const LevelSelection = () => {
|
|||
scale={[0.3, 0.15, 0]}
|
||||
position={[1.1, -0.35, 0]}
|
||||
renderOrder={4}
|
||||
ref={downArrowRef}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={downArrowTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
color={0xffffff}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[0.3, 0.15, 0]} position={[1.1, 0.5, 0]} renderOrder={4}>
|
||||
<sprite
|
||||
scale={[0.3, 0.15, 0]}
|
||||
position={[1.1, 0.5, 0]}
|
||||
renderOrder={4}
|
||||
ref={upArrowRef}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={upArrowTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
color={0xffffff}
|
||||
/>
|
||||
</sprite>
|
||||
</a.group>
|
||||
|
@ -128,7 +200,7 @@ const LevelSelection = () => {
|
|||
scale={[3, 0.3, 0]}
|
||||
position={[-0.6, 0, 0]}
|
||||
renderOrder={4}
|
||||
position-x={horizontalHudPosX}
|
||||
position-x={pos.horizPosX}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={horizontalHudTex}
|
||||
|
|
|
@ -95,8 +95,8 @@ const Site = (props: SiteProps) => {
|
|||
rotation-y={siteState.siteRotY}
|
||||
position-y={siteState.sitePosY}
|
||||
>
|
||||
<ActiveLevelNodes />
|
||||
{/*<InactiveLevelNodes />*/}
|
||||
<ActiveLevelNodes visibleNodes={visibleNodes} />
|
||||
<InactiveLevelNodes visibleNodes={visibleNodes} />
|
||||
<NodeAnimations />
|
||||
<Rings
|
||||
activateAllRings={props.shouldIntro ? props.introFinished : true}
|
||||
|
|
|
@ -9,13 +9,11 @@ import { NodeDataType, SiteType } from "../Site";
|
|||
import usePrevious from "../../../../hooks/usePrevious";
|
||||
|
||||
type ActiveLevelNodesProps = {
|
||||
visibleNodes: any;
|
||||
visibleNodes: SiteType;
|
||||
};
|
||||
|
||||
const ActiveLevelNodes = memo((props: ActiveLevelNodesProps) => {
|
||||
const activeNodeId = useStore((state) => state.activeNode.id);
|
||||
const gameProgress = useStore((state) => state.gameProgress);
|
||||
const currentSite = useStore((state) => state.activeSite);
|
||||
const activeLevel = useStore((state) => state.activeLevel);
|
||||
const prevData = usePrevious({ activeLevel });
|
||||
|
||||
|
@ -24,7 +22,6 @@ const ActiveLevelNodes = memo((props: ActiveLevelNodesProps) => {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
const siteData = currentSite === "a" ? site_a : site_b;
|
||||
if (
|
||||
prevData?.activeLevel !== activeLevel &&
|
||||
prevData?.activeLevel !== undefined
|
||||
|
@ -32,36 +29,38 @@ const ActiveLevelNodes = memo((props: ActiveLevelNodesProps) => {
|
|||
const prevLevel = parseInt(prevData?.activeLevel);
|
||||
const newLevel = parseInt(activeLevel);
|
||||
if (prevLevel - 1 === newLevel || prevLevel + 1 === newLevel) {
|
||||
setVisibleNodes(siteData[activeLevel as keyof typeof siteData]);
|
||||
setVisibleNodes(
|
||||
props.visibleNodes[activeLevel as keyof typeof props.visibleNodes]
|
||||
);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
setVisibleNodes(siteData[activeLevel as keyof typeof siteData]);
|
||||
setVisibleNodes(
|
||||
props.visibleNodes[activeLevel as keyof typeof props.visibleNodes]
|
||||
);
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
}, [activeLevel, currentSite, gameProgress, prevData?.activeLevel]);
|
||||
}, [activeLevel, prevData?.activeLevel, props, props.visibleNodes]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.values(visibleNodes).map((node: NodeDataType) => {
|
||||
if (isNodeVisible(node, gameProgress)) {
|
||||
return (
|
||||
<Node
|
||||
nodeName={node.node_name}
|
||||
position={
|
||||
node_positions[node.id.substr(2) as keyof typeof node_positions]
|
||||
.position
|
||||
}
|
||||
rotation={
|
||||
node_positions[node.id.substr(2) as keyof typeof node_positions]
|
||||
.rotation
|
||||
}
|
||||
key={node.node_name}
|
||||
active={node.id === activeNodeId}
|
||||
level={node.id.substr(0, 2)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Node
|
||||
nodeName={node.node_name}
|
||||
position={
|
||||
node_positions[node.id.substr(2) as keyof typeof node_positions]
|
||||
.position
|
||||
}
|
||||
rotation={
|
||||
node_positions[node.id.substr(2) as keyof typeof node_positions]
|
||||
.rotation
|
||||
}
|
||||
key={node.node_name}
|
||||
active={node.id === activeNodeId}
|
||||
level={node.id.substr(0, 2)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import React, { memo, useMemo } from "react";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import { a } from "@react-spring/three";
|
||||
import * as THREE from "three";
|
||||
import Cou from "../../../../static/sprite/Cou.png";
|
||||
import Dc from "../../../../static/sprite/Dc.png";
|
||||
import SSkn from "../../../../static/sprite/SSkn.png";
|
||||
import Tda from "../../../../static/sprite/Tda.png";
|
||||
import Dia from "../../../../static/sprite/Dia.png";
|
||||
import Lda from "../../../../static/sprite/Lda.png";
|
||||
import MULTI from "../../../../static/sprite/MULTI.png";
|
||||
import level_y_values from "../../../../resources/level_y_values.json";
|
||||
|
||||
type NodeContructorProps = {
|
||||
nodeName: string;
|
||||
position: number[];
|
||||
rotation: number[];
|
||||
level: string;
|
||||
};
|
||||
|
||||
const InactiveLevelNode = memo((props: NodeContructorProps) => {
|
||||
const tex = useMemo(() => {
|
||||
if (props.nodeName.includes("S")) {
|
||||
return SSkn;
|
||||
} else if (
|
||||
props.nodeName.startsWith("P") ||
|
||||
props.nodeName.startsWith("G") ||
|
||||
props.nodeName.includes("?")
|
||||
) {
|
||||
return MULTI;
|
||||
} else if (props.nodeName.includes("Dc")) {
|
||||
return Dc;
|
||||
} else {
|
||||
switch (props.nodeName.substr(0, 3)) {
|
||||
case "Tda":
|
||||
return Tda;
|
||||
case "Cou":
|
||||
return Cou;
|
||||
case "Dia":
|
||||
return Dia;
|
||||
case "Lda":
|
||||
return Lda;
|
||||
case "Ere":
|
||||
case "Ekm":
|
||||
case "Eda":
|
||||
case "TaK":
|
||||
case "Env":
|
||||
return MULTI;
|
||||
}
|
||||
}
|
||||
}, [props.nodeName]);
|
||||
|
||||
const nonActiveTexture = useLoader(THREE.TextureLoader, tex!);
|
||||
|
||||
return (
|
||||
<group
|
||||
position={[
|
||||
0,
|
||||
level_y_values[props.level as keyof typeof level_y_values],
|
||||
0,
|
||||
]}
|
||||
>
|
||||
<a.mesh
|
||||
position-x={props.position[0]}
|
||||
position-y={props.position[1]}
|
||||
position-z={props.position[2]}
|
||||
rotation-y={props.rotation[1]}
|
||||
rotation-z={0}
|
||||
scale={[0.36, 0.18, 0.36]}
|
||||
renderOrder={1}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<meshStandardMaterial
|
||||
attach="material"
|
||||
map={nonActiveTexture}
|
||||
side={THREE.DoubleSide}
|
||||
transparent={true}
|
||||
/>
|
||||
</a.mesh>
|
||||
</group>
|
||||
);
|
||||
});
|
||||
|
||||
export default InactiveLevelNode;
|
|
@ -1,59 +1,60 @@
|
|||
import React, { useMemo, memo } from "react";
|
||||
import Node from "./Node";
|
||||
import React, { memo, useEffect, useState } from "react";
|
||||
import node_positions from "../../../../resources/node_positions.json";
|
||||
import { useStore } from "../../../../store";
|
||||
import { isNodeVisible } from "../../../../core/nodeSelector";
|
||||
import site_a from "../../../../resources/site_a.json";
|
||||
import site_b from "../../../../resources/site_b.json";
|
||||
import { SiteType } from "../Site";
|
||||
import InactiveLevelNode from "./InactiveLevelNode";
|
||||
import usePrevious from "../../../../hooks/usePrevious";
|
||||
import { generateInactiveNodes } from "../../../../core/utils/nodeUtils";
|
||||
|
||||
const InactiveLevelNodes = memo(() => {
|
||||
const gameProgress = useStore((state) => state.gameProgress);
|
||||
|
||||
const currentSite = useStore((state) => state.activeSite);
|
||||
|
||||
const siteData = useMemo(() => (currentSite === "a" ? site_a : site_b), [
|
||||
currentSite,
|
||||
]);
|
||||
type ActiveLevelNodesProps = {
|
||||
visibleNodes: SiteType;
|
||||
};
|
||||
|
||||
const InactiveLevelNodes = memo((props: ActiveLevelNodesProps) => {
|
||||
const activeLevel = useStore((state) => state.activeLevel);
|
||||
const prevData = usePrevious({ activeLevel });
|
||||
|
||||
const visibleNodes = useMemo(() => {
|
||||
const obj = {};
|
||||
const activeLevelNr = parseInt(activeLevel);
|
||||
const visibleLevels = [
|
||||
(activeLevelNr - 2).toString().padStart(2, "0"),
|
||||
(activeLevelNr - 1).toString().padStart(2, "0"),
|
||||
(activeLevelNr + 1).toString().padStart(2, "0"),
|
||||
(activeLevelNr + 2).toString().padStart(2, "0"),
|
||||
];
|
||||
const [visibleNodes, setVisibleNodes] = useState<{}>(
|
||||
generateInactiveNodes(props.visibleNodes, activeLevel)
|
||||
);
|
||||
|
||||
visibleLevels.forEach((level) => {
|
||||
Object.assign(obj, siteData[level as keyof typeof siteData]);
|
||||
});
|
||||
|
||||
return obj;
|
||||
}, [activeLevel, siteData]);
|
||||
useEffect(() => {
|
||||
if (
|
||||
prevData?.activeLevel !== activeLevel &&
|
||||
prevData?.activeLevel !== undefined
|
||||
) {
|
||||
const prevLevel = parseInt(prevData?.activeLevel);
|
||||
const newLevel = parseInt(activeLevel);
|
||||
if (prevLevel - 1 === newLevel || prevLevel + 1 === newLevel) {
|
||||
setVisibleNodes(generateInactiveNodes(props.visibleNodes, activeLevel));
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
setVisibleNodes(
|
||||
generateInactiveNodes(props.visibleNodes, activeLevel)
|
||||
);
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
}, [activeLevel, prevData?.activeLevel, props.visibleNodes]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.entries(visibleNodes).map((node: [string, any]) => {
|
||||
if (isNodeVisible(node[1], gameProgress)) {
|
||||
return (
|
||||
<Node
|
||||
nodeName={node[1].node_name}
|
||||
position={
|
||||
node_positions[node[0].substr(2) as keyof typeof node_positions]
|
||||
.position
|
||||
}
|
||||
rotation={
|
||||
node_positions[node[0].substr(2) as keyof typeof node_positions]
|
||||
.rotation
|
||||
}
|
||||
key={node[1].node_name}
|
||||
level={node[0].substr(0, 2)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<InactiveLevelNode
|
||||
nodeName={node[1].node_name}
|
||||
position={
|
||||
node_positions[node[0].substr(2) as keyof typeof node_positions]
|
||||
.position
|
||||
}
|
||||
rotation={
|
||||
node_positions[node[0].substr(2) as keyof typeof node_positions]
|
||||
.rotation
|
||||
}
|
||||
key={node[1].node_name}
|
||||
level={node[0].substr(0, 2)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ type NodeContructorProps = {
|
|||
nodeName: string;
|
||||
position: number[];
|
||||
rotation: number[];
|
||||
active?: boolean;
|
||||
active: boolean;
|
||||
level: string;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,8 +6,17 @@ const LevelSelectionManager = (props: StateManagerProps) => {
|
|||
const setSelectedLevel = useStore((state) => state.setSelectedLevel);
|
||||
|
||||
const dispatchObject = useCallback(
|
||||
(eventState: { event: string; selectedLevelIdx: number }) => {
|
||||
(eventState: {
|
||||
event: string;
|
||||
selectedLevelIdx: number;
|
||||
level: number;
|
||||
}) => {
|
||||
switch (eventState.event) {
|
||||
case "toggle_level_selection":
|
||||
return {
|
||||
action: setSelectedLevel,
|
||||
value: eventState.level,
|
||||
};
|
||||
case "level_selection_up":
|
||||
case "level_selection_down":
|
||||
return {
|
||||
|
|
|
@ -90,7 +90,7 @@ const handleMainSceneEvent = (gameContext: any) => {
|
|||
}
|
||||
break;
|
||||
case "L2":
|
||||
return { event: "toggle_level_selection" };
|
||||
return { event: "toggle_level_selection", level: level };
|
||||
case "TRIANGLE":
|
||||
return { event: "pause_game" };
|
||||
case "SPACE":
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import {
|
||||
NodeDataType,
|
||||
SiteType,
|
||||
} from "../../components/MainScene/SyncedComponents/Site";
|
||||
import { SiteType } from "../../components/MainScene/SyncedComponents/Site";
|
||||
import game_progress from "../../resources/initial_progress.json";
|
||||
import { isNodeVisible } from "../nodeSelector";
|
||||
|
||||
|
@ -9,10 +6,13 @@ const filterInvisibleNodes = (
|
|||
siteData: SiteType,
|
||||
gameProgress: typeof game_progress
|
||||
) => {
|
||||
const visibleNodes: NodeDataType[] = [];
|
||||
Object.values(siteData).forEach((level) => {
|
||||
Object.values(level).forEach((node) => {
|
||||
if (isNodeVisible(node, gameProgress)) visibleNodes.push(node);
|
||||
const visibleNodes: SiteType = {};
|
||||
Object.entries(siteData).forEach((level) => {
|
||||
visibleNodes[level[0]] = {};
|
||||
Object.entries(level[1]).forEach((node) => {
|
||||
if (isNodeVisible(node[1], gameProgress)) {
|
||||
visibleNodes[level[0]][node[0]] = node[1];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
21
src/core/utils/nodeUtils.ts
Normal file
21
src/core/utils/nodeUtils.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { SiteType } from "../../components/MainScene/SyncedComponents/Site";
|
||||
|
||||
export const generateInactiveNodes = (
|
||||
visibleNodes: SiteType,
|
||||
activeLevel: string
|
||||
) => {
|
||||
const obj = {};
|
||||
const activeLevelNr = parseInt(activeLevel);
|
||||
const visibleLevels = [
|
||||
(activeLevelNr - 2).toString().padStart(2, "0"),
|
||||
(activeLevelNr - 1).toString().padStart(2, "0"),
|
||||
(activeLevelNr + 1).toString().padStart(2, "0"),
|
||||
(activeLevelNr + 2).toString().padStart(2, "0"),
|
||||
];
|
||||
|
||||
visibleLevels.forEach((level) => {
|
||||
Object.assign(obj, visibleNodes[level as keyof typeof visibleNodes]);
|
||||
});
|
||||
|
||||
return obj;
|
||||
};
|
Loading…
Reference in a new issue