Skip to main content

brep_kernel/feature_pipeline/pmi/annotations/
hide.rs

1//! Hide body (`HID`): a display-only step that keeps solids / components out
2//! of the owning view while it is active — the visibility counterpart of the
3//! explode step, recorded, listed, edited and undone the same way. Nothing is
4//! drawn for it: no chip in the 3D view, no text on a sheet. The viewport,
5//! the sheets, the 3D PDF and the instructions pictures all read the same
6//! rule, [`PmiView::hides`](crate::feature_pipeline::pmi::PmiView::hides).
7
8use super::{id_field, params, reference_field, schema_entry, target_solids, PmiTypeDef};
9use crate::feature_pipeline::pmi::resolve::{a3, solid_bbox};
10use crate::feature_pipeline::pmi::{PmiAnnotation, PmiContext, PmiGeometry, Resolved};
11use crate::feature_pipeline::SelectionProbe;
12use crate::Vec3;
13
14pub const DEF: PmiTypeDef = PmiTypeDef {
15    type_id: "hide",
16    short_name: "HID",
17    icon: "\u{E0D4}",
18    long_name: "\u{E0D4} Hide body",
19    label: "Hide body",
20    applicable,
21    schema,
22    resolve,
23};
24
25/// One or more solids / components.
26fn applicable(probe: &SelectionProbe) -> bool {
27    probe.solids + probe.components >= 1
28}
29
30fn schema() -> serde_json::Value {
31    schema_entry(
32        &DEF,
33        params(vec![
34            ("id", id_field()),
35            (
36                "targets",
37                reference_field("Targets", &["SOLID", "COMPONENT"], true, 1, 64, "The solids or components hidden while the view is active"),
38            ),
39        ]),
40    )
41}
42
43fn resolve(annotation: &PmiAnnotation, context: &PmiContext<'_>) -> Result<Resolved, String> {
44    // A view's baseline step (the solids hidden at capture) skips a name
45    // that no longer resolves, as the captured list always did; an author's
46    // step names what it hides, so a stale target is its error.
47    let solids = if annotation.is_baseline_hide() {
48        let mut solids: Vec<(String, u32)> = Vec::new();
49        for target in annotation.references("targets") {
50            for solid in target_solids(std::slice::from_ref(&target), context).unwrap_or_default() {
51                if !solids.iter().any(|(name, _)| *name == solid.0) {
52                    solids.push(solid);
53                }
54            }
55        }
56        solids
57    } else {
58        target_solids(&annotation.references("targets"), context)?
59    };
60    if solids.is_empty() {
61        return Ok(Resolved {
62            text: "Hide (nothing present)".into(),
63            value: None,
64            unit: "",
65            references: Vec::new(),
66            geometry: PmiGeometry::Hide { solids: Vec::new() },
67            default_label: [0.0; 3],
68        });
69    }
70    let mut low = Vec3::new(f64::INFINITY, f64::INFINITY, f64::INFINITY);
71    let mut high = Vec3::new(f64::NEG_INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY);
72    for (_, handle) in &solids {
73        let (lo, hi) = solid_bbox(*handle)?;
74        low = Vec3::new(low.x.min(lo.x), low.y.min(lo.y), low.z.min(lo.z));
75        high = Vec3::new(high.x.max(hi.x), high.y.max(hi.y), high.z.max(hi.z));
76    }
77    let center = low.add(high).scale(0.5);
78    let names: Vec<String> = solids.into_iter().map(|(name, _)| name).collect();
79    Ok(Resolved {
80        text: format!("Hide {}", names.join(", ")),
81        value: None,
82        unit: "",
83        references: names.clone(),
84        geometry: PmiGeometry::Hide { solids: names },
85        default_label: a3(center),
86    })
87}