Skip to content

Commit

Permalink
Merge pull request #2382 from stakwork/feature/layour3.0
Browse files Browse the repository at this point in the history
Feature/layour3.0
  • Loading branch information
Rassl authored Oct 24, 2024
2 parents 23f6df5 + 9412b96 commit 8192282
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 98 deletions.
2 changes: 1 addition & 1 deletion src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ export const App = () => {

<DeviceCompatibilityNotice />

<Leva hidden={!isDevelopment} />
<Leva hidden={!isDevelopment || true} isRoot />

<Suspense fallback={<div>Loading...</div>}>
{!splashDataLoading ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import styled from 'styled-components'
import { BoxGeometry, Mesh, Vector3 } from 'three'
import { SchemaExtended } from '~/components/ModalsContainer/BlueprintModal/types'
import { fontProps } from '~/components/Universe/Graph/Cubes/Text/constants'
import { useSchemaStore } from '~/stores/useSchemaStore'
import { truncateText } from '~/utils/truncateText'
import { NODE_RADIUS } from '../../constants'
import { useSchemaStore } from '~/stores/useSchemaStore'

export const NODE_TYPE_COLORS = ['#ff13c9', '#5af0ff', '#3233ff', '#c2f0c2', '#ff6666', '#99ccff', '#ffb3b3']

Expand Down
15 changes: 4 additions & 11 deletions src/components/Universe/Graph/Connections/LineComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Line } from '@react-three/drei'
import gsap from 'gsap'
import { forwardRef, useEffect } from 'react'
import { Vector3 } from 'three'
import { Color, Vector3 } from 'three'
import { Line2 } from 'three-stdlib'

type LineComponentProps = {
Expand Down Expand Up @@ -29,17 +29,10 @@ const LineComponent = forwardRef<Line2, LineComponentProps>(
}
}, [isSelected, lineWidth, ref])

const color = new Color(0xff0000)

return (
<Line
ref={ref}
color="rgba(136, 136, 136, 1)"
isLine2
lineWidth={1}
opacity={1}
points={[source, target]}
transparent
visible={visible}
/>
<Line ref={ref} color={color} isLine2 lineWidth={2} opacity={0.5} points={[source, target]} visible={visible} />
)
},
)
Expand Down
13 changes: 13 additions & 0 deletions src/components/Universe/Graph/Cubes/NodePoints/Point/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Billboard, Instance } from '@react-three/drei'

type Props = {
color: string
}

export const Point = ({ color }: Props) => (
<>
<Billboard follow lockX={false} lockY={false} lockZ={false}>
<Instance color={color} />
</Billboard>
</>
)
70 changes: 70 additions & 0 deletions src/components/Universe/Graph/Cubes/NodePoints/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Instances } from '@react-three/drei'
import { memo, useMemo } from 'react'
import { BufferGeometry, TorusGeometry } from 'three'
import { useDataStore, useNodeTypes } from '~/stores/useDataStore'
import { useSelectedNode } from '~/stores/useGraphStore'
import { useSchemaStore } from '~/stores/useSchemaStore'
import { NodeExtended } from '~/types'
import { colors } from '~/utils'
import { Point } from './Point'

const COLORS_MAP = [
'#fff',
'#9747FF',
'#00887A',
'#0098A6',
'#0288D1',
'#33691E',
'#465A65',
'#512DA7',
'#5C6BC0',
'#5D4038',
'#662C00',
'#689F39',
'#6B1B00',
'#750000',
'#78909C',
'#7E57C2',
'#8C6E63',
'#AA47BC',
'#BF360C',
'#C2175B',
'#EC407A',
'#EF6C00',
'#F5511E',
'#FF9696',
'#FFC064',
'#FFCD29',
'#FFEA60',
]

