mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-24 06:58:48 -05:00
refactor: simplifies renderer component
This commit is contained in:
@@ -16,7 +16,7 @@ import { sceneToSceneInput } from 'src/utils';
|
||||
import { useSceneStore, SceneProvider } from 'src/stores/sceneStore';
|
||||
import { GlobalStyles } from 'src/styles/GlobalStyles';
|
||||
import { Renderer } from 'src/components/Renderer/Renderer';
|
||||
import { LabelContainer } from 'src/components/Node/LabelContainer';
|
||||
import { LabelContainer } from 'src/components/Nodes/Node/LabelContainer';
|
||||
import { useWindowUtils } from 'src/hooks/useWindowUtils';
|
||||
import { sceneInput as sceneValidationSchema } from 'src/validation/scene';
|
||||
import { EMPTY_SCENE } from 'src/config';
|
||||
|
||||
28
src/components/Connectors/Connectors.tsx
Normal file
28
src/components/Connectors/Connectors.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { Connector } from './Connector/Connector';
|
||||
|
||||
export const Connectors = () => {
|
||||
const connectors = useSceneStore((state) => {
|
||||
return state.connectors;
|
||||
});
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{connectors.map((connector) => {
|
||||
return (
|
||||
<>
|
||||
<Connector key={connector.id} connector={connector} />
|
||||
{mode.type === 'CONNECTOR' && mode.connector && (
|
||||
<Connector connector={mode.connector} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,14 +1,12 @@
|
||||
import React from 'react';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { Coords } from 'src/types';
|
||||
import { IsoTileArea } from 'src/components/IsoTileArea/IsoTileArea';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
|
||||
interface Props {
|
||||
tile: Coords;
|
||||
}
|
||||
|
||||
export const Cursor = ({ tile }: Props) => {
|
||||
export const Cursor = () => {
|
||||
const tile = useUiStateStore((state) => {
|
||||
return state.mouse.position.tile;
|
||||
});
|
||||
const zoom = useUiStateStore((state) => {
|
||||
return state.zoom;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Box, useTheme } from '@mui/material';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { SizeIndicator } from './SizeIndicator';
|
||||
import { LineItem } from './LineItem';
|
||||
|
||||
@@ -11,6 +12,9 @@ export const DebugUtils = () => {
|
||||
const uiState = useUiStateStore(({ scroll, mouse, zoom, rendererSize }) => {
|
||||
return { scroll, mouse, zoom, rendererSize };
|
||||
});
|
||||
const scene = useSceneStore((state) => {
|
||||
return state;
|
||||
});
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
@@ -73,6 +77,7 @@ export const DebugUtils = () => {
|
||||
title="Size"
|
||||
value={`${rendererSize.width}, ${rendererSize.height}`}
|
||||
/>
|
||||
<LineItem title="Scene info" value={`${scene.nodes.length} nodes`} />
|
||||
<LineItem title="Mode" value={mode.type} />
|
||||
<LineItem title="Mode data" value={JSON.stringify(mode)} />
|
||||
</Box>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { Coords, TileOriginEnum, IconInput } from 'src/types';
|
||||
import { useGetTilePosition } from 'src/hooks/useGetTilePosition';
|
||||
import { NodeIcon } from 'src/components/Node/NodeIcon';
|
||||
import { NodeIcon } from 'src/components/Nodes/Node/NodeIcon';
|
||||
|
||||
interface Props {
|
||||
icon: IconInput;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import gridTileSvg from 'src/assets/grid-tile-bg.svg';
|
||||
import { Scroll } from 'src/types';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { getProjectedTileSize } from 'src/utils';
|
||||
|
||||
interface Props {
|
||||
scroll: Scroll;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
export const Grid = ({ zoom, scroll }: Props) => {
|
||||
export const Grid = () => {
|
||||
const scroll = useUiStateStore((state) => {
|
||||
return state.scroll;
|
||||
});
|
||||
const zoom = useUiStateStore((state) => {
|
||||
return state.zoom;
|
||||
});
|
||||
const projectedTileSize = useMemo(() => {
|
||||
return getProjectedTileSize({ zoom });
|
||||
}, [zoom]);
|
||||
|
||||
33
src/components/Groups/Groups.tsx
Normal file
33
src/components/Groups/Groups.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { DEFAULT_COLOR } from 'src/config';
|
||||
import { Group } from './Group/Group';
|
||||
|
||||
export const Groups = () => {
|
||||
const groups = useSceneStore((state) => {
|
||||
return state.groups;
|
||||
});
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{groups.map((group) => {
|
||||
return (
|
||||
<>
|
||||
<Group key={group.id} {...group} />
|
||||
{mode.type === 'AREA_TOOL' && mode.area && (
|
||||
<Group
|
||||
from={mode.area.from}
|
||||
to={mode.area.to}
|
||||
color={DEFAULT_COLOR}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
29
src/components/Nodes/Nodes.tsx
Normal file
29
src/components/Nodes/Nodes.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { Node } from './Node/Node';
|
||||
|
||||
export const Nodes = () => {
|
||||
const nodes = useSceneStore((state) => {
|
||||
return state.nodes;
|
||||
});
|
||||
const icons = useSceneStore((state) => {
|
||||
return state.icons;
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{nodes.map((node) => {
|
||||
return (
|
||||
<Node
|
||||
key={node.id}
|
||||
order={-node.position.x - node.position.y}
|
||||
node={node}
|
||||
icon={icons.find((icon) => {
|
||||
return icon.id === node.iconId;
|
||||
})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,54 +1,28 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { useInteractionManager } from 'src/interaction/useInteractionManager';
|
||||
import { Grid } from 'src/components/Grid/Grid';
|
||||
import { Cursor } from 'src/components/Cursor/Cursor';
|
||||
import { Node } from 'src/components/Node/Node';
|
||||
import { Group } from 'src/components/Group/Group';
|
||||
import { Connector } from 'src/components/Connector/Connector';
|
||||
import { Nodes } from 'src/components/Nodes/Nodes';
|
||||
import { Groups } from 'src/components/Groups/Groups';
|
||||
import { Connectors } from 'src/components/Connectors/Connectors';
|
||||
import { DebugUtils } from 'src/components/DebugUtils/DebugUtils';
|
||||
import { useResizeObserver } from 'src/hooks/useResizeObserver';
|
||||
import { SceneLayer } from 'src/components/SceneLayer/SceneLayer';
|
||||
import { DEFAULT_COLOR } from 'src/config';
|
||||
|
||||
export const Renderer = () => {
|
||||
const containerRef = useRef<HTMLDivElement>();
|
||||
const debugMode = useUiStateStore((state) => {
|
||||
return state.debugMode;
|
||||
});
|
||||
const nodes = useSceneStore((state) => {
|
||||
return state.nodes;
|
||||
});
|
||||
const scene = useSceneStore(({ connectors, groups }) => {
|
||||
return { connectors, groups };
|
||||
});
|
||||
const interactionsEnabled = useUiStateStore((state) => {
|
||||
return state.interactionsEnabled;
|
||||
});
|
||||
const icons = useSceneStore((state) => {
|
||||
return state.icons;
|
||||
});
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
const zoom = useUiStateStore((state) => {
|
||||
return state.zoom;
|
||||
});
|
||||
const mouse = useUiStateStore((state) => {
|
||||
return state.mouse;
|
||||
});
|
||||
const scroll = useUiStateStore((state) => {
|
||||
return state.scroll;
|
||||
});
|
||||
const { setRendererSize } = useUiStateStore((state) => {
|
||||
return state.actions;
|
||||
});
|
||||
const {
|
||||
setElement: setInteractionsElement,
|
||||
setIsEnabled: setInteractionsEnabled
|
||||
} = useInteractionManager();
|
||||
const { setElement: setInteractionsElement } = useInteractionManager();
|
||||
const { observe, disconnect, size: rendererSize } = useResizeObserver();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -62,10 +36,6 @@ export const Renderer = () => {
|
||||
};
|
||||
}, [setInteractionsElement, observe, disconnect]);
|
||||
|
||||
useEffect(() => {
|
||||
setInteractionsEnabled(interactionsEnabled);
|
||||
}, [interactionsEnabled, setInteractionsEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
setRendererSize(rendererSize);
|
||||
}, [rendererSize, setRendererSize]);
|
||||
@@ -77,47 +47,22 @@ export const Renderer = () => {
|
||||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Grid scroll={scroll} zoom={zoom} />
|
||||
<SceneLayer>
|
||||
{scene.groups.map((group) => {
|
||||
return <Group key={group.id} {...group} />;
|
||||
})}
|
||||
<Grid />
|
||||
</SceneLayer>
|
||||
{mode.showCursor && (
|
||||
<SceneLayer>
|
||||
<Cursor />
|
||||
</SceneLayer>
|
||||
)}
|
||||
<SceneLayer>
|
||||
<Groups />
|
||||
</SceneLayer>
|
||||
<SceneLayer>
|
||||
{mode.showCursor && <Cursor tile={mouse.position.tile} />}
|
||||
<Connectors />
|
||||
</SceneLayer>
|
||||
<SceneLayer>
|
||||
{mode.type === 'AREA_TOOL' && mode.area && (
|
||||
<Group
|
||||
from={mode.area.from}
|
||||
to={mode.area.to}
|
||||
color={DEFAULT_COLOR}
|
||||
/>
|
||||
)}
|
||||
</SceneLayer>
|
||||
<SceneLayer>
|
||||
{scene.connectors.map((connector) => {
|
||||
return <Connector key={connector.id} connector={connector} />;
|
||||
})}
|
||||
</SceneLayer>
|
||||
<SceneLayer>
|
||||
{nodes.map((node) => {
|
||||
return (
|
||||
<Node
|
||||
key={node.id}
|
||||
order={-node.position.x - node.position.y}
|
||||
node={node}
|
||||
icon={icons.find((icon) => {
|
||||
return icon.id === node.iconId;
|
||||
})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</SceneLayer>
|
||||
<SceneLayer>
|
||||
{mode.type === 'CONNECTOR' && mode.connector && (
|
||||
<Connector connector={mode.connector} />
|
||||
)}
|
||||
<Nodes />
|
||||
</SceneLayer>
|
||||
{debugMode && (
|
||||
<SceneLayer>
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Callbacks } from './Callbacks/Callbacks';
|
||||
import { DebugTools } from './DebugTools/DebugTools';
|
||||
|
||||
const examples = [
|
||||
{ name: 'Callbacks', component: Callbacks },
|
||||
{ name: 'Debug tools', component: DebugTools }
|
||||
{ name: 'Debug tools', component: DebugTools },
|
||||
{ name: 'Callbacks', component: Callbacks }
|
||||
];
|
||||
|
||||
export const Examples = () => {
|
||||
|
||||
@@ -15,9 +15,6 @@ export const useScroll = () => {
|
||||
const rendererSize = useUiStateStore((state) => {
|
||||
return state.rendererSize;
|
||||
});
|
||||
const zoom = useUiStateStore((state) => {
|
||||
return state.zoom;
|
||||
});
|
||||
|
||||
const scrollToTile = useCallback(
|
||||
(tile: Coords, origin?: TileOriginEnum) => {
|
||||
@@ -36,6 +33,7 @@ export const useScroll = () => {
|
||||
);
|
||||
|
||||
return {
|
||||
scroll,
|
||||
scrollToTile
|
||||
};
|
||||
};
|
||||
|
||||
@@ -23,9 +23,10 @@ const reducers: { [k in string]: InteractionReducer } = {
|
||||
|
||||
export const useInteractionManager = () => {
|
||||
const rendererRef = useRef<HTMLElement>();
|
||||
const reducerTypeRef = useRef<string>();
|
||||
const [isEnabled, setIsEnabled] = useState(true);
|
||||
const destroyListeners = useRef<() => void>();
|
||||
const interactionsEnabled = useUiStateStore((state) => {
|
||||
return state.interactionsEnabled;
|
||||
});
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
@@ -151,7 +152,7 @@ export const useInteractionManager = () => {
|
||||
|
||||
// TODO: Needs optimisation, listeners are added / removed every time the mouse position changes. Very intensive.
|
||||
useEffect(() => {
|
||||
if (!rendererRef.current || !isEnabled) {
|
||||
if (!rendererRef.current || !interactionsEnabled) {
|
||||
destroyListeners.current?.();
|
||||
return;
|
||||
}
|
||||
@@ -169,14 +170,13 @@ export const useInteractionManager = () => {
|
||||
};
|
||||
|
||||
return destroyListeners.current;
|
||||
}, [onMouseEvent, isEnabled]);
|
||||
}, [onMouseEvent, interactionsEnabled]);
|
||||
|
||||
const setElement = useCallback((element: HTMLElement) => {
|
||||
rendererRef.current = element;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
setElement,
|
||||
setIsEnabled
|
||||
setElement
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user