1- use std:: { collections:: HashSet , hash:: Hash } ;
1+ use std:: { collections:: HashSet , hash:: Hash , u32 } ;
22
33use egui:: {
44 Align , Button , Color32 , Image , Layout , Pos2 , Rect , Sense , Stroke , Ui , Vec2 , Widget as _, pos2,
@@ -9,27 +9,6 @@ use crate::{assets, config::CanvasConfig};
99
1010const EDGE_THRESHOLD : f32 = 15.0 ;
1111
12- // TODO Direction is not used anymore. I can calculate it from current positions?
13- #[ derive( serde:: Deserialize , serde:: Serialize , Debug , Clone , Copy , Default , Eq , PartialEq ) ]
14- pub enum Direction {
15- Up ,
16- #[ default]
17- Right ,
18- Down ,
19- Left ,
20- }
21-
22- impl Direction {
23- fn _rotate_cw ( self ) -> Self {
24- match self {
25- Self :: Up => Self :: Right ,
26- Self :: Right => Self :: Down ,
27- Self :: Down => Self :: Left ,
28- Self :: Left => Self :: Up ,
29- }
30- }
31- }
32-
3312/// All possible things that can appear on the screen.
3413#[ derive( serde:: Deserialize , serde:: Serialize , Copy , Debug , Clone ) ]
3514pub struct Instance {
@@ -367,7 +346,7 @@ impl Connection {
367346 }
368347
369348 /// Return pins in the order that starts with pin from instance id
370- fn get_pin ( & self , moving_instance_id : InstanceId ) -> Option < ( Pin , Pin ) > {
349+ fn get_ins_pin_first ( & self , moving_instance_id : InstanceId ) -> Option < ( Pin , Pin ) > {
371350 if self . pin1 . ins == moving_instance_id {
372351 Some ( ( self . pin1 , self . pin2 ) )
373352 } else if self . pin2 . ins == moving_instance_id {
@@ -376,6 +355,16 @@ impl Connection {
376355 None
377356 }
378357 }
358+
359+ fn get_pin_first ( & self , pin : Pin ) -> Option < ( Pin , Pin ) > {
360+ if self . pin1 == pin {
361+ Some ( ( self . pin1 , self . pin2 ) )
362+ } else if self . pin2 == pin {
363+ Some ( ( self . pin2 , self . pin1 ) )
364+ } else {
365+ None
366+ }
367+ }
379368}
380369
381370impl PartialEq for Connection {
@@ -407,6 +396,8 @@ pub struct TemplateApp {
407396 instances : Vec < Instance > ,
408397 /// Connected instance pairs
409398 connections : HashSet < Connection > ,
399+ /// What pins have current
400+ current : HashSet < Pin > ,
410401 /// Next unique ID for gates
411402 next_instance_id : InstanceId ,
412403
@@ -428,6 +419,7 @@ impl Default for TemplateApp {
428419 Self {
429420 instances : Default :: default ( ) ,
430421 connections : Default :: default ( ) ,
422+ current : Default :: default ( ) ,
431423 next_instance_id : InstanceId ( 0 ) ,
432424 panel_drag : None ,
433425 canvas_drag : None ,
@@ -458,8 +450,8 @@ impl TemplateApp {
458450 ui. add_sized (
459451 vec2 ( 200.0 , 50.0 ) ,
460452 egui:: TextEdit :: multiline ( & mut format ! (
461- "world {:#?}\n conn: {:#?}\n moving: {:#?}\n \n \n " ,
462- self . instances, self . connections, self . canvas_drag
453+ "world {:#?}\n conn: {:#?}\n current: {:#?} \n moving: {:#?}\n \n \n " ,
454+ self . instances, self . connections, self . current , self . canvas_drag
463455 ) ) ,
464456 )
465457 } ) ;
@@ -520,6 +512,7 @@ impl TemplateApp {
520512 {
521513 self . instances . clear ( ) ;
522514 self . connections . clear ( ) ;
515+ self . current . clear ( ) ;
523516 self . next_instance_id = InstanceId ( 0 ) ;
524517 self . canvas_drag = None ;
525518 self . panel_drag = None ;
@@ -533,6 +526,9 @@ impl TemplateApp {
533526 let ( resp, _painter) = ui. allocate_painter ( ui. available_size ( ) , Sense :: hover ( ) ) ;
534527 let canvas_rect = resp. rect ;
535528
529+ // Keep track if a new connection appeared
530+ let mut connected_changed = false ;
531+
536532 if let Some ( pd) = & mut self . panel_drag {
537533 if let Some ( mouse) = ui. ctx ( ) . pointer_interact_pos ( ) {
538534 match & mut pd. ty {
@@ -569,7 +565,7 @@ impl TemplateApp {
569565 match pd. ty {
570566 InstanceType :: Gate ( gate) => self . draw_gate ( ui, & gate) ,
571567 InstanceType :: Power ( power) => self . draw_power ( ui, & power) ,
572- InstanceType :: Wire ( wire) => Self :: draw_wire ( ui, & wire) ,
568+ InstanceType :: Wire ( wire) => self . draw_wire ( ui, InstanceId ( u32 :: MAX ) , & wire) ,
573569 }
574570 }
575571 }
@@ -600,6 +596,7 @@ impl TemplateApp {
600596 let id = instance. id ;
601597 if let InstanceType :: Power ( pi) = & mut self . get_instance_mut ( id) . ty {
602598 pi. on = !pi. on ;
599+ connected_changed = true ;
603600 }
604601 }
605602
@@ -717,7 +714,7 @@ impl TemplateApp {
717714 // TODO: inefficient but okay for now. We want to highlight connections for moving
718715 // object.
719716 for conn in & possible_connections {
720- if let Some ( ( _, other) ) = conn. get_pin ( moving_instance_id) {
717+ if let Some ( ( _, other) ) = conn. get_ins_pin_first ( moving_instance_id) {
721718 ui. painter ( ) . circle_filled (
722719 self . get_pin_pos ( other) ,
723720 EDGE_THRESHOLD ,
@@ -727,12 +724,12 @@ impl TemplateApp {
727724 }
728725 if mouse_up {
729726 for conn in & possible_connections {
730- let ( pin1, pin2) = if let Some ( ( pin1 , pin2 ) ) = conn . get_pin ( moving_instance_id )
731- {
732- ( pin1, pin2)
733- } else {
734- ( conn. pin1 , conn. pin2 )
735- } ;
727+ let ( pin1, pin2) =
728+ if let Some ( ( pin1 , pin2 ) ) = conn . get_ins_pin_first ( moving_instance_id ) {
729+ ( pin1, pin2)
730+ } else {
731+ ( conn. pin1 , conn. pin2 )
732+ } ;
736733 let instance = self . get_instance ( pin1. ins ) ;
737734 let pin_pos = self . get_pin_pos ( pin2) ;
738735 if let InstanceType :: Wire ( _) = instance. ty {
@@ -749,11 +746,18 @@ impl TemplateApp {
749746 }
750747 }
751748 for conn in & possible_connections {
749+ connected_changed = true ;
752750 self . connections . insert ( * conn) ;
753751 }
754752 // Remove any connections not present in possible_connections
755- self . connections
756- . retain ( |conn| possible_connections. contains ( conn) ) ;
753+ self . connections . retain ( |conn| {
754+ if possible_connections. contains ( conn) {
755+ true
756+ } else {
757+ connected_changed = false ;
758+ false
759+ }
760+ } ) ;
757761 }
758762 }
759763
@@ -789,6 +793,7 @@ impl TemplateApp {
789793 }
790794
791795 let d_pressed = ui. input ( |i| i. key_pressed ( egui:: Key :: D ) ) ;
796+ // TODO: Placing two items and then removing one by one causes panic
792797 if d_pressed {
793798 if let Some ( canvas_drag) = & self . canvas_drag {
794799 self . remove_instance ( canvas_drag. id ) ;
@@ -803,6 +808,58 @@ impl TemplateApp {
803808 }
804809 }
805810
811+ if connected_changed {
812+ let mut current = HashSet :: new ( ) ;
813+ let mut seen = HashSet :: new ( ) ;
814+ for instance in & self . instances {
815+ let InstanceType :: Power ( p) = instance. ty else {
816+ continue ;
817+ } ;
818+ if !p. on {
819+ continue ;
820+ }
821+ self . flow_current (
822+ Pin {
823+ ins : instance. id ,
824+ index : 0 , // We know power instance pin is 0
825+ } ,
826+ & mut current,
827+ & mut seen,
828+ ) ;
829+ }
830+ for instance in & self . instances {
831+ match instance. ty {
832+ InstanceType :: Gate ( _) => {
833+ let input1 = Pin {
834+ ins : instance. id ,
835+ index : 0 ,
836+ } ;
837+ let input2 = Pin {
838+ ins : instance. id ,
839+ index : 2 ,
840+ } ;
841+ let input1_p = current. contains ( & input1) ;
842+ let input2_p = current. contains ( & input2) ;
843+
844+ match ( input1_p, input2_p) {
845+ ( true , true ) => { }
846+ ( true , false ) | ( false , true ) | ( false , false ) => {
847+ let new_on = Pin {
848+ ins : instance. id ,
849+ index : 1 ,
850+ } ;
851+ current. insert ( new_on) ;
852+ self . flow_current ( new_on, & mut current, & mut seen) ;
853+ }
854+ }
855+ }
856+ InstanceType :: Wire ( _) => { }
857+ InstanceType :: Power ( _) => { }
858+ }
859+ }
860+ self . current = current;
861+ }
862+
806863 for instance in & self . instances {
807864 match instance. ty {
808865 InstanceType :: Gate ( gate) => {
@@ -812,7 +869,7 @@ impl TemplateApp {
812869 self . draw_power ( ui, & power) ;
813870 }
814871 InstanceType :: Wire ( wire) => {
815- Self :: draw_wire ( ui, & wire) ;
872+ self . draw_wire ( ui, instance . id , & wire) ;
816873 }
817874 }
818875 }
@@ -823,12 +880,15 @@ impl TemplateApp {
823880 }
824881 }
825882
826- fn draw_wire ( ui : & Ui , wire : & WireInstance ) {
883+ fn draw_wire ( & self , ui : & Ui , id : InstanceId , wire : & WireInstance ) {
884+ let color = if self . current . contains ( & Pin { ins : id, index : 0 } ) {
885+ Color32 :: BLUE
886+ } else {
887+ Color32 :: LIGHT_BLUE
888+ } ;
827889 let thickness = 6.0 ;
828- ui. painter ( ) . line_segment (
829- [ wire. start , wire. end ] ,
830- Stroke :: new ( thickness, Color32 :: LIGHT_RED ) ,
831- ) ;
890+ ui. painter ( )
891+ . line_segment ( [ wire. start , wire. end ] , Stroke :: new ( thickness, color) ) ;
832892 }
833893
834894 fn draw_gate ( & self , ui : & mut Ui , gate : & GateInstance ) {
@@ -924,6 +984,35 @@ impl TemplateApp {
924984 {
925985 self . resize = None ;
926986 }
987+ // TODO: Remove from current table
988+ }
989+
990+ fn flow_current ( & self , pin : Pin , current : & mut HashSet < Pin > , seen : & mut HashSet < Pin > ) {
991+ if seen. contains ( & pin) {
992+ return ;
993+ }
994+ seen. insert ( pin) ;
995+ // TODO: Can do better search
996+ for connection in & self . connections {
997+ let Some ( ( self_pin, other_pin) ) = connection. get_pin_first ( pin) else {
998+ continue ;
999+ } ;
1000+ current. insert ( self_pin) ;
1001+ current. insert ( other_pin) ;
1002+ // Also add current for other pins in the other_pin instance
1003+ let instance = self . get_instance ( other_pin. ins ) ;
1004+ match instance. ty {
1005+ InstanceType :: Gate ( _) => { }
1006+ InstanceType :: Wire ( _) => {
1007+ for pin in instance. pins ( ) {
1008+ current. insert ( pin) ;
1009+ self . flow_current ( pin, current, seen) ;
1010+ }
1011+ }
1012+ InstanceType :: Power ( _) => { }
1013+ }
1014+ self . flow_current ( other_pin, current, seen) ;
1015+ }
9271016 }
9281017}
9291018
0 commit comments