Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into feat/add-state-tab
Browse files Browse the repository at this point in the history
  • Loading branch information
begonaalvarezd committed Feb 22, 2024
2 parents 1d9ef02 + 42477e3 commit 43f0cb7
Show file tree
Hide file tree
Showing 19 changed files with 556 additions and 320 deletions.
9 changes: 5 additions & 4 deletions api/src/initServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,11 @@ function initNovaServices(networkConfig: INetwork): void {
};

if (networkConfig.permaNodeEndpoint) {
novaClientParams.nodes = [networkConfig.permaNodeEndpoint];
// Client with permanode needs the ignoreNodeHealth as chronicle is considered "not healthy" by the sdk
// Related: https://github.com/iotaledger/inx-chronicle/issues/1302
novaClientParams.ignoreNodeHealth = true;
const chronicleNode = {
url: networkConfig.permaNodeEndpoint,
permanode: true,
};
novaClientParams.primaryNodes.push(chronicleNode);

const chronicleService = new ChronicleService(networkConfig);
ServiceFactory.register(`chronicle-${networkConfig.network}`, () => chronicleService);
Expand Down
58 changes: 40 additions & 18 deletions client/src/features/visualizer-threejs/CameraControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,56 @@ import { getCameraAngles } from "./utils";
import React, { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import { CanvasElement } from "./enums";
import { useTangleStore } from "./store";
import { VISUALIZER_PADDINGS } from "./constants";

const CAMERA_ANGLES = getCameraAngles();

const CameraControls = () => {
const [shouldLockZoom, setShouldLockZoom] = React.useState<boolean>(false);
const controls = React.useRef<DreiCameraControls>(null);

const CAMERA_ANGLES = getCameraAngles();
const scene = useThree((state) => state.scene);
const mesh = scene.getObjectByName(CanvasElement.TangleWrapperMesh) as THREE.Mesh | undefined;

const zoom = useTangleStore((s) => s.zoom);
const get = useThree((state) => state.get);
const mesh = get().scene.getObjectByName(CanvasElement.TangleWrapperMesh);
/**
* Locks the camera zoom to the current zoom value.
*/
function lockCameraZoom(controls: DreiCameraControls) {
const zoom = controls.camera.zoom;
controls.maxZoom = zoom;
controls.minZoom = zoom;
}

// Set fixed zoom
useEffect(() => {
if (controls.current && shouldLockZoom) {
controls.current.maxZoom = zoom;
controls.current.minZoom = zoom;
/**
* Unlocks the camera zoom for free movement.
*/
function unlockCameraZoom(controls: DreiCameraControls) {
controls.maxZoom = Infinity;
controls.minZoom = 0.01;
}

/**
* Fits the camera to the TangleMesh.
*/
function fitCameraToTangle(controls: DreiCameraControls | null, mesh?: THREE.Mesh) {
if (controls && mesh) {
unlockCameraZoom(controls);
controls.fitToBox(mesh, false, { ...VISUALIZER_PADDINGS });
controls.setOrbitPoint(0, 0, 0);
lockCameraZoom(controls);
}
}, [controls, zoom, shouldLockZoom]);
}

// Fix to TangleMesh
/**
* Fit camera to TangleMesh on mount and on window resize.
*/
useEffect(() => {
if (controls.current && mesh) {
controls.current.fitToBox(mesh, false, { ...VISUALIZER_PADDINGS });
controls.current.setOrbitPoint(0, 0, 0);
setShouldLockZoom(true);
}
const adjustCamera = () => fitCameraToTangle(controls.current, mesh);
adjustCamera();

window.addEventListener("resize", adjustCamera);
return () => {
window.removeEventListener("resize", adjustCamera);
};
}, [controls, mesh]);

return <DreiCameraControls ref={controls} makeDefault {...CAMERA_ANGLES} />;
Expand Down
97 changes: 41 additions & 56 deletions client/src/features/visualizer-threejs/Emitter.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
/* eslint-disable react/no-unknown-property */
import { useFrame, useThree } from "@react-three/fiber";
import React, { RefObject, Dispatch, SetStateAction, useEffect, useRef } from "react";
import React, { RefObject, Dispatch, SetStateAction, useEffect, useRef, useLayoutEffect } from "react";
import * as THREE from "three";
import { useConfigStore, useTangleStore } from "./store";
import { useRenderTangle } from "./useRenderTangle";
import { getTangleDistances, getSinusoidalPosition } from "./utils";
import { getTangleDistances, getEmitterPositions, generateRandomPeriods } from "./utils";
import { CanvasElement } from "./enums";
import {
EMITTER_SPEED_MULTIPLIER,
EMITTER_DEPTH,
EMITTER_HEIGHT,
EMITTER_WIDTH,
MAX_SINUSOIDAL_AMPLITUDE,
SINUSOIDAL_AMPLITUDE_ACCUMULATOR,
HALF_WAVE_PERIOD_SECONDS,
INITIAL_SINUSOIDAL_AMPLITUDE,
} from "./constants";
import useVisualizerTimer from "~/helpers/nova/hooks/useVisualizerTimer";
import { EMITTER_DEPTH, EMITTER_HEIGHT, EMITTER_WIDTH } from "./constants";

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

const { xTangleDistance, yTangleDistance } = getTangleDistances();

const Emitter: React.FC<EmitterProps> = ({ setRunListeners, emitterRef }: EmitterProps) => {
const getVisualizerTimeDiff = useVisualizerTimer();

const setZoom = useTangleStore((s) => s.setZoom);
const get = useThree((state) => state.get);
const currentZoom = useThree((state) => state.camera.zoom);
const groupRef = useRef<THREE.Group>(null);
const camera = get().camera;

const { xTangleDistance, yTangleDistance } = getTangleDistances();
const isPlaying = useConfigStore((state) => state.isPlaying);
const setIsPlaying = useConfigStore((state) => state.setIsPlaying);
const setInitialTime = useConfigStore((state) => state.setInitialTime);

const sinusoidPeriodsSum = useConfigStore((state) => state.sinusoidPeriodsSum);
const setSinusoidPeriodsSum = useConfigStore((state) => state.setSinusoidPeriodsSum);
const randomizedSinusoidPeriods = useConfigStore((state) => state.sinusoidRandomPeriods);
const setRandomizedSinusoidPeriods = useConfigStore((state) => state.setSinusoidRandomPeriods);

const animationTime = useRef<number>(0);
const currentAmplitude = useRef<number>(INITIAL_SINUSOIDAL_AMPLITUDE);
const tangleWrapperRef = useRef<THREE.Mesh | null>(null);

const previousRealTime = useRef<number>(0);
const previousPeakTime = useRef<number>(0);
useLayoutEffect(() => {
const { periods, sum: periodsSum } = generateRandomPeriods();
setRandomizedSinusoidPeriods(periods);
setSinusoidPeriodsSum(periodsSum);
}, []);

useEffect(() => {
setZoom(currentZoom);
Expand All @@ -47,6 +49,7 @@ const Emitter: React.FC<EmitterProps> = ({ setRunListeners, emitterRef }: Emitte
if (emitterRef?.current) {
setIsPlaying(true);
setRunListeners(true);
setInitialTime(Date.now());
}

return () => {
Expand All @@ -55,68 +58,50 @@ const Emitter: React.FC<EmitterProps> = ({ setRunListeners, emitterRef }: Emitte
};
}, [emitterRef?.current]);

useFrame(() => {
if (camera && groupRef.current) {
camera.position.x = groupRef.current.position.x;
}
});

function updateAnimationTime(realTimeDelta: number): void {
animationTime.current += realTimeDelta;
}

function checkAndHandleNewPeak(): void {
const currentHalfWaveCount = Math.floor(animationTime.current / HALF_WAVE_PERIOD_SECONDS);
const lastPeakHalfWaveCount = Math.floor(previousPeakTime.current / HALF_WAVE_PERIOD_SECONDS);

if (currentHalfWaveCount > lastPeakHalfWaveCount) {
currentAmplitude.current = Math.min(currentAmplitude.current + SINUSOIDAL_AMPLITUDE_ACCUMULATOR, MAX_SINUSOIDAL_AMPLITUDE);
previousPeakTime.current = animationTime.current;
}
}

/**
* Emitter shift
*/
useFrame(({ clock }, delta) => {
const currentRealTime = clock.getElapsedTime();
const realTimeDelta = currentRealTime - previousRealTime.current;
previousRealTime.current = currentRealTime;
useFrame(() => {
const currentAnimationTime = getVisualizerTimeDiff();
const { x, y } = getEmitterPositions({
currentAnimationTime,
periods: randomizedSinusoidPeriods,
periodsSum: sinusoidPeriodsSum,
});

if (isPlaying) {
updateAnimationTime(realTimeDelta);
checkAndHandleNewPeak();

if (groupRef.current) {
const { x } = groupRef.current.position;
const newXPos = x + delta * EMITTER_SPEED_MULTIPLIER;
groupRef.current.position.x = newXPos;
if (emitterRef.current) {
emitterRef.current.position.x = x;
emitterRef.current.position.y = y;
}

if (emitterRef.current) {
const newYPos = getSinusoidalPosition(animationTime.current, currentAmplitude.current);
emitterRef.current.position.y = newYPos;
if (tangleWrapperRef.current) {
tangleWrapperRef.current.position.x = x - xTangleDistance / 2;
}
}

if (tangleWrapperRef.current && camera) {
camera.position.x = tangleWrapperRef.current.position.x + xTangleDistance / 2;
}
});

// The Tangle rendering hook
useRenderTangle();

return (
<group ref={groupRef}>
<>
{/* TangleWrapper Mesh */}
<mesh name={CanvasElement.TangleWrapperMesh} position={[-(xTangleDistance / 2), 0, 0]}>
<mesh ref={tangleWrapperRef} name={CanvasElement.TangleWrapperMesh} position={[-(xTangleDistance / 2), 0, 0]}>
<boxGeometry args={[xTangleDistance, yTangleDistance, 0]} attach="geometry" />
<meshPhongMaterial transparent opacity={0} wireframe={true} attach="material" />
<meshPhongMaterial transparent opacity={0} attach="material" />
</mesh>

{/* Emitter Mesh */}
<mesh ref={emitterRef} name={CanvasElement.EmitterMesh} position={[0, 0, 0]}>
<boxGeometry args={[EMITTER_WIDTH, EMITTER_HEIGHT, EMITTER_DEPTH]} />
<meshPhongMaterial transparent opacity={0} />
</mesh>
</group>
</>
);
};
export default Emitter;
68 changes: 0 additions & 68 deletions client/src/features/visualizer-threejs/Visualizer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,74 +83,6 @@
}
}

.stats-panel-container {
display: flex;
position: absolute;
z-index: 1;
top: 90px !important;
left: 20px !important;
bottom: auto !important;
justify-content: left !important;
align-items: center;
pointer-events: none;

.stats-panel {
background: var(--body-background);

.card--value,
.card--label {
text-align: left;
}
.card--label {
justify-content: flex-start;
}
.card--content {
padding: 0;
}
.stats-panel__info {
padding: 0 10px;
display: inline-block;
}
}

@include tablet-down {
top: 60px;
left: 20px;
bottom: auto;
justify-content: left;

.stats-panel {
.card--value,
.card--label {
text-align: left;
}
.card--label {
justify-content: flex-start;
}
.card--content {
padding: 0;
}
.stats-panel__info {
padding: 0 10px;
display: inline-block;
}
}
}

@include phone-down {
left: 10px;
.stats-panel {
.card--value,
.card--label {
font-size: 12px;
}
.stats-panel__info:last-of-type {
display: block;
}
}
}
}

.info-panel {
background: var(--body-background);
display: flex;
Expand Down
Loading

0 comments on commit 43f0cb7

Please sign in to comment.