Skip to content

Commit 9215637

Browse files
committed
Better module pins
1 parent c39c956 commit 9215637

File tree

6 files changed

+456
-1307
lines changed

6 files changed

+456
-1307
lines changed

src/app.rs

Lines changed: 48 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::{
1818
config::CanvasConfig,
1919
connection_manager::{Connection, ConnectionManager},
2020
drag::Drag,
21-
module::Module,
2221
};
2322

2423
pub const PANEL_BUTTON_MAX_HEIGHT: f32 = 50.0;
@@ -538,10 +537,7 @@ impl App {
538537
InstanceKind::Wire => self.db.circuit.new_wire(Wire::new_at(pos)),
539538
InstanceKind::Lamp => self.db.circuit.new_lamp(Lamp { pos }),
540539
InstanceKind::Clock => self.db.circuit.new_clock(Clock { pos }),
541-
InstanceKind::Module(c) => self.db.new_module_with_flattening(Module {
542-
pos,
543-
definition_index: c,
544-
}),
540+
InstanceKind::Module(c) => self.db.new_module(c, pos),
545541
};
546542
self.set_drag(Drag::Canvas(crate::drag::CanvasDrag::Single {
547543
id,
@@ -556,7 +552,7 @@ impl App {
556552
{
557553
let mut ids = Vec::new();
558554
for (id, m) in &self.circuit().modules {
559-
if m.definition_index == i {
555+
if m.definition_id == i {
560556
ids.push(id);
561557
}
562558
}
@@ -1077,18 +1073,19 @@ impl App {
10771073
fn draw_module(&mut self, ui: &mut Ui, id: InstanceId) {
10781074
let (pos, definition_index) = {
10791075
let module = self.db.circuit.get_module(id);
1080-
(module.pos, module.definition_index)
1076+
(module.pos, module.definition_id)
10811077
};
10821078
let screen_center = pos - self.viewport_offset;
10831079

10841080
let (name, pins, pin_offsets) = {
10851081
let definition = self.db.circuit.get_module(id).definition(&self.db);
10861082
let name = definition.name.clone();
1087-
let pins = definition.get_unconnected_pins(&self.db, id);
1088-
1083+
let pins = self.db.circuit.get_module(id).pins();
10891084
let pin_offsets: Vec<Vec2> = pins
10901085
.iter()
1091-
.map(|pin| definition.calculate_pin_offset(&self.db, pin, &self.canvas_config))
1086+
.map(|pin| {
1087+
definition.calculate_pin_offset(&self.db, &pins, pin, &self.canvas_config)
1088+
})
10921089
.collect();
10931090

10941091
(name, pins, pin_offsets)
@@ -1128,7 +1125,7 @@ impl App {
11281125
}));
11291126
}
11301127

1131-
for (pin_index, (&pin, &pin_offset)) in pins.iter().zip(pin_offsets.iter()).enumerate() {
1128+
for (&pin, &pin_offset) in pins.iter().zip(pin_offsets.iter()) {
11321129
let pin_pos_world = pos + pin_offset;
11331130
let pin_screen_pos = self.adjusted_pos(pin_pos_world);
11341131

@@ -1140,7 +1137,7 @@ impl App {
11401137
ui.painter()
11411138
.circle_filled(pin_screen_pos, self.canvas_config.base_pin_size, pin_color);
11421139

1143-
let has_current = self.is_on(Pin::new(id, pin_index as u32, pin.kind));
1140+
let has_current = self.is_on(pin);
11441141

11451142
if has_current {
11461143
ui.painter().circle_stroke(
@@ -1155,15 +1152,12 @@ impl App {
11551152
Vec2::splat(self.canvas_config.base_pin_size + PIN_HOVER_THRESHOLD),
11561153
);
11571154
let pin_resp = ui.allocate_rect(pin_rect, Sense::drag());
1158-
let pin_obj = Pin::new(id, pin_index as u32, pin.kind);
11591155
if pin_resp.hovered() {
1160-
self.hovered = Some(Hover::Pin(pin_obj));
1156+
self.hovered = Some(Hover::Pin(pin));
11611157
}
11621158
if pin_resp.dragged() {
11631159
self.selected.clear();
1164-
self.set_drag(Drag::PinToWire {
1165-
source_pin: pin_obj,
1166-
});
1160+
self.set_drag(Drag::PinToWire { source_pin: pin });
11671161
}
11681162
}
11691163
}
@@ -1551,30 +1545,31 @@ impl App {
15511545

15521546
fn debug_string(&self, ui: &Ui) -> String {
15531547
let mut out = String::new();
1548+
1549+
// App state (compact)
1550+
writeln!(out, "======================================").ok();
1551+
writeln!(out, " APP STATE").ok();
1552+
writeln!(out, "======================================").ok();
15541553
let mouse_pos_world = self.mouse_pos_world(ui);
15551554
writeln!(out, "mouse: {mouse_pos_world:?}").ok();
1556-
15571555
writeln!(out, "hovered: {:?}", self.hovered).ok();
15581556
writeln!(out, "drag: {:?}", self.drag).ok();
1559-
writeln!(out, "viewport_offset: {:?}", self.viewport_offset).ok();
1560-
writeln!(out, "potential_conns: {}", self.potential_connections.len()).ok();
1561-
writeln!(out, "clipboard: {:?}", self.clipboard).ok();
15621557
writeln!(out, "selected: {:?}", self.selected).ok();
1563-
writeln!(out, "editing_label: {:?}", self.editing_label).ok();
1564-
writeln!(out, "label_edit_buffer: {}", self.label_edit_buffer).ok();
15651558
writeln!(out, "viewing_module: {:?}", self.viewing_module).ok();
15661559

15671560
// Simulation status
1568-
writeln!(out, "\n=== Simulation Status ===").ok();
1569-
writeln!(out, "needs update {}", self.current_dirty).ok();
1561+
writeln!(out).ok();
1562+
writeln!(out, "======================================").ok();
1563+
writeln!(out, " SIMULATION").ok();
1564+
writeln!(out, "======================================").ok();
15701565
match self.simulator.status {
15711566
SimulationStatus::Stable { iterations } => {
1572-
writeln!(out, "Status: STABLE (after {iterations} iterations)").ok();
1567+
writeln!(out, "Status: STABLE ({iterations} iters)").ok();
15731568
}
15741569
SimulationStatus::Unstable { max_reached } => {
15751570
if max_reached {
15761571
let iters = self.simulator.last_iterations;
1577-
writeln!(out, "Status: UNSTABLE (max iterations: {iters})").ok();
1572+
writeln!(out, "Status: UNSTABLE (max: {iters})").ok();
15781573
} else {
15791574
writeln!(out, "Status: UNSTABLE").ok();
15801575
}
@@ -1583,44 +1578,31 @@ impl App {
15831578
writeln!(out, "Status: RUNNING...").ok();
15841579
}
15851580
}
1586-
let iters = self.simulator.last_iterations;
1587-
writeln!(out, "Iterations: {iters}").ok();
1588-
1589-
// Clock controller state
1590-
writeln!(out, "\n--- Clock Controller ---").ok();
1591-
writeln!(out, "State: {:?}", self.clock_controller.state).ok();
15921581
writeln!(
15931582
out,
1594-
"Tick interval: {:.2}s",
1595-
self.clock_controller.tick_interval
1583+
"Clock: {:?}, interval: {:.2}s",
1584+
self.clock_controller.state, self.clock_controller.tick_interval
15961585
)
15971586
.ok();
1598-
writeln!(out, "Voltage: {}", self.clock_controller.voltage).ok();
15991587

1600-
if self.potential_connections.is_empty() {
1601-
writeln!(out, "\nPotential Connections: none").ok();
1602-
} else {
1603-
writeln!(out, "\nPotential Connections:").ok();
1604-
for c in &self.potential_connections {
1605-
writeln!(out, " {}", c.display(self.circuit())).ok();
1606-
}
1607-
}
1608-
1609-
writeln!(out, "\n{}", self.connection_manager.debug_info()).ok();
1610-
1611-
writeln!(out, "\n").ok();
1612-
1613-
out.write_str(&self.circuit().display(&self.db)).ok();
1588+
// Circuit instances (main content)
1589+
writeln!(out).ok();
1590+
out.write_str(&self.circuit().display(&self.db, Some(&self.simulator)))
1591+
.ok();
16141592

1593+
// Module definitions (at the bottom, summary only)
16151594
if !self.db.module_definitions.is_empty() {
1616-
writeln!(out, "\nModule Def:").ok();
1617-
let mut iter = self.db.module_definitions.iter();
1618-
if let Some((id, first)) = iter.next() {
1619-
writeln!(out, " {}", first.display_definition(&self.db, id)).ok();
1620-
}
1621-
for (id, m) in iter {
1622-
writeln!(out).ok();
1623-
writeln!(out, " {}", m.display_definition(&self.db, id)).ok();
1595+
writeln!(out).ok();
1596+
writeln!(out, "======================================").ok();
1597+
writeln!(
1598+
out,
1599+
" MODULE DEFINITIONS ({} total)",
1600+
self.db.module_definitions.len()
1601+
)
1602+
.ok();
1603+
writeln!(out, "======================================").ok();
1604+
for (id, m) in &self.db.module_definitions {
1605+
writeln!(out, "{}", m.display_definition(&self.db, id)).ok();
16241606
}
16251607
}
16261608

@@ -1691,7 +1673,7 @@ impl App {
16911673
}
16921674
InstanceKind::Module(_) => {
16931675
let cc = self.db.circuit.get_module(id);
1694-
object_pos.push(ClipBoardItem::Module(cc.definition_index, center - cc.pos));
1676+
object_pos.push(ClipBoardItem::Module(cc.definition_id, center - cc.pos));
16951677
}
16961678
}
16971679
}
@@ -1742,12 +1724,13 @@ impl App {
17421724
self.selected.insert(id);
17431725
}
17441726
ClipBoardItem::Module(def_index, offset) => {
1745-
let id = self.db.new_module_with_flattening(Module {
1746-
pos: mouse - offset,
1747-
definition_index: def_index,
1748-
});
1749-
self.connection_manager.mark_instance_dirty(id);
1750-
self.selected.insert(id);
1727+
// TODO: Modules
1728+
// let id = self.db.new_module_with_flattening(Module {
1729+
// pos: mouse - offset,
1730+
// definition_index: def_index,
1731+
// });
1732+
// self.connection_manager.mark_instance_dirty(id);
1733+
// self.selected.insert(id);
17511734
}
17521735
ClipBoardItem::Lamp(offset) => {
17531736
let id = self.db.circuit.new_lamp(Lamp {

src/connection_manager.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,46 @@ use std::collections::{HashMap, HashSet};
88

99
const SPATIAL_INDEX_GRID_SIZE: f32 = 100.0;
1010

11+
#[derive(serde::Deserialize, serde::Serialize, Copy, PartialEq, Eq, Debug, Clone)]
12+
pub enum ConnectionKind {
13+
SINGLE,
14+
// Bi directional connection is a special kind where both ends can be input or output.
15+
BI,
16+
}
17+
1118
// A normalized, order-independent connection between two pins
1219
#[derive(serde::Deserialize, serde::Serialize, Copy, Debug, Clone)]
1320
pub struct Connection {
1421
pub a: Pin,
1522
pub b: Pin,
23+
pub kind: ConnectionKind,
1624
}
1725

1826
impl Connection {
1927
pub fn new(p1: Pin, p2: Pin) -> Self {
20-
Self { a: p2, b: p1 }
28+
Self {
29+
a: p2,
30+
b: p1,
31+
kind: ConnectionKind::SINGLE,
32+
}
33+
}
34+
35+
pub fn new_bi(p1: Pin, p2: Pin) -> Self {
36+
Self {
37+
a: p2,
38+
b: p1,
39+
kind: ConnectionKind::BI,
40+
}
2141
}
2242

2343
pub fn involves_instance(&self, id: InstanceId) -> bool {
2444
self.a.ins == id || self.b.ins == id
2545
}
2646

47+
pub fn involves_pin(&self, pin: &Pin) -> bool {
48+
self.a == *pin || self.b == *pin
49+
}
50+
2751
pub fn display(&self, circuit: &Circuit) -> String {
2852
format!(
2953
"{} <-> {}",
@@ -32,6 +56,24 @@ impl Connection {
3256
)
3357
}
3458

59+
/// Short display for connection list: "And[0v1].pin#0 -> Lamp[1v1].pin#0"
60+
pub fn display_short(&self, circuit: &Circuit, db: &DB) -> String {
61+
if self.kind == ConnectionKind::SINGLE {
62+
format!(
63+
"{} -> {}",
64+
self.a.display_short(circuit, db),
65+
self.b.display_short(circuit, db)
66+
)
67+
} else {
68+
format!(
69+
"{} <-> {}",
70+
self.a.display_short(circuit, db),
71+
self.b.display_short(circuit, db)
72+
)
73+
}
74+
}
75+
76+
// Returns a tuple with the given pin first and then second pin
3577
pub fn get_pin_first(&self, pin: Pin) -> Option<(Pin, Pin)> {
3678
if self.a == pin {
3779
Some((self.a, self.b))
@@ -41,6 +83,17 @@ impl Connection {
4183
None
4284
}
4385
}
86+
87+
// Returns a tuple with the given pin first and then second pin
88+
pub fn get_other_pin(&self, pin: Pin) -> Pin {
89+
if self.a == pin {
90+
self.b
91+
} else if self.b == pin {
92+
self.a
93+
} else {
94+
unreachable!();
95+
}
96+
}
4497
}
4598

4699
impl PartialEq for Connection {
@@ -326,6 +379,16 @@ impl ConnectionManager {
326379

327380
let mut connections_to_keep = HashSet::new();
328381
for connection in &db.circuit.connections {
382+
let is_module_connection = {
383+
db.get_module_owner(connection.a.ins).is_some()
384+
|| db.get_module_owner(connection.b.ins).is_some()
385+
};
386+
// Keep module connections always, as they're structural user cannot remove them.
387+
if is_module_connection {
388+
connections_to_keep.insert(*connection);
389+
continue;
390+
}
391+
329392
let keep_connection = !self.dirty_instances.contains(&connection.a.ins)
330393
&& !self.dirty_instances.contains(&connection.b.ins);
331394

0 commit comments

Comments
 (0)