@@ -37,7 +37,12 @@ import { Button } from "@/ui/components/StyledComponents"
3737import FlowControls from "@/ui/components/simulation/FlowControls"
3838import FlowInfo from "@/ui/components/simulation/FlowInfo"
3939import { useUIContext } from "../../helpers/UIProviderHelpers"
40- import { WiringNode } from "./WiringNode"
40+ import WiringNode from "./WiringNode"
41+
42+ /**
43+ * WARNING: Please test *thoroughly* when making changes. React Flow is very tempermental with how nodes
44+ * and object references are maintained.
45+ */
4146
4247type ConfigComponentProps = {
4348 setConfigState : ( state : ConfigState ) => void
@@ -56,7 +61,7 @@ type NodeType = ComponentType<
5661const nodeTypes : Record < string , NodeType > = [ WiringNode ] . reduce < {
5762 [ k : string ] : NodeType
5863} > ( ( prev , next ) => {
59- prev [ next . name ] = next as NodeType
64+ prev [ next . name ] = next
6065 return prev
6166} , { } )
6267
@@ -68,7 +73,7 @@ function generateGraph(
6873 const nodes : Map < string , FlowNode > = new Map ( )
6974 const edges : FlowEdge [ ] = [ ]
7075
71- for ( const [ _k , v ] of Object . entries ( simConfig . nodes ) ) {
76+ Object . entries ( simConfig . nodes ) . forEach ( ( [ _k , v ] ) => {
7277 let onEdit : ( ( ) => void ) | undefined
7378 let onRefresh : ( ( ) => void ) | undefined
7479 let onDelete : ( ( ) => void ) | undefined
@@ -99,32 +104,34 @@ function generateGraph(
99104 }
100105
101106 nodes . set ( v . id , {
102- ...v ,
107+ id : v . id ,
108+ type : v . type ,
109+ position : v . position ,
103110 data : {
104- title,
105- onEdit,
106- onRefresh,
107- onDelete,
108- simConfig,
111+ title : title ,
112+ onEdit : onEdit ,
113+ onRefresh : onRefresh ,
114+ onDelete : onDelete ,
115+ simConfig : simConfig ,
109116 input : [ ] ,
110117 output : [ ] ,
111118 tooltip : v . tooltip ,
112119 } ,
113120 } )
114- }
121+ } )
115122
116- for ( const [ _k , v ] of Object . entries ( simConfig . handles ) ) {
117- if ( ! v . enabled ) break
123+ Object . entries ( simConfig . handles ) . forEach ( ( [ _k , v ] ) => {
124+ if ( ! v . enabled ) return
118125 const node = nodes . get ( v . nodeId )
119126 if ( ! node ) {
120127 console . warn ( "Orphaned handle found" )
121- break
128+ return
122129 }
123130 const list = ( v . isSource ? node . data . output : node . data . input ) as unknown [ ]
124- list . push ( v )
125- }
131+ list . push ( { ... v } )
132+ } )
126133
127- for ( const [ k , v ] of Object . entries ( simConfig . edges ) ) {
134+ Object . entries ( simConfig . edges ) . forEach ( ( [ k , v ] ) => {
128135 const sourceHandle = simConfig . handles [ v . sourceId ]
129136 const targetHandle = simConfig . handles [ v . targetId ]
130137
@@ -137,22 +144,28 @@ function generateGraph(
137144 targetHandle : targetHandle . id ,
138145 } )
139146 }
140- }
147+ } )
141148
142149 return [ [ ...nodes . values ( ) ] , edges ]
143150}
144151
145152const SimIoComponent : React . FC < ConfigComponentProps > = ( { setConfigState, simConfig } ) => {
146153 const theme = useTheme ( )
147154
148- const simOut : HandleInfo [ ] = [ ]
149- const simIn : HandleInfo [ ] = [ ]
150- for ( const [ _k , v ] of Object . entries ( simConfig . handles ) ) {
151- if ( v . nodeId === NODE_ID_SIM_OUT || v . nodeId === NODE_ID_SIM_IN ) {
152- const list = v . isSource ? simOut : simIn
153- list . push ( v )
155+ const [ simOut , setSimOut ] = useState < Record < string , HandleInfo > > ( { } )
156+ const [ simIn , setSimIn ] = useState < Record < string , HandleInfo > > ( { } )
157+
158+ useEffect ( ( ) => {
159+ const simOut : Record < string , HandleInfo > = { }
160+ const simIn : Record < string , HandleInfo > = { }
161+ for ( const [ _k , v ] of Object . entries ( simConfig . handles ) ) {
162+ if ( v . nodeId === NODE_ID_SIM_OUT || v . nodeId === NODE_ID_SIM_IN ) {
163+ v . isSource ? ( simOut [ v . id ] = v ) : ( simIn [ v . id ] = v )
164+ }
154165 }
155- }
166+ setSimOut ( simOut )
167+ setSimIn ( simIn )
168+ } , [ simConfig ] )
156169
157170 return (
158171 < Stack gap = { 4 } direction = { "column" } sx = { { width : "stretch" } } >
@@ -167,13 +180,14 @@ const SimIoComponent: React.FC<ConfigComponentProps> = ({ setConfigState, simCon
167180 < Stack >
168181 < Label size = "md" > Output</ Label >
169182 < ScrollView >
170- { simOut . sort ( handleInfoDisplayCompare ) . map ( handle => (
183+ { Object . values ( simOut ) . sort ( handleInfoDisplayCompare ) . map ( handle => (
171184 < Checkbox
172185 label = { `${ handle . displayName } ` }
173186 key = { handle . id }
174187 checked = { handle . enabled }
175188 onClick = { checked => {
176189 handle . enabled = checked
190+ setSimOut ( { ...simOut , [ handle . id ] : handle } )
177191 } }
178192 />
179193 ) ) }
@@ -183,13 +197,14 @@ const SimIoComponent: React.FC<ConfigComponentProps> = ({ setConfigState, simCon
183197 < Stack >
184198 < Label size = "md" > Input</ Label >
185199 < ScrollView >
186- { simIn . sort ( handleInfoDisplayCompare ) . map ( handle => (
200+ { Object . values ( simIn ) . sort ( handleInfoDisplayCompare ) . map ( handle => (
187201 < Checkbox
188202 label = { `${ handle . displayName } ` }
189203 key = { handle . id }
190204 checked = { handle . enabled }
191205 onClick = { checked => {
192206 handle . enabled = checked
207+ setSimIn ( { ...simIn , [ handle . id ] : handle } )
193208 } }
194209 />
195210 ) ) }
@@ -206,22 +221,27 @@ const SimIoComponent: React.FC<ConfigComponentProps> = ({ setConfigState, simCon
206221const RobotIoComponent : React . FC < ConfigComponentProps > = ( { setConfigState, simConfig } ) => {
207222 const theme = useTheme ( )
208223
224+ const [ refreshHook , refreshCheckboxes ] = useReducer ( x => ! x , false )
225+
209226 const [ canEncoders , canMotors , pwmDevices , accelerometers ] = useMemo ( ( ) => {
210227 const canEncoders : JSX . Element [ ] = [ ]
211228 const canMotors : JSX . Element [ ] = [ ]
212229 const pwmDevices : JSX . Element [ ] = [ ]
213230 const accelerometers : JSX . Element [ ] = [ ]
214231
215- for ( const [ _k , v ] of Object . entries ( simConfig . handles ) ) {
232+ Object . entries ( simConfig . handles ) . forEach ( ( [ _k , v ] ) => {
216233 if ( v . nodeId !== NODE_ID_ROBOT_IO ) return [ ]
217234
235+ console . debug ( v )
236+
218237 const checkbox = (
219238 < Checkbox
220239 label = { v . displayName }
221240 key = { v . id }
222241 checked = { v . enabled }
223242 onClick = { enabled => {
224243 v . enabled = enabled
244+ refreshCheckboxes ( )
225245 } }
226246 />
227247 )
@@ -234,16 +254,16 @@ const RobotIoComponent: React.FC<ConfigComponentProps> = ({ setConfigState, simC
234254 pwmDevices . push ( checkbox )
235255 break
236256 case SimType . CAN_ENCODER :
237- pwmDevices . push ( checkbox )
257+ canEncoders . push ( checkbox )
238258 break
239259 case SimType . ACCELEROMETER :
240- pwmDevices . push ( checkbox )
260+ accelerometers . push ( checkbox )
241261 break
242262 }
243- }
263+ } )
244264
245265 return [ canEncoders , canMotors , pwmDevices , accelerometers ]
246- } , [ simConfig ] )
266+ } , [ simConfig , refreshHook ] )
247267
248268 return (
249269 < Stack gap = { 4 } >
@@ -360,7 +380,7 @@ const WiringComponent: React.FC<ConfigComponentProps> = ({ setConfigState, simCo
360380 const onCreateJunction = useCallback ( ( ) => {
361381 SimConfig . AddJunctionNode ( simConfig )
362382 refreshGraph ( )
363- } , [ simConfig ] )
383+ } , [ refreshGraph , simConfig ] )
364384
365385 return (
366386 < ReactFlow
@@ -402,8 +422,10 @@ const WiringPanel: React.FC<PanelImplProps<void, void>> = ({ panel }) => {
402422
403423 const existingConfig = selectedAssembly . simConfigData
404424 if ( existingConfig ) {
425+ console . debug ( 'Existing SimConfig found' )
405426 setSimConfig ( JSON . parse ( JSON . stringify ( existingConfig ) ) ) // Create copy to not force a save
406427 } else {
428+ console . debug ( 'No SimConfig found, creating default...' )
407429 setSimConfig ( SimConfig . Default ( selectedAssembly ) )
408430 }
409431 } , [ selectedAssembly ] )
@@ -418,6 +440,8 @@ const WiringPanel: React.FC<PanelImplProps<void, void>> = ({ panel }) => {
418440 console . debug ( `${ flows . length } Flows Successfully Compiled!` )
419441
420442 selectedAssembly . updateSimConfig ( simConfig )
443+ } else {
444+ console . warn ( 'Failed to save SimConfig' , simConfig , selectedAssembly )
421445 }
422446 } , [ selectedAssembly , simConfig ] )
423447
@@ -429,7 +453,7 @@ const WiringPanel: React.FC<PanelImplProps<void, void>> = ({ panel }) => {
429453
430454 useEffect ( ( ) => {
431455 configureScreen ( panel ! , { title : "Wiring Panel" } , { onBeforeAccept : save } )
432- } , [ ] )
456+ } , [ save ] )
433457
434458 return (
435459 < >
@@ -473,4 +497,4 @@ const WiringPanel: React.FC<PanelImplProps<void, void>> = ({ panel }) => {
473497 )
474498}
475499
476- export { WiringPanel }
500+ export default WiringPanel
0 commit comments