@@ -421,6 +421,132 @@ impl DB {
421421 }
422422 out
423423 }
424+
425+ pub fn connected_insntances ( & self , id : InstanceId ) -> Vec < InstanceId > {
426+ let mut out = vec ! [ id] ;
427+ for c in & self . connections {
428+ if c. a . ins == id {
429+ out. push ( c. b . ins ) ;
430+ } else if c. b . ins == id {
431+ out. push ( c. a . ins ) ;
432+ }
433+ }
434+ out
435+ }
436+
437+ pub fn move_nonwires_and_resize_wires ( & mut self , ids : & [ InstanceId ] , delta : Vec2 ) {
438+ // Move all non-wire instances, then adjust connected wire endpoints
439+ for id in ids {
440+ match self . ty ( * id) {
441+ InstanceKind :: Gate ( _) => {
442+ let g = self . get_gate_mut ( * id) ;
443+ g. pos += delta;
444+ }
445+ InstanceKind :: Power => {
446+ let p = self . get_power_mut ( * id) ;
447+ p. pos += delta;
448+ }
449+ InstanceKind :: Wire => { }
450+ InstanceKind :: CustomCircuit ( _) => {
451+ let cc = self . get_custom_circuit_mut ( * id) ;
452+ cc. pos += delta;
453+ }
454+ }
455+ }
456+
457+ // Resize wire endpoints attached to any moved instance
458+ for id in ids {
459+ for pin in self . connected_pins_of_instance ( * id) {
460+ if matches ! ( self . ty( pin. ins) , InstanceKind :: Wire ) {
461+ let w = self . get_wire_mut ( pin. ins ) ;
462+ if pin. index == 0 {
463+ w. start += delta;
464+ } else {
465+ w. end += delta;
466+ }
467+ }
468+ }
469+ }
470+ }
471+
472+ pub fn move_instance_and_propagate ( & mut self , id : InstanceId , delta : Vec2 ) {
473+ let mut visited = HashSet :: new ( ) ;
474+ self . move_instance_and_propagate_recursive ( id, delta, & mut visited) ;
475+ }
476+
477+ fn move_instance_and_propagate_recursive (
478+ & mut self ,
479+ id : InstanceId ,
480+ delta : Vec2 ,
481+ visited : & mut HashSet < InstanceId > ,
482+ ) {
483+ if !visited. insert ( id) {
484+ return ;
485+ }
486+
487+ // Move this instance
488+ match self . ty ( id) {
489+ InstanceKind :: Gate ( _) => {
490+ let g = self . get_gate_mut ( id) ;
491+ g. pos += delta;
492+ }
493+ InstanceKind :: Power => {
494+ let p = self . get_power_mut ( id) ;
495+ p. pos += delta;
496+ }
497+ InstanceKind :: Wire => {
498+ let w = self . get_wire_mut ( id) ;
499+ w. start += delta;
500+ w. end += delta;
501+ }
502+ InstanceKind :: CustomCircuit ( _) => {
503+ let cc = self . get_custom_circuit_mut ( id) ;
504+ cc. pos += delta;
505+ }
506+ }
507+
508+ // Get connected instances before we recurse
509+ let connected = self . connected_insntances ( id) ;
510+
511+ // Process each connected instance
512+ for connected_id in connected {
513+ if connected_id == id || visited. contains ( & connected_id) {
514+ continue ;
515+ }
516+
517+ match self . ty ( connected_id) {
518+ InstanceKind :: Wire => {
519+ // For wires, resize them to stay connected
520+ // Find which pin of the wire is connected to our moved instance
521+ let wire_pins = self . pins_of ( connected_id) ;
522+ for wire_pin in wire_pins {
523+ // Check if this wire pin is connected to any pin of our moved instance
524+ for moved_pin in self . pins_of ( id) {
525+ if self
526+ . connections
527+ . contains ( & Connection :: new ( wire_pin, moved_pin) )
528+ {
529+ // Update the wire endpoint to match the new pin position
530+ let new_pin_pos = self . pin_position ( moved_pin) ;
531+ let w = self . get_wire_mut ( connected_id) ;
532+ if wire_pin. index == 0 {
533+ w. start = new_pin_pos;
534+ } else {
535+ w. end = new_pin_pos;
536+ }
537+ }
538+ }
539+ }
540+ // Mark as visited but don't propagate further (wires are endpoints)
541+ visited. insert ( connected_id) ;
542+ }
543+ InstanceKind :: Gate ( _) | InstanceKind :: Power | InstanceKind :: CustomCircuit ( _) => {
544+ // For non-wires, propagate the same delta
545+ self . move_instance_and_propagate_recursive ( connected_id, delta, visited) ;
546+ }
547+ }
548+ }
549+ }
424550}
425551
426552#[ derive( serde:: Deserialize , serde:: Serialize ) ]
@@ -909,7 +1035,8 @@ impl App {
9091035 && let Some ( hovered) = self . hovered
9101036 && let Some ( mouse) = mouse_pos_world
9111037 && self . drag . is_none ( )
912- && let Some ( split_point) = self . wire_branching_action_point ( mouse, hovered)
1038+ && let Hover :: Instance ( instance_id) = hovered
1039+ && let Some ( split_point) = self . wire_branching_action_point ( mouse, instance_id)
9131040 {
9141041 ui. painter ( ) . circle_filled (
9151042 split_point - self . viewport_offset ,
@@ -1907,10 +2034,11 @@ impl App {
19072034 self . current_dirty = true ;
19082035 }
19092036
1910- pub fn wire_branching_action_point ( & self , mouse : Pos2 , hovered : Hover ) -> Option < Pos2 > {
1911- let Hover :: Instance ( instance_id) = hovered else {
1912- return None ;
1913- } ;
2037+ pub fn wire_branching_action_point (
2038+ & self ,
2039+ mouse : Pos2 ,
2040+ instance_id : InstanceId ,
2041+ ) -> Option < Pos2 > {
19142042 if !self . selected . contains ( & instance_id) || self . selected . len ( ) != 1 {
19152043 return None ;
19162044 }
0 commit comments