Skip to content

Commit 94b2a81

Browse files
committed
Can we simulate?
1 parent 5f08492 commit 94b2a81

File tree

2 files changed

+132
-41
lines changed

2 files changed

+132
-41
lines changed

mise.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[tools]
2+
rust = { version = "1.89", components = "rust-src,llvm-tools,rustfmt,rust-analyzer", targets = "wasm32-unknown-unknown" }

src/app.rs

Lines changed: 130 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashSet, hash::Hash};
1+
use std::{collections::HashSet, hash::Hash, u32};
22

33
use 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

1010
const 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)]
3514
pub 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

381370
impl 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

Comments
 (0)