Skip to main content

viewport_lib/resources/scivis/
curve_store.rs

1//! Slot-based storage for pre-uploaded curve GPU data.
2//!
3//! Each store holds GPU data produced by the per-frame upload helpers, keyed
4//! by a typed handle. Per-frame ref items (`PolylineRefItem` and friends) name
5//! a store entry by handle and supply per-frame overrides (model matrix, etc.)
6//! instead of resubmitting the geometry every frame.
7
8use crate::resources::{
9    GlyphGpuData, PointCloudGpuData, PolylineGpuData, SpriteGpuData, StreamtubeGpuData,
10    TensorGlyphGpuData,
11};
12
13macro_rules! curve_store {
14    ($(#[$id_doc:meta])* $id:ident, $store:ident, $data:ty) => {
15        $(#[$id_doc])*
16        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17        pub struct $id(pub(crate) usize);
18
19        impl $id {
20            /// Build an id from a raw slot index.
21            pub fn from_index(index: usize) -> Self { Self(index) }
22            /// The raw slot index.
23            pub fn index(&self) -> usize { self.0 }
24        }
25
26        pub(crate) struct $store {
27            slots: Vec<Option<$data>>,
28            free_list: Vec<usize>,
29        }
30
31        impl $store {
32            pub fn new() -> Self {
33                Self { slots: Vec::new(), free_list: Vec::new() }
34            }
35
36            pub fn insert(&mut self, data: $data) -> $id {
37                if let Some(idx) = self.free_list.pop() {
38                    self.slots[idx] = Some(data);
39                    $id(idx)
40                } else {
41                    let idx = self.slots.len();
42                    self.slots.push(Some(data));
43                    $id(idx)
44                }
45            }
46
47            pub fn get(&self, id: $id) -> Option<&$data> {
48                self.slots.get(id.0)?.as_ref()
49            }
50
51            pub fn replace(&mut self, id: $id, data: $data) -> bool {
52                match self.slots.get_mut(id.0) {
53                    Some(slot) if slot.is_some() => { *slot = Some(data); true }
54                    _ => false,
55                }
56            }
57
58            pub fn remove(&mut self, id: $id) -> bool {
59                if let Some(slot) = self.slots.get_mut(id.0) {
60                    if slot.is_some() {
61                        *slot = None;
62                        self.free_list.push(id.0);
63                        return true;
64                    }
65                }
66                false
67            }
68
69            pub fn contains(&self, id: $id) -> bool {
70                self.get(id).is_some()
71            }
72
73            pub fn len(&self) -> usize {
74                self.slots.iter().filter(|s| s.is_some()).count()
75            }
76        }
77    };
78}
79
80curve_store!(
81    /// Handle to a pre-uploaded polyline produced by
82    /// [`ViewportGpuResources::upload_polyline`](crate::resources::ViewportGpuResources::upload_polyline).
83    PolylineId,
84    PolylineStore,
85    PolylineGpuData
86);
87
88curve_store!(
89    /// Handle to a pre-uploaded streamtube produced by
90    /// [`ViewportGpuResources::upload_streamtube`](crate::resources::ViewportGpuResources::upload_streamtube).
91    StreamtubeId,
92    StreamtubeStore,
93    StreamtubeGpuData
94);
95
96curve_store!(
97    /// Handle to a pre-uploaded tube produced by
98    /// [`ViewportGpuResources::upload_tube`](crate::resources::ViewportGpuResources::upload_tube).
99    TubeId,
100    TubeStore,
101    StreamtubeGpuData
102);
103
104curve_store!(
105    /// Handle to a pre-uploaded ribbon produced by
106    /// [`ViewportGpuResources::upload_ribbon`](crate::resources::ViewportGpuResources::upload_ribbon).
107    RibbonId,
108    RibbonStore,
109    StreamtubeGpuData
110);
111
112curve_store!(
113    /// Handle to a pre-uploaded point cloud produced by
114    /// [`ViewportGpuResources::upload_point_cloud`](crate::resources::ViewportGpuResources::upload_point_cloud).
115    PointCloudId,
116    PointCloudStore,
117    PointCloudGpuData
118);
119
120curve_store!(
121    /// Handle to a pre-uploaded glyph set produced by
122    /// [`ViewportGpuResources::upload_glyph_set`](crate::resources::ViewportGpuResources::upload_glyph_set).
123    GlyphSetId,
124    GlyphSetStore,
125    GlyphGpuData
126);
127
128curve_store!(
129    /// Handle to a pre-uploaded tensor glyph set produced by
130    /// [`ViewportGpuResources::upload_tensor_glyph_set`](crate::resources::ViewportGpuResources::upload_tensor_glyph_set).
131    TensorGlyphSetId,
132    TensorGlyphSetStore,
133    TensorGlyphGpuData
134);
135
136curve_store!(
137    /// Handle to a pre-uploaded sprite set produced by
138    /// [`ViewportGpuResources::upload_sprite_set`](crate::resources::ViewportGpuResources::upload_sprite_set).
139    /// Backs static billboards such as foliage, signage, and light flares.
140    SpriteSetId,
141    SpriteSetStore,
142    SpriteGpuData
143);
144
145curve_store!(
146    /// Handle to a pre-uploaded sprite instance set produced by
147    /// [`ViewportGpuResources::upload_sprite_instance_set`](crate::resources::ViewportGpuResources::upload_sprite_instance_set).
148    /// Backs entity sprites such as NPCs, item drops, and damage numbers.
149    SpriteInstanceSetId,
150    SpriteInstanceSetStore,
151    SpriteGpuData
152);