// eslint-disable-next-line no-underscore-dangle
const _NodePoints = () => {
const selectedNode = useSelectedNode()
const data = useDataStore((s) => s.dataInitial)
const { normalizedSchemasByType } = useSchemaStore((s) => s)
const nodeTypes = useNodeTypes()
const ringGeometry = useMemo(() => new TorusGeometry(30, 4, 16, 100), [])

return (
<>
<Instances
geometry={ringGeometry as BufferGeometry}
limit={1000} // Optional: max amount of items (for calculating buffer size)
range={1000}
visible={!selectedNode}
// Optional: draw-range
>
<meshStandardMaterial />
{data?.nodes.map((node: NodeExtended) => {
const primaryColor = normalizedSchemasByType[node.node_type]?.primary_color
const color = primaryColor ?? (COLORS_MAP[nodeTypes.indexOf(node.node_type)] || colors.white)

return <Point key={node.ref_id} color={color} />
})}
</Instances>
</>
)
}

export const NodePoints = memo(_NodePoints)
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const SelectionDataNodes = memo(() => {
{selectionGraphData?.nodes.map((node) => (
<mesh key={node.ref_id}>
{node.name ? (
<TextNode key={node.ref_id || node.id} hide node={node} />
<TextNode key={node.ref_id || node.id} hide isHovered={false} node={node} />
) : (
<Cube key={node.ref_id || node.id} hide node={node} />
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Universe/Graph/Cubes/Text/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const fontProps = {
font: '/fonts/Inter-Bold.woff',
characters: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!',
fontSize: 2,
fontSize: 1,
letterSpacing: -0.05,
lineHeight: 1,
'material-toneMapped': false,
Expand Down
98 changes: 50 additions & 48 deletions src/components/Universe/Graph/Cubes/Text/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Svg, Text } from '@react-three/drei'
import { Billboard, Svg, Text } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import { Select } from '@react-three/postprocessing'
import { memo, useMemo, useRef } from 'react'
import { Mesh } from 'three'
import { Mesh, MeshStandardMaterial, Vector3 } from 'three'
import { Icons } from '~/components/Icons'
import { useNodeTypes } from '~/stores/useDataStore'
import { useGraphStore, useHoveredNode, useSelectedNode, useSelectedNodeRelativeIds } from '~/stores/useGraphStore'
import { useGraphStore, useSelectedNode, useSelectedNodeRelativeIds } from '~/stores/useGraphStore'
import { useSchemaStore } from '~/stores/useSchemaStore'
import { NodeExtended } from '~/types'
import { colors } from '~/utils/colors'
import { removeEmojis } from '~/utils/removeEmojisFromText'
import { truncateText } from '~/utils/truncateText'
import { smoothness } from '../Cube/constants'
import { fontProps } from './constants'

const COLORS_MAP = [
Expand Down Expand Up @@ -47,59 +45,57 @@ const COLORS_MAP = [
type Props = {
node: NodeExtended
hide?: boolean
isHovered: boolean
}

function splitStringIntoThreeParts(text: string): string {
// Split the string into an array of words

const truncatedText = truncateText(text, 30)
const words = truncatedText.split(' ')

// If the word count is 5 or less, return the original text
if (text.split(' ').length <= 5) {
if (words.length <= 5) {
return truncatedText
}

// Determine the split points
const third = Math.ceil(words.length / 3)
const twoThirds = third * 2

// Split the array into three parts
const firstPart = words.slice(0, third).join(' ')
const secondPart = words.slice(third, twoThirds).join(' ')
const thirdPart = words.slice(twoThirds).join(' ')

// Return the three parts as a single string with newline characters in between
return `${firstPart}\n${secondPart}\n${thirdPart}`
}

export const TextNode = memo(({ node, hide }: Props) => {
export const TextNode = memo(({ node, hide, isHovered }: Props) => {
const ref = useRef<Mesh | null>(null)
const svgRef = useRef<Mesh | null>(null)
const ringRef = useRef<Mesh | null>(null)
const selectedNode = useSelectedNode()
const hoveredNode = useHoveredNode()

const nodePositionRef = useRef(new Vector3())

const selectedNodeRelativeIds = useSelectedNodeRelativeIds()
const isRelative = selectedNodeRelativeIds.includes(node?.ref_id || '')
const isSelected = !!selectedNode && selectedNode?.ref_id === node.ref_id
const isHovered = !!hoveredNode && hoveredNode?.ref_id === node.ref_id
const showSelectionGraph = useGraphStore((s) => s.showSelectionGraph)
const { normalizedSchemasByType } = useSchemaStore((s) => s)

const nodeTypes = useNodeTypes()

useFrame(({ camera }) => {
if (ref?.current) {
// Make text face the camera
ref.current.quaternion.copy(camera.quaternion)
}
const checkDistance = () => {
const nodePosition = nodePositionRef.current.setFromMatrixPosition(ref.current!.matrixWorld)

if (ringRef.current) {
ringRef.current.visible = nodePosition.distanceTo(camera.position) < 2500
}

if (svgRef?.current) {
// Make text face the camera
svgRef.current.quaternion.copy(camera.quaternion)
// Set visibility based on distance
}

checkDistance()
})

const nodeTypes = useNodeTypes()

const textScale = useMemo(() => {
let scale = (node.edge_count || 1) * 20

Expand All @@ -111,60 +107,66 @@ export const TextNode = memo(({ node, hide }: Props) => {

const nodeScale = scale / Math.sqrt(node.name.length)

scale = Math.max(nodeScale, 20)

return Math.min(scale, 30)
return Math.min(Math.max(nodeScale, 20), 30)
}, [node.edge_count, node.name, isSelected, isRelative, showSelectionGraph])

const fillOpacity = useMemo(() => {
if (selectedNode && !isSelected) {
return 0.2
}

if (hoveredNode && !isHovered) {
if (!isHovered) {
return 0.2
}

return 1
}, [isSelected, selectedNode, isHovered, hoveredNode])
}, [isSelected, selectedNode, isHovered])

const primaryColor = normalizedSchemasByType[node.node_type]?.primary_color
const primaryIcon = normalizedSchemasByType[node.node_type]?.icon

const color = primaryColor ?? (COLORS_MAP[nodeTypes.indexOf(node.node_type)] || colors.white)

const Icon = primaryIcon ? Icons[primaryIcon] : null

const iconName = Icon ? primaryIcon : 'AddCircleIcon'

const iconName = Icon ? primaryIcon : 'NodesIcon'
const sanitizedNodeName = removeEmojis(String(node.name))

return (
<>
{!Icon ? (
<Billboard follow lockX={false} lockY={false} lockZ={false} name="billboard" userData={node}>
<mesh ref={ringRef} name={node.id} userData={node} visible={!hide}>
<Svg
ref={svgRef}
name="svg"
onUpdate={(svg) => {
svg.traverse((child) => {
if (child instanceof Mesh) {
// Apply dynamic color to meshes
// eslint-disable-next-line no-param-reassign
child.material = new MeshStandardMaterial({ color })
}
})
}}
position={[-15, 15, 0]}
scale={2}
src={`svg-icons/${iconName}.svg`}
strokeMaterial={{ color: 'yellow' }}
userData={node}
/>

<Text
ref={ref}
anchorX="center"
anchorY="middle"
color={color}
fillOpacity={fillOpacity}
fillOpacity={1 || fillOpacity}
name="text"
position={[0, -40, 0]}
scale={textScale}
userData={node}
visible={!hide}
{...fontProps}
>
{splitStringIntoThreeParts(sanitizedNodeName)}
</Text>
) : (
<Select enabled={!!isSelected}>
<mesh name={node.id} userData={node} visible={!hide}>
<sphereGeometry args={[30, 32, 32]} userData={node} />
<meshStandardMaterial {...smoothness} color={color} />
<Svg ref={svgRef} position={[20, 20, 20]} scale={2} src={`svg-icons/${iconName}.svg`} />
</mesh>
</Select>
)}
</>
</mesh>
</Billboard>
)
})

Expand Down
Loading

0 comments on commit 8192282

Please sign in to comment.