Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring: move "running" and "show edges" flags to useConfigStore. #820

Merged
merged 3 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions client/src/features/visualizer-threejs/Emitter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@ import { useFrame, useThree } from "@react-three/fiber";
import React, { RefObject, Dispatch, SetStateAction, useEffect } from "react";
import * as THREE from "three";
import { useBorderPositions } from "./hooks/useBorderPositions";
import { useBlockStore } from "./store";
import { useConfigStore } from "./store";
import { useRenderTangle } from "./useRenderTangle";

interface EmitterProps {
readonly setRunListeners: Dispatch<SetStateAction<boolean>>;
readonly emitterRef: RefObject<THREE.Mesh>;
readonly isEdgeRenderingEnabled: boolean;
}

const Emitter: React.FC<EmitterProps> = ({
setRunListeners,
emitterRef,
isEdgeRenderingEnabled
emitterRef
}: EmitterProps) => {
const isPlaying = useBlockStore(state => state.isPlaying);
const isPlaying = useConfigStore(state => state.isPlaying);
const get = useThree(state => state.get);
const { halfScreenWidth } = useBorderPositions();

Expand Down Expand Up @@ -53,7 +51,7 @@ const Emitter: React.FC<EmitterProps> = ({
});

// The Tangle rendering hook
useRenderTangle(isEdgeRenderingEnabled);
useRenderTangle();

return (
<mesh
Expand Down
34 changes: 17 additions & 17 deletions client/src/features/visualizer-threejs/VisualizerInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import { CameraControls, OrthographicCamera } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { Perf } from "r3f-perf";
import React, { useEffect, useRef, useState } from "react";
import React, { useEffect, useRef } from "react";
import { RouteComponentProps } from "react-router-dom";
import * as THREE from "three";
import { Box3 } from "three";
import { COLORS, TIME_DIFF_COUNTER, ZOOM_DEFAULT } from "./constants";
import Emitter from "./Emitter";
import { useBlockStore } from "./store";
import { useTangleStore, useConfigStore } from "./store";
import { getGenerateY, randomIntFromInterval, timer } from "./utils";
import { BPSCounter } from "./worker/entities/BPSCounter";
import { Wrapper } from "../../app/components/stardust/Visualizer/Wrapper";
Expand All @@ -31,29 +31,30 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
params: { network }
}
}) => {
const [isEdgeRenderingEnabled, setEdgeRenderingEnabled] = useState(false);
const setDimensions = useBlockStore(s => s.setDimensions);
const [networkConfig] = useNetworkConfig(network);
const generateY = getGenerateY({ withRandom: true });

const [runListeners, setRunListeners] = React.useState<boolean>(false);

const setBps = useBlockStore(s => s.setBps);
const setBps = useTangleStore(s => s.setBps);
const [bpsCounter] = React.useState(new BPSCounter(bps => {
setBps(bps);
}));

// Note: to prevent rerender each store update - call methods separate.
const addBlock = useBlockStore(s => s.addToBlockQueue);
const addToScaleQueue = useBlockStore(s => s.addToScaleQueue);
const addToEdgeQueue = useBlockStore(s => s.addToEdgeQueue);
const addYPosition = useBlockStore(s => s.addYPosition);
const checkZoom = useBlockStore(s => s.checkZoom);
const setIsPlaying = useBlockStore(s => s.setIsPlaying);

const isPlaying = useBlockStore(s => s.isPlaying);
const blockIdToPosition = useBlockStore(s => s.blockIdToPosition);
const indexToBlockId = useBlockStore(s => s.indexToBlockId);
const isEdgeRenderingEnabled = useConfigStore(s => s.isEdgeRenderingEnabled);
const setEdgeRenderingEnabled = useConfigStore(s => s.setEdgeRenderingEnabled);
const canvasHeight = useConfigStore(s => s.dimensions.height);
const setDimensions = useConfigStore(s => s.setDimensions);
const isPlaying = useConfigStore(s => s.isPlaying);
const setIsPlaying = useConfigStore(s => s.setIsPlaying);
const addBlock = useTangleStore(s => s.addToBlockQueue);
const addToScaleQueue = useTangleStore(s => s.addToScaleQueue);
const addToEdgeQueue = useTangleStore(s => s.addToEdgeQueue);
const addYPosition = useTangleStore(s => s.addYPosition);
const checkZoom = useTangleStore(s => s.checkZoom);
const blockIdToPosition = useTangleStore(s => s.blockIdToPosition);
const indexToBlockId = useTangleStore(s => s.indexToBlockId);

const emitterRef = useRef<THREE.Mesh>(null);
const feedServiceRef = useRef<StardustFeedClient | null>(null);
Expand Down Expand Up @@ -156,7 +157,7 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
addToScaleQueue(blockData.blockId, blockData.parents ?? []);
addToEdgeQueue(blockData.blockId, blockData.parents ?? []);
addYPosition(Y);
checkZoom();
checkZoom(canvasHeight);
}
};

