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);