use super::*;
use brep_kernel::{WireHarnessConnection, WireHarnessReport, WireHarnessState};
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ConnectionPatch {
pub name: Option<String>,
pub from: Option<String>,
pub to: Option<String>,
pub diameter: Option<f64>,
}
impl EngineState {
pub fn wire_harness_report(&self) -> Option<&WireHarnessReport> {
self.wire_harness_report.as_ref()
}
pub fn wire_harness_state(&self) -> WireHarnessState {
self.history
.wire_harness_block()
.and_then(|block| serde_json::from_value(block.clone()).ok())
.unwrap_or_default()
}
pub fn wire_harness_state_json(&self) -> String {
let state = self.wire_harness_state();
serde_json::json!({
"connections": state.connections,
"buildBundles": state.build_bundles,
"report": self.wire_harness_report,
})
.to_string()
}
fn write_wire_harness_state(&mut self, state: WireHarnessState) -> String {
let block = if state.connections.is_empty() && state.id_counter == 0 {
None
} else {
serde_json::to_value(&state).ok()
};
self.history.set_wire_harness_block(block);
self.rerun_history()
}
pub fn wire_harness_add_connection(&mut self, from: &str, to: &str, diameter: f64) -> String {
let mut state = self.wire_harness_state();
let id = state.next_id();
let name = format!("Wire {}", state.id_counter);
state.connections.push(WireHarnessConnection {
id: id.clone(),
name,
from: from.to_string(),
to: to.to_string(),
diameter: if diameter.is_finite() && diameter > 0.0 { diameter } else { 1.0 },
});
self.write_wire_harness_state(state);
id
}
pub fn wire_harness_update_connection(
&mut self,
id: &str,
patch: &ConnectionPatch,
) -> Result<(), String> {
let mut state = self.wire_harness_state();
let connection = state
.connections
.iter_mut()
.find(|connection| connection.id == id)
.ok_or_else(|| format!("no harness connection '{id}'"))?;
if let Some(name) = &patch.name {
connection.name = name.trim().to_string();
}
if let Some(from) = &patch.from {
connection.from = from.trim().to_string();
}
if let Some(to) = &patch.to {
connection.to = to.trim().to_string();
}
if let Some(diameter) = patch.diameter {
if !(diameter.is_finite() && diameter > 0.0) {
return Err(format!("wire diameter must be positive, got {diameter}"));
}
connection.diameter = diameter;
}
self.write_wire_harness_state(state);
Ok(())
}
pub fn wire_harness_remove_connection(&mut self, id: &str) -> Result<(), String> {
let mut state = self.wire_harness_state();
let before = state.connections.len();
state.connections.retain(|connection| connection.id != id);
if state.connections.len() == before {
return Err(format!("no harness connection '{id}'"));
}
self.write_wire_harness_state(state);
Ok(())
}
pub fn wire_harness_set_build_bundles(&mut self, on: bool) {
let mut state = self.wire_harness_state();
if state.build_bundles == on {
return;
}
state.build_bundles = on;
self.write_wire_harness_state(state);
}
pub fn wire_harness_hover_connection(&mut self, id: &str) {
let state = self.wire_harness_state();
let mut names: Vec<String> = Vec::new();
if let Some(connection) = state.connections.iter().find(|c| c.id == id) {
for port in [&connection.from, &connection.to] {
if !port.is_empty() && self.scene.solid(port).is_some() {
names.push(port.clone());
}
}
}
if let Some(report) = &self.wire_harness_report {
if let Some(route) = report.routes.iter().find(|route| route.connection_id == id) {
for segment in &route.segment_ids {
if let Some(bundle) = report.bundles.iter().find(|b| &b.segment_id == segment) {
if !bundle.solid_name.is_empty() {
names.push(bundle.solid_name.clone());
}
}
}
}
}
self.clear_hover();
self.emphasis.hovered_solids.extend(names);
self.emphasis.generation = self.emphasis.generation.wrapping_add(1);
self.dirty = true;
}
pub fn wire_harness_hover_end(&mut self) {
if self.clear_hover() {
self.dirty = true;
}
}
}