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/// Returns all group names.
69#[must_use]
70pub fn get_all_groups() -> Vec<String> {
71    with_context(|ctx| {
72        ctx.group_names()
73            .into_iter()
74            .map(std::string::ToString::to_string)
75            .collect()
76    })
77}
78
79/// Handle for a group.
80#[derive(Clone)]
81pub struct GroupHandle {
82    name: String,
83}
84
85impl GroupHandle {
86    /// Returns the name of this group.
87    #[must_use]
88    pub fn name(&self) -> &str {
89        &self.name
90    }
91
92    /// Sets whether this group is enabled (visible).
93    pub fn set_enabled(&self, enabled: bool) -> &Self {
94        with_context_mut(|ctx| {
95            if let Some(group) = ctx.get_group_mut(&self.name) {
96                group.set_enabled(enabled);
97            }
98        });
99        self
100    }
101
102    /// Returns whether this group is enabled.
103    #[must_use]
104    pub fn is_enabled(&self) -> bool {
105        with_context(|ctx| {
106            ctx.get_group(&self.name)
107                .is_some_and(polyscope_core::Group::is_enabled)
108        })
109    }
110
111    /// Sets whether child details are shown in UI.
112    pub fn set_show_child_details(&self, show: bool) -> &Self {
113        with_context_mut(|ctx| {
114            if let Some(group) = ctx.get_group_mut(&self.name) {
115                group.set_show_child_details(show);
116            }
117        });
118        self
119    }
120
121    /// Adds a point cloud to this group.
122    pub fn add_point_cloud(&self, pc_name: &str) -> &Self {
123        with_context_mut(|ctx| {
124            if let Some(group) = ctx.get_group_mut(&self.name) {
125                group.add_structure("PointCloud", pc_name);
126            }
127        });
128        self
129    }
130
131    /// Adds a surface mesh to this group.
132    pub fn add_surface_mesh(&self, mesh_name: &str) -> &Self {
133        with_context_mut(|ctx| {
134            if let Some(group) = ctx.get_group_mut(&self.name) {
135                group.add_structure("SurfaceMesh", mesh_name);
136            }
137        });
138        self
139    }
140
141    /// Adds a curve network to this group.
142    pub fn add_curve_network(&self, cn_name: &str) -> &Self {
143        with_context_mut(|ctx| {
144            if let Some(group) = ctx.get_group_mut(&self.name) {
145                group.add_structure("CurveNetwork", cn_name);
146            }
147        });
148        self
149    }
150
151    /// Adds a volume mesh to this group.
152    pub fn add_volume_mesh(&self, vm_name: &str) -> &Self {
153        with_context_mut(|ctx| {
154            if let Some(group) = ctx.get_group_mut(&self.name) {
155                group.add_structure("VolumeMesh", vm_name);
156            }
157        });
158        self
159    }
160
161    /// Adds a volume grid to this group.
162    pub fn add_volume_grid(&self, vg_name: &str) -> &Self {
163        with_context_mut(|ctx| {
164            if let Some(group) = ctx.get_group_mut(&self.name) {
165                group.add_structure("VolumeGrid", vg_name);
166            }
167        });
168        self
169    }
170
171    /// Adds a camera view to this group.
172    pub fn add_camera_view(&self, cv_name: &str) -> &Self {
173        with_context_mut(|ctx| {
174            if let Some(group) = ctx.get_group_mut(&self.name) {
175                group.add_structure("CameraView", cv_name);
176            }
177        });
178        self
179    }
180
181    /// Removes a structure from this group.
182    pub fn remove_structure(&self, type_name: &str, name: &str) -> &Self {
183        with_context_mut(|ctx| {
184            if let Some(group) = ctx.get_group_mut(&self.name) {
185                group.remove_structure(type_name, name);
186            }
187        });
188        self
189    }
190
191    /// Adds a child group to this group.
192    pub fn add_child_group(&self, child_name: &str) -> &Self {
193        with_context_mut(|ctx| {
194            // Set parent on child group
195            if let Some(child) = ctx.get_group_mut(child_name) {
196                child.set_parent_group(Some(self.name.clone()));
197            }
198            // Add child reference to this group
199            if let Some(group) = ctx.get_group_mut(&self.name) {
200                group.add_child_group(child_name);
201            }
202        });
203        self
204    }
205
206    /// Removes a child group from this group.
207    pub fn remove_child_group(&self, child_name: &str) -> &Self {
208        with_context_mut(|ctx| {
209            // Remove parent from child group
210            if let Some(child) = ctx.get_group_mut(child_name) {
211                child.set_parent_group(None);
212            }
213            // Remove child reference from this group
214            if let Some(group) = ctx.get_group_mut(&self.name) {
215                group.remove_child_group(child_name);
216            }
217        });
218        self
219    }
220
221    /// Returns the number of structures in this group.
222    #[must_use]
223    pub fn num_structures(&self) -> usize {
224        with_context(|ctx| {
225            ctx.get_group(&self.name)
226                .map_or(0, polyscope_core::Group::num_child_structures)
227        })
228    }
229
230    /// Returns the number of child groups.
231    #[must_use]
232    pub fn num_child_groups(&self) -> usize {
233        with_context(|ctx| {
234            ctx.get_group(&self.name)
235                .map_or(0, polyscope_core::Group::num_child_groups)
236        })
237    }
238}