use brep_render::engine_state::EngineState;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum ComponentAction {
Move,
OpenPart,
ToggleFixed,
Delete,
}
impl ComponentAction {
pub const ALL: [ComponentAction; 4] = [
ComponentAction::Move,
ComponentAction::OpenPart,
ComponentAction::ToggleFixed,
ComponentAction::Delete,
];
pub fn id(self) -> &'static str {
match self {
ComponentAction::Move => "move",
ComponentAction::OpenPart => "open-part",
ComponentAction::ToggleFixed => "toggle-fixed",
ComponentAction::Delete => "delete",
}
}
pub fn from_id(id: &str) -> Option<Self> {
Self::ALL.into_iter().find(|action| action.id() == id)
}
pub fn label(self, fixed: bool) -> &'static str {
match self {
ComponentAction::Move => "\u{2725} Move",
ComponentAction::OpenPart => "\u{270E} Edit Part",
ComponentAction::ToggleFixed => {
if fixed {
"\u{1F513} Unfix"
} else {
"\u{1F512} Fix"
}
}
ComponentAction::Delete => "\u{2716} Delete",
}
}
pub fn tooltip(self) -> &'static str {
match self {
ComponentAction::Move => "Move/rotate gizmo on-off (arrows + arcs together)",
ComponentAction::OpenPart => "Open the part's source document in its own tab",
ComponentAction::ToggleFixed => "Ground / free this instance for the solver",
ComponentAction::Delete => "Delete this component instance",
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ComponentActionRequest {
OpenPart { component_id: String },
}
pub fn run_component_action(
state: &mut EngineState,
action: ComponentAction,
component_id: &str,
) -> Option<ComponentActionRequest> {
match action {
ComponentAction::Move => {
state.component_move_toggle(component_id);
None
}
ComponentAction::ToggleFixed => {
let Some(info) = state.component_info(component_id) else {
state.push_notice(format!("'{component_id}' is not an assembly component"));
return None;
};
let mut params = serde_json::from_str::<serde_json::Value>(
&state.feature_params_json(feature_index(state, component_id)?),
)
.unwrap_or_else(|_| serde_json::json!({}));
if let Some(object) = params.as_object_mut() {
object.insert("isFixed".into(), serde_json::Value::Bool(!info.fixed));
}
let _ = state.update_feature_params(component_id, ¶ms.to_string());
None
}
ComponentAction::Delete => {
let _ = state.delete_feature(component_id);
None
}
ComponentAction::OpenPart => Some(ComponentActionRequest::OpenPart {
component_id: component_id.to_string(),
}),
}
}
fn feature_index(state: &EngineState, id: &str) -> Option<usize> {
(0..state.history_len()).find(|&i| state.feature_id_at(i).as_deref() == Some(id))
}
pub fn part_source_key(state: &EngineState, component_id: &str) -> Option<String> {
let info = state.component_info(component_id)?;
let document: serde_json::Value =
serde_json::from_str(&state.history_request_json()).ok()?;
document["partsLibrary"][&info.part_name]["sourceKey"]
.as_str()
.filter(|key| !key.is_empty())
.map(str::to_string)
}