Expand Down Expand Up @@ -221,7 +222,6 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
<Emitter
emitterRef={emitterRef}
setRunListeners={setRunListeners}
isEdgeRenderingEnabled={isEdgeRenderingEnabled}
/>
{features.cameraControls && <CameraControls makeDefault />}
{features.statsEnabled && <Perf />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo } from "react";
import { useBlockStore } from "../store";
import { useTangleStore, useConfigStore } from "../store";

export const useBorderPositions = () => {
const zoom = useBlockStore(s => s.zoom);
const canvasWidth = useBlockStore(state => state.dimensions.width);
const zoom = useTangleStore(s => s.zoom);
const canvasWidth = useConfigStore(state => state.dimensions.width);

const borderLeftPosition = useMemo(() => -(canvasWidth / zoom / 2), [canvasWidth, zoom]);
const halfScreenWidth = useMemo(() => canvasWidth / zoom / 2, [canvasWidth, zoom]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useThree } from "@react-three/fiber";
import { useEffect } from "react";
import { useBlockStore } from "../store";
import { useTangleStore } from "../store";

export const useZoomDynamic = () => {
/**
* Zoom Changes
*/
const cameraState = useThree(state => state.camera);
const zoomStore = useBlockStore(s => s.zoom);
const zoomStore = useTangleStore(s => s.zoom);
useEffect(() => {
if (cameraState) {
cameraState.zoom = zoomStore;
Expand Down
49 changes: 49 additions & 0 deletions client/src/features/visualizer-threejs/store/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { create } from "zustand";


interface ConfigState {
dimensions: { width: number; height: number };
setDimensions: (width: number, height: number) => void;

isPlaying: boolean;
setIsPlaying: (isPlaying: boolean) => void;

isEdgeRenderingEnabled: boolean;
setEdgeRenderingEnabled: (isEdgeRenderingEnabled: boolean) => void;
}

export const useConfigStore = create<ConfigState>(set => ({
/**
* Canvas dimensions
*/
dimensions: { width: 0, height: 0 },
setDimensions: (width, height) => {
set(state => ({
...state,
dimensions: { width, height }
})
);
},

/**
* Is animation playing
*/
isPlaying: false,
setIsPlaying: isPlaying => {
set(state => ({
...state,
isPlaying
}));
},

/**
* Is edge rendering enabled
*/
isEdgeRenderingEnabled: false,
setEdgeRenderingEnabled: isEdgeRenderingEnabled => {
set(state => ({
...state,
isEdgeRenderingEnabled
}));
}
}));
2 changes: 2 additions & 0 deletions client/src/features/visualizer-threejs/store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./tangle";
export * from "./config";
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Color } from "three";
import { create } from "zustand";
import { ZOOM_DEFAULT } from "./constants";
import { getScaleMultiplier } from "./utils";
import { ZOOM_DEFAULT } from "../constants";
import { getScaleMultiplier } from "../utils";

interface BlockState {
id: string;
Expand All @@ -19,7 +19,7 @@ interface EdgeEntry {
toPositions: [x: number, y: number, z: number][];
}

interface BlockStoreState {
interface TangleState {
// Queue for "add block" operation to the canvas
blockQueue: BlockState[];
addToBlockQueue: (newBlock: BlockState) => void;
Expand All @@ -46,20 +46,14 @@ interface BlockStoreState {
removeYPosition: (blockY: number) => void;

zoom: number;
checkZoom: () => void;
checkZoom: (canvasHeight: number) => void;
setZoom: (zoom: number) => void;

dimensions: { width: number; height: number };
setDimensions: (width: number, height: number) => void;

isPlaying: boolean;
setIsPlaying: (isPlaying: boolean) => void;

bps: number;
setBps: (bps: number) => void;
}

export const useBlockStore = create<BlockStoreState>(set => ({
export const useTangleStore = create<TangleState>(set => ({
blockQueue: [],
scaleQueue: [],
edgeQueue: [],
Expand All @@ -69,8 +63,6 @@ export const useBlockStore = create<BlockStoreState>(set => ({
indexToBlockId: [],
yPositions: {},
zoom: ZOOM_DEFAULT,
dimensions: { width: 0, height: 0 },
isPlaying: false,
bps: 0,
addToBlockQueue: newBlockData => {
set(state => ({
Expand Down Expand Up @@ -181,10 +173,10 @@ export const useBlockStore = create<BlockStoreState>(set => ({
};
});
},
checkZoom: () => {
checkZoom: (canvasHeight: number) => {
set(state => {
const yPositions = Object.keys(state.yPositions).map(Number);
const multiplier = getScaleMultiplier(yPositions, state.dimensions.height);
const multiplier = getScaleMultiplier(yPositions, canvasHeight);

return {
...state,
Expand All @@ -198,19 +190,6 @@ export const useBlockStore = create<BlockStoreState>(set => ({
zoom
}));
},
setDimensions: (width, height) => {
set(state => ({
...state,
dimensions: { width, height }
})
);
},
setIsPlaying: isPlaying => {
set(state => ({
...state,
isPlaying
}));
},
setBps: bps => {
set(state => ({
...state,
Expand Down
18 changes: 10 additions & 8 deletions client/src/features/visualizer-threejs/useRenderEdges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ import { useThree } from "@react-three/fiber";
import { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { Color } from "three";
import { useBlockStore } from "./store";
import { useConfigStore, useTangleStore } from "./store";

const EDGE_MATERIAL = new THREE.LineBasicMaterial({ color: new Color("#d8dbdf"), transparent: true });

export const useRenderEdges = (edgeRenderingEnabled: boolean) => {
export const useRenderEdges = () => {
const edgesMeshRef = useRef(new THREE.BufferGeometry());
const scene = useThree(state => state.scene);

const edgeQueue = useBlockStore(s => s.edgeQueue);
const removeFromEdgeQueue = useBlockStore(s => s.removeFromEdgeQueue);
const isEdgeRenderingEnabled = useConfigStore(s => s.isEdgeRenderingEnabled);

const blockIdToEdges = useBlockStore(s => s.blockIdToEdges);
const blockIdToPosition = useBlockStore(s => s.blockIdToPosition);
const edgeQueue = useTangleStore(s => s.edgeQueue);
const removeFromEdgeQueue = useTangleStore(s => s.removeFromEdgeQueue);

const blockIdToEdges = useTangleStore(s => s.blockIdToEdges);
const blockIdToPosition = useTangleStore(s => s.blockIdToPosition);

const [linePoints, setLinePoints] = useState<number[]>([]);
const indices = useRef<number[]>([]);
Expand Down Expand Up @@ -54,7 +56,7 @@ export const useRenderEdges = (edgeRenderingEnabled: boolean) => {

// Re-draws the 'LineSegments' every time the linePoints change
useEffect(() => {
if (edgeRenderingEnabled && edgesMeshRef.current) {
if (isEdgeRenderingEnabled && edgesMeshRef.current) {
const pointsBuffer = new THREE.Float32BufferAttribute(linePoints, 3);
edgesMeshRef.current.setAttribute("position", pointsBuffer);
edgesMeshRef.current.setIndex(indices.current);
Expand All @@ -73,7 +75,7 @@ export const useRenderEdges = (edgeRenderingEnabled: boolean) => {
const oldEdges = scene.getObjectByName("edges");
oldEdges?.removeFromParent();
}
}, [linePoints, edgeRenderingEnabled]);
}, [linePoints, isEdgeRenderingEnabled]);

/**
* Computes the update points array from the blockIdToEdges map.
Expand Down
20 changes: 9 additions & 11 deletions client/src/features/visualizer-threejs/useRenderTangle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,29 @@ import * as THREE from "three";
import { MAX_BLOCK_INSTANCES, NODE_SIZE_DEFAULT } from "./constants";
import { useMouseMove } from "./hooks/useMouseMove";
import { useZoomDynamic } from "./hooks/useZoomDynamic";
import { useBlockStore } from "./store";
import { useTangleStore } from "./store";
import { useRenderEdges } from "./useRenderEdges";

const SPHERE_GEOMETRY = new THREE.SphereGeometry(NODE_SIZE_DEFAULT, 32, 16);
const SPHERE_MATERIAL = new THREE.MeshPhongMaterial();
const SPHERE_TEMP_OBJECT = new THREE.Object3D();
const SCALE_INCREMENT = 0.1;

export const useRenderTangle = (
isEdgeRenderingEnabled: boolean
) => {
export const useRenderTangle = () => {
const tangleMeshRef = useRef(new THREE.InstancedMesh(SPHERE_GEOMETRY, SPHERE_MATERIAL, MAX_BLOCK_INSTANCES));
const objectIndexRef = useRef(0);
const clearBlocksRef = useRef<() => void>();
const { scene } = useThree();

const blockQueue = useBlockStore(s => s.blockQueue);
const removeFromBlockQueue = useBlockStore(s => s.removeFromBlockQueue);
const scaleQueue = useBlockStore(s => s.scaleQueue);
const removeFromScaleQueue = useBlockStore(s => s.removeFromScaleQueue);
const blockQueue = useTangleStore(s => s.blockQueue);
const removeFromBlockQueue = useTangleStore(s => s.removeFromBlockQueue);
const scaleQueue = useTangleStore(s => s.scaleQueue);
const removeFromScaleQueue = useTangleStore(s => s.removeFromScaleQueue);

const blockIdToIndex = useBlockStore(s => s.blockIdToIndex);
const updateBlockIdToIndex = useBlockStore(s => s.updateBlockIdToIndex);
const blockIdToIndex = useTangleStore(s => s.blockIdToIndex);
const updateBlockIdToIndex = useTangleStore(s => s.updateBlockIdToIndex);

useRenderEdges(isEdgeRenderingEnabled);
useRenderEdges();
useMouseMove({ tangleMeshRef });
useZoomDynamic();

Expand Down