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            #[allow(dead_code)]
74            pub fn len(&self) -> usize {
75                self.slots.iter().filter(|s| s.is_some()).count()
76            }
77        }
78    };
79}
80
81curve_store!(
82    /// Handle to a pre-uploaded polyline produced by
83    /// [`ViewportGpuResources::upload_polyline`](crate::resources::ViewportGpuResources::upload_polyline).
84    PolylineId,
85    PolylineStore,
86    PolylineGpuData
87);
88
89curve_store!(
90    /// Handle to a pre-uploaded streamtube produced by
91    /// [`ViewportGpuResources::upload_streamtube`](crate::resources::ViewportGpuResources::upload_streamtube).
92    StreamtubeId,
93    StreamtubeStore,
94    StreamtubeGpuData
95);
96
97curve_store!(
98    /// Handle to a pre-uploaded tube produced by
99    /// [`ViewportGpuResources::upload_tube`](crate::resources::ViewportGpuResources::upload_tube).
100    TubeId,
101    TubeStore,
102    StreamtubeGpuData
103);
104
105curve_store!(
106    /// Handle to a pre-uploaded ribbon produced by
107    /// [`ViewportGpuResources::upload_ribbon`](crate::resources::ViewportGpuResources::upload_ribbon).
108    RibbonId,
109    RibbonStore,
110    StreamtubeGpuData
111);
112
113curve_store!(
114    /// Handle to a pre-uploaded point cloud produced by
115    /// [`ViewportGpuResources::upload_point_cloud`](crate::resources::ViewportGpuResources::upload_point_cloud).
116    PointCloudId,
117    PointCloudStore,
118    PointCloudGpuData
119);
120
121curve_store!(
122    /// Handle to a pre-uploaded glyph set produced by
123    /// [`ViewportGpuResources::upload_glyph_set`](crate::resources::ViewportGpuResources::upload_glyph_set).
124    GlyphSetId,
125    GlyphSetStore,
126    GlyphGpuData
127);
128
129curve_store!(
130    /// Handle to a pre-uploaded tensor glyph set produced by
131    /// [`ViewportGpuResources::upload_tensor_glyph_set`](crate::resources::ViewportGpuResources::upload_tensor_glyph_set).
132    TensorGlyphSetId,
133    TensorGlyphSetStore,
134    TensorGlyphGpuData
135);
136
137curve_store!(
138    /// Handle to a pre-uploaded sprite set produced by
139    /// [`ViewportGpuResources::upload_sprite_set`](crate::resources::ViewportGpuResources::upload_sprite_set).
140    /// Backs static billboards such as foliage, signage, and light flares.
141    SpriteSetId,
142    SpriteSetStore,
143    SpriteGpuData
144);
145
146curve_store!(
147    /// Handle to a pre-uploaded sprite instance set produced by
148    /// [`ViewportGpuResources::upload_sprite_instance_set`](crate::resources::ViewportGpuResources::upload_sprite_instance_set).
149    /// Backs entity sprites such as NPCs, item drops, and damage numbers.
150    SpriteInstanceSetId,
151    SpriteInstanceSetStore,
152    SpriteGpuData
153);