brep_render/engine_state/
wire_harness_ops.rs1use super::*;
2use brep_kernel::{WireHarnessConnection, WireHarnessReport, WireHarnessState};
3
4#[derive(Debug, Default, Clone, PartialEq)]
7pub struct ConnectionPatch {
8 pub name: Option<String>,
9 pub from: Option<String>,
10 pub to: Option<String>,
11 pub diameter: Option<f64>,
12}
13
14impl EngineState {
15 pub fn wire_harness_report(&self) -> Option<&WireHarnessReport> {
21 self.wire_harness_report.as_ref()
22 }
23
24 pub fn wire_harness_state(&self) -> WireHarnessState {
27 self.history
28 .wire_harness_block()
29 .and_then(|block| serde_json::from_value(block.clone()).ok())
30 .unwrap_or_default()
31 }
32
33 pub fn wire_harness_state_json(&self) -> String {
36 self.wire_harness_state_value().to_string()
37 }
38
39 pub fn wire_harness_state_value(&self) -> serde_json::Value {
41 let state = self.wire_harness_state();
42 serde_json::json!({
43 "connections": state.connections,
44 "buildBundles": state.build_bundles,
45 "cutMargin": state.cut_margin,
46 "report": self.wire_harness_report,
47 })
48 }
49
50 fn write_wire_harness_state(&mut self, state: WireHarnessState) -> String {
57 let block = if state.connections.is_empty() && state.id_counter == 0 && state.cut_margin == 0.0 {
58 None
59 } else {
60 serde_json::to_value(&state).ok()
61 };
62 self.history.set_wire_harness_block(block);
63 self.rerun_history()
64 }
65
66 pub fn wire_harness_add_connection(&mut self, from: &str, to: &str, diameter: f64) -> String {
69 let mut state = self.wire_harness_state();
70 let id = state.next_id();
71 let name = format!("Wire {}", state.id_counter);
72 state.connections.push(WireHarnessConnection {
73 id: id.clone(),
74 name,
75 from: from.to_string(),
76 to: to.to_string(),
77 diameter: if diameter.is_finite() && diameter > 0.0 { diameter } else { 1.0 },
78 });
79 self.write_wire_harness_state(state);
80 id
81 }
82
83 pub fn wire_harness_update_connection(
86 &mut self,
87 id: &str,
88 patch: &ConnectionPatch,
89 ) -> Result<(), String> {
90 let mut state = self.wire_harness_state();
91 let connection = state
92 .connections
93 .iter_mut()
94 .find(|connection| connection.id == id)
95 .ok_or_else(|| format!("no harness connection '{id}'"))?;
96 if let Some(name) = &patch.name {
97 connection.name = name.trim().to_string();
98 }
99 if let Some(from) = &patch.from {
100 connection.from = from.trim().to_string();
101 }
102 if let Some(to) = &patch.to {
103 connection.to = to.trim().to_string();
104 }
105 if let Some(diameter) = patch.diameter {
106 if !(diameter.is_finite() && diameter > 0.0) {
107 return Err(format!("wire diameter must be positive, got {diameter}"));
108 }
109 connection.diameter = diameter;
110 }
111 self.write_wire_harness_state(state);
112 Ok(())
113 }
114
115 pub fn wire_harness_remove_connection(&mut self, id: &str) -> Result<(), String> {
117 let mut state = self.wire_harness_state();
118 let before = state.connections.len();
119 state.connections.retain(|connection| connection.id != id);
120 if state.connections.len() == before {
121 return Err(format!("no harness connection '{id}'"));
122 }
123 self.write_wire_harness_state(state);
124 Ok(())
125 }
126
127 pub fn wire_harness_set_build_bundles(&mut self, on: bool) {
129 let mut state = self.wire_harness_state();
130 if state.build_bundles == on {
131 return;
132 }
133 state.build_bundles = on;
134 self.write_wire_harness_state(state);
135 }
136
137 pub fn wire_harness_set_cut_margin(&mut self, margin: f64) -> Result<(), String> {
143 if !(margin.is_finite() && margin >= 0.0) {
144 return Err(format!("cut margin must be zero or more, got {margin}"));
145 }
146 let mut state = self.wire_harness_state();
147 if state.cut_margin == margin {
148 return Ok(());
149 }
150 state.cut_margin = margin;
151 self.write_wire_harness_state(state);
152 Ok(())
153 }
154
155 pub fn wire_harness_hover_connection(&mut self, id: &str) {
161 let state = self.wire_harness_state();
162 let mut names: Vec<String> = Vec::new();
163 if let Some(connection) = state.connections.iter().find(|c| c.id == id) {
164 for port in [&connection.from, &connection.to] {
165 if !port.is_empty() && self.scene.solid(port).is_some() {
166 names.push(port.clone());
167 }
168 }
169 }
170 if let Some(report) = &self.wire_harness_report {
171 if let Some(route) = report.routes.iter().find(|route| route.connection_id == id) {
172 for segment in &route.segment_ids {
173 if let Some(bundle) = report.bundles.iter().find(|b| &b.segment_id == segment) {
174 if !bundle.solid_name.is_empty() {
175 names.push(bundle.solid_name.clone());
176 }
177 }
178 }
179 }
180 }
181 self.clear_hover();
182 self.emphasis.hovered_solids.extend(names);
183 self.emphasis.generation = self.emphasis.generation.wrapping_add(1);
184 self.dirty = true;
185 }
186
187 pub fn wire_harness_hover_end(&mut self) {
189 if self.clear_hover() {
190 self.dirty = true;
191 }
192 }
193}
194