Skip to main content

polyscope_rs/
groups.rs

1//! Group management for organizing structures.
2//!
3//! Groups provide hierarchical organization of structures. When a group is
4//! disabled, all structures within it (and child groups) are hidden.
5//!
6//! # Example
7//!
8//! ```no_run
9//! use polyscope_rs::*;
10//!
11//! fn main() -> Result<()> {
12//!     init()?;
13//!
14//!     // Create structures
15//!     register_point_cloud("points1", vec![Vec3::ZERO]);
16//!     register_point_cloud("points2", vec![Vec3::X]);
17//!
18//!     // Organize into a group
19//!     let group = create_group("my group");
20//!     group.add_point_cloud("points1");
21//!     group.add_point_cloud("points2");
22//!
23//!     // Toggle visibility of entire group
24//!     group.set_enabled(false);
25//!
26//!     show();
27//!     Ok(())
28//! }
29//! ```
30
31use crate::{with_context, with_context_mut};
32
33/// Creates a new group for organizing structures.
34///
35/// Groups allow organizing structures hierarchically. When a group is disabled,
36/// all structures and child groups within it are hidden.
37pub fn create_group(name: impl Into<String>) -> GroupHandle {
38    let name = name.into();
39    with_context_mut(|ctx| {
40        ctx.create_group(&name);
41    });
42    GroupHandle { name }
43}
44
45/// Gets an existing group by name.
46#[must_use]
47pub fn get_group(name: &str) -> Option<GroupHandle> {
48    with_context(|ctx| {
49        if ctx.has_group(name) {
50            Some(GroupHandle {
51                name: name.to_string(),
52            })
53        } else {
54            None
55        }
56    })
57}
58
59/// Removes a group by name.
60///
61/// Note: This does not remove structures from the group, only the group itself.
62pub fn remove_group(name: &str) {
63    with_context_mut(|ctx| {
64        ctx.remove_group(name);
65    });
66}
67
68/// Removes all groups.
69///
70/// Note: This does not remove structures, only the groups themselves.
71pub fn remove_all_groups() {
72    with_context_mut(|ctx| {
73        ctx.groups.clear();
74    });
75}
76
77/// Returns all group names.
78#[must_use]
79pub fn get_all_groups() -> Vec<String> {
80    with_context(|ctx| {
81        ctx.group_names()
82            .into_iter()
83            .map(std::string::ToString::to_string)
84            .collect()
85    })
86}
87
88/// Handle for a group.
89#[derive(Clone)]
90pub struct GroupHandle {
91    name: String,
92}
93
94impl GroupHandle {
95    /// Returns the name of this group.
96    #[must_use]
97    pub fn name(&self) -> &str {
98        &self.name
99    }
100
101    /// Sets whether this group is enabled (visible).
102    pub fn set_enabled(&self, enabled: bool) -> &Self {
103        with_context_mut(|ctx| {
104            if let Some(group) = ctx.get_group_mut(&self.name) {
105                group.set_enabled(enabled);
106            }
107        });
108        self
109    }
110
111    /// Returns whether this group is enabled.
112    #[must_use]
113    pub fn is_enabled(&self) -> bool {
114        with_context(|ctx| {
115            ctx.get_group(&self.name)
116                .is_some_and(polyscope_core::Group::is_enabled)
117        })
118    }
119
120    /// Sets whether child details are shown in UI.
121    pub fn set_show_child_details(&self, show: bool) -> &Self {
122        with_context_mut(|ctx| {
123            if let Some(group) = ctx.get_group_mut(&self.name) {
124                group.set_show_child_details(show);
125            }
126        });
127        self
128    }
129
130    /// Adds a point cloud to this group.
131    pub fn add_point_cloud(&self, pc_name: &str) -> &Self {
132        with_context_mut(|ctx| {
133            if let Some(group) = ctx.get_group_mut(&self.name) {
134                group.add_structure("PointCloud", pc_name);
135            }
136        });
137        self
138    }
139
140    /// Adds a surface mesh to this group.
141    pub fn add_surface_mesh(&self, mesh_name: &str) -> &Self {
142        with_context_mut(|ctx| {
143            if let Some(group) = ctx.get_group_mut(&self.name) {
144                group.add_structure("SurfaceMesh", mesh_name);
145            }
146        });
147        self
148    }
149
150    /// Adds a curve network to this group.
151    pub fn add_curve_network(&self, cn_name: &str) -> &Self {
152        with_context_mut(|ctx| {
153            if let Some(group) = ctx.get_group_mut(&self.name) {
154                group.add_structure("CurveNetwork", cn_name);
155            }
156        });
157        self
158    }
159
160    /// Adds a volume mesh to this group.
161    pub fn add_volume_mesh(&self, vm_name: &str) -> &Self {
162        with_context_mut(|ctx| {
163            if let Some(group) = ctx.get_group_mut(&self.name) {
164                group.add_structure("VolumeMesh", vm_name);
165            }
166        });
167        self
168    }
169
170    /// Adds a volume grid to this group.
171    pub fn add_volume_grid(&self, vg_name: &str) -> &Self {
172        with_context_mut(|ctx| {
173            if let Some(group) = ctx.get_group_mut(&self.name) {
174                group.add_structure("VolumeGrid", vg_name);
175            }
176        });
177        self
178    }
179
180    /// Adds a camera view to this group.
181    pub fn add_camera_view(&self, cv_name: &str) -> &Self {
182        with_context_mut(|ctx| {
183            if let Some(group) = ctx.get_group_mut(&self.name) {
184                group.add_structure("CameraView", cv_name);
185            }
186        });
187        self
188    }
189
190    /// Removes a structure from this group.
191    pub fn remove_structure(&self, type_name: &str, name: &str) -> &Self {
192        with_context_mut(|ctx| {
193            if let Some(group) = ctx.get_group_mut(&self.name) {
194                group.remove_structure(type_name, name);
195            }
196        });
197        self
198    }
199
200    /// Adds a child group to this group.
201    pub fn add_child_group(&self, child_name: &str) -> &Self {
202        with_context_mut(|ctx| {
203            // Set parent on child group
204            if let Some(child) = ctx.get_group_mut(child_name) {
205                child.set_parent_group(Some(self.name.clone()));
206            }
207            // Add child reference to this group
208            if let Some(group) = ctx.get_group_mut(&self.name) {
209                group.add_child_group(child_name);
210            }
211        });
212        self
213    }
214
215    /// Removes a child group from this group.
216    pub fn remove_child_group(&self, child_name: &str) -> &Self {
217        with_context_mut(|ctx| {
218            // Remove parent from child group
219            if let Some(child) = ctx.get_group_mut(child_name) {
220                child.set_parent_group(None);
221            }
222            // Remove child reference from this group
223            if let Some(group) = ctx.get_group_mut(&self.name) {
224                group.remove_child_group(child_name);
225            }
226        });
227        self
228    }
229
230    /// Returns the number of structures in this group.
231    #[must_use]
232    pub fn num_structures(&self) -> usize {
233        with_context(|ctx| {
234            ctx.get_group(&self.name)
235                .map_or(0, polyscope_core::Group::num_child_structures)
236        })
237    }
238
239    /// Returns the number of child groups.
240    #[must_use]
241    pub fn num_child_groups(&self) -> usize {
242        with_context(|ctx| {
243            ctx.get_group(&self.name)
244                .map_or(0, polyscope_core::Group::num_child_groups)
245        })
246    }
247}