import { Text, Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Flex, StackDivider, Switch, VStack, } from '@chakra-ui/react' import React, { useCallback } from 'react' import { initialPhysics } from '../config' import { EnableSection } from './EnableSection' import { SliderWithInfo } from './SliderWithInfo' export interface PhysicsPanelProps { physics: typeof initialPhysics setPhysics: any } export const PhysicsPanel = (props: PhysicsPanelProps) => { const { physics, setPhysics } = props const setPhysicsCallback = useCallback((val: number, phys: string, scale: number) => { setPhysics((curr: typeof initialPhysics) => { return { ...curr, [phys]: val / scale } }) }, []) return ( <Box> <VStack spacing={2} justifyContent="flex-start" divider={<StackDivider borderColor="gray.500" />} align="stretch" paddingLeft={7} color="gray.800" > <EnableSection label="Gravity" value={physics.gravityOn} onChange={() => setPhysics({ ...physics, gravityOn: !physics.gravityOn })} > <Flex justifyContent="space-between"> <Text>Also in local</Text> <Switch onChange={() => { setPhysics((curr: typeof initialPhysics) => { return { ...curr, gravityLocal: !curr.gravityLocal } }) }} isChecked={physics.gravityLocal} ></Switch> </Flex> <SliderWithInfo label="Strength" value={physics.gravity * 10} onChange={(v: number) => setPhysicsCallback(v, 'gravity', 10)} /> </EnableSection> <SliderWithInfo value={-physics.charge / 100} onChange={(v) => setPhysicsCallback(v, 'charge', -1 / 100)} label="Repulsive Force" /> <EnableSection label="Collision" infoText="Perfomance sap, disable if slow" value={physics.collision} onChange={() => setPhysics({ ...physics, collision: !physics.collision })} > <SliderWithInfo value={physics.collisionStrength / 5} onChange={(v) => setPhysicsCallback(v, 'collisionStrength', 1 / 5)} label="Collision Radius" infoText="Easy with this one, high values can lead to a real jiggly mess" /> </EnableSection> <SliderWithInfo value={physics.linkStrength * 5} onChange={(v) => setPhysicsCallback(v, 'linkStrength', 5)} label="Link Force" /> <SliderWithInfo label="Link Iterations" value={physics.linkIts} onChange={(v) => setPhysicsCallback(v, 'linkIts', 1)} min={0} max={6} step={1} infoText="How many links down the line the physics of a single node affects (Slow)" /> <SliderWithInfo label="Viscosity" value={physics.velocityDecay * 10} onChange={(v) => setPhysicsCallback(v, 'velocityDecay', 10)} /> </VStack> <Box> <Accordion paddingLeft={3} allowToggle> <AccordionItem> <AccordionButton> <Text>Advanced</Text> <AccordionIcon marginRight={2} /> </AccordionButton> <AccordionPanel> <VStack spacing={2} justifyContent="flex-start" divider={<StackDivider borderColor="gray.500" />} align="stretch" paddingLeft={3} color="gray.800" > <SliderWithInfo label="Stabilization rate" value={physics.alphaDecay * 50} onChange={(v) => setPhysicsCallback(v, 'alphaDecay', 50)} /> <EnableSection label="Center nodes" value={physics.centering} onChange={() => setPhysics({ ...physics, centering: !physics.centering })} infoText="Keeps the nodes in the center of the viewport. If disabled you can drag the nodes anywhere you want." > <SliderWithInfo label="Centering Strength" value={physics.centeringStrength} max={2} step={0.01} onChange={(v) => setPhysicsCallback(v, 'centeringStrength', 1)} /> </EnableSection> </VStack> </AccordionPanel> </AccordionItem> </Accordion> </Box> </Box> ) }