Skip to main content

polyscope_core/
structure.rs

1//! Structure trait and related types.
2//!
3//! A [`Structure`] represents a geometric object in the scene, such as a point cloud,
4//! surface mesh, or curve network.
5
6use std::any::Any;
7
8use glam::{Mat4, Vec3};
9
10use crate::pick::PickResult;
11use crate::quantity::Quantity;
12
13/// A geometric object that can be visualized in polyscope.
14///
15/// Structures are the primary objects managed by polyscope. Each structure has:
16/// - A unique name within its type
17/// - A transform matrix for positioning in the scene
18/// - Visibility state
19/// - Methods for rendering and UI building
20pub trait Structure: Any + Send + Sync {
21    /// Returns a reference to self as `Any` for downcasting.
22    fn as_any(&self) -> &dyn Any;
23
24    /// Returns a mutable reference to self as `Any` for downcasting.
25    fn as_any_mut(&mut self) -> &mut dyn Any;
26    /// Returns the unique name of this structure.
27    fn name(&self) -> &str;
28
29    /// Returns the type name of this structure (e.g., "`PointCloud`", "`SurfaceMesh`").
30    fn type_name(&self) -> &'static str;
31
32    /// Returns the axis-aligned bounding box in world coordinates.
33    ///
34    /// Returns `None` if the structure has no spatial extent.
35    fn bounding_box(&self) -> Option<(Vec3, Vec3)>;
36
37    /// Returns a characteristic length scale for this structure.
38    fn length_scale(&self) -> f32;
39
40    /// Returns the current model transform matrix.
41    fn transform(&self) -> Mat4;
42
43    /// Sets the model transform matrix.
44    fn set_transform(&mut self, transform: Mat4);
45
46    /// Returns whether this structure is currently visible.
47    fn is_enabled(&self) -> bool;
48
49    /// Sets the visibility of this structure.
50    fn set_enabled(&mut self, enabled: bool);
51
52    /// Draws this structure to the scene.
53    ///
54    /// Called during the main render pass.
55    fn draw(&self, ctx: &mut dyn RenderContext);
56
57    /// Draws this structure for picking/selection.
58    ///
59    /// Called during the pick render pass.
60    fn draw_pick(&self, ctx: &mut dyn RenderContext);
61
62    /// Builds the `ImGui` UI for this structure.
63    fn build_ui(&mut self, ui: &dyn std::any::Any);
64
65    /// Builds the `ImGui` UI for a picked element.
66    fn build_pick_ui(&self, ui: &dyn std::any::Any, pick: &PickResult);
67
68    /// Refreshes GPU resources after data changes.
69    fn refresh(&mut self);
70
71    /// Centers the camera on this structure's bounding box.
72    fn center_bounding_box(&mut self) {
73        // Default implementation - can be overridden
74    }
75
76    /// Resets the transform to identity.
77    fn reset_transform(&mut self) {
78        self.set_transform(Mat4::IDENTITY);
79    }
80
81    /// Clears all GPU resources (render data, pick buffers, etc.).
82    ///
83    /// After calling this, the structure's GPU resources will be lazily
84    /// re-initialized on the next render frame. This is needed when switching
85    /// wgpu devices (e.g., between headless render calls).
86    fn clear_gpu_resources(&mut self) {
87        // Default no-op; each structure type overrides this
88    }
89
90    /// Returns the material name for this structure (e.g., "clay", "wax").
91    #[allow(clippy::unnecessary_literal_bound)]
92    fn material(&self) -> &str {
93        "clay"
94    }
95
96    /// Sets the material for this structure by name.
97    fn set_material(&mut self, _material: &str) {
98        // Default no-op; structures that support materials override this
99    }
100}
101
102/// A structure that can have quantities attached to it.
103pub trait HasQuantities: Structure {
104    /// Adds a quantity to this structure.
105    fn add_quantity(&mut self, quantity: Box<dyn Quantity>);
106
107    /// Gets a quantity by name.
108    fn get_quantity(&self, name: &str) -> Option<&dyn Quantity>;
109
110    /// Gets a mutable quantity by name.
111    fn get_quantity_mut(&mut self, name: &str) -> Option<&mut Box<dyn Quantity>>;
112
113    /// Removes a quantity by name.
114    fn remove_quantity(&mut self, name: &str) -> Option<Box<dyn Quantity>>;
115
116    /// Returns all quantities attached to this structure.
117    fn quantities(&self) -> &[Box<dyn Quantity>];
118
119    /// Returns the number of quantities attached.
120    fn num_quantities(&self) -> usize {
121        self.quantities().len()
122    }
123}
124
125/// Trait for render context - will be implemented in polyscope-render.
126///
127/// This is a placeholder trait to avoid circular dependencies.
128pub trait RenderContext: Send + Sync {}