gloss_renderer/plugin_manager/
plugins.rs

1/// TODO Technically we also need to add [no-mangle] as in here:
2/// <https://docs.rust-embedded.org/book/interoperability/rust-with-c.html>
3/// However since we only create the mangles by the same rust compiler it should
4/// work fine. This no-mangle is mostly when you try to export the function to C
5/// which does not mangle the names in the same way as Rust. Currently since we
6/// don't target C++, we can mangle the functions as normal and therefore avoid
7/// collision in names of function.
8use crate::scene::Scene;
9use crate::viewer_dummy::RunnerDummy;
10use crate::{
11    viewer::{GpuResources, Runner},
12    viewer_headless::RunnerHeadless,
13};
14
15use gloss_utils::abi_stable_aliases::std_types::{RDuration, RString, RVec, Tuple2};
16#[cfg(not(target_arch = "wasm32"))]
17use gloss_utils::abi_stable_aliases::StableAbi;
18
19use super::GpuSystem;
20use super::{
21    runner::RunnerState,
22    systems::{EventSystem, GuiSystem, LogicSystem, SystemMetadata},
23};
24
25#[repr(C)]
26#[cfg_attr(not(target_arch = "wasm32"), derive(StableAbi))]
27pub enum Event {
28    DroppedFile(RString),
29}
30/// Trait for defining a plugin for gloss, to be used when defining Plugins in external crates
31/// This is FFI safe
32pub trait Plugin {
33    fn event_systems(&self) -> Vec<EventSystem>;
34    fn logic_systems(&self) -> Vec<LogicSystem>;
35    fn gui_systems(&self) -> Vec<GuiSystem>;
36    fn autorun(&self) -> bool;
37}
38
39/// Trait for defining an internal plugin for gloss, to be used by Plugins within gloss
40/// Not FFI safe since it is used within gloss
41pub(crate) trait InternalPlugin {
42    // fn event_systems(&self) -> Vec<EventSystem>;
43    // fn logic_systems(&self) -> Vec<LogicSystem>;
44    // fn gui_systems(&self) -> Vec<GuiSystem>;
45    fn gpu_systems(&self) -> Vec<GpuSystem>;
46    fn autorun(&self) -> bool;
47}
48
49#[repr(C)]
50#[cfg_attr(not(target_arch = "wasm32"), derive(StableAbi))]
51pub struct Plugins {
52    pub event_systems: RVec<Tuple2<EventSystem, SystemMetadata>>,
53    pub logic_systems: RVec<Tuple2<LogicSystem, SystemMetadata>>,
54    pub gui_systems: RVec<Tuple2<GuiSystem, SystemMetadata>>,
55}
56
57impl Default for Plugins {
58    fn default() -> Self {
59        Self {
60            event_systems: RVec::new(),
61            logic_systems: RVec::new(),
62            gui_systems: RVec::new(),
63        }
64    }
65}
66impl Plugins {
67    pub fn new() -> Self {
68        Self {
69            event_systems: RVec::new(),
70            logic_systems: RVec::new(),
71            gui_systems: RVec::new(),
72        }
73    }
74    #[allow(clippy::needless_update)]
75    pub fn insert_plugin<T: Plugin + 'static>(&mut self, plugin: &T) {
76        for sys in plugin.event_systems().iter() {
77            let metadata = SystemMetadata {
78                autorun: plugin.autorun(),
79                ..Default::default()
80            };
81            self.event_systems.push(Tuple2(sys.clone(), metadata));
82        }
83        for sys in plugin.logic_systems().iter() {
84            let metadata = SystemMetadata {
85                autorun: plugin.autorun(),
86                ..Default::default()
87            };
88            self.logic_systems.push(Tuple2(sys.clone(), metadata));
89        }
90        for sys in plugin.gui_systems().iter() {
91            let metadata = SystemMetadata {
92                autorun: plugin.autorun(),
93                ..Default::default()
94            };
95            self.gui_systems.push(Tuple2(sys.clone(), metadata));
96        }
97    }
98
99    pub fn run_logic_systems(&mut self, gpu_res: &mut GpuResources, scene: &mut Scene, runner: &mut Runner, autorun_flag: bool) {
100        let mut runner_state = RunnerState::from(runner);
101
102        // gpu_res.gpu.device().poll(wgpu::Maintain::Wait);
103
104        for system_and_metadata in self.logic_systems.iter_mut() {
105            let metadata = &mut system_and_metadata.1;
106            let sys = &system_and_metadata.0;
107            if metadata.autorun == autorun_flag {
108                let func = sys.f;
109
110                //run and time the function
111                let now = wasm_timer::Instant::now();
112                func(scene, &mut runner_state);
113                // gpu_res.gpu.device().poll(wgpu::Maintain::Wait); // Sync
114                metadata.execution_time = RDuration::from(now.elapsed());
115            }
116        }
117        runner_state.to(runner);
118
119        if runner_state.request_redraw {
120            gpu_res.request_redraw();
121        }
122    }
123
124    pub fn run_logic_systems_headless(&mut self, scene: &mut Scene, runner: &mut RunnerHeadless, autorun_flag: bool) {
125        let mut runner_state = RunnerState::from_headless(runner);
126        for system_and_metadata in self.logic_systems.iter_mut() {
127            let metadata = &mut system_and_metadata.1;
128            let sys = &system_and_metadata.0;
129            if metadata.autorun == autorun_flag {
130                let func = sys.f;
131
132                //run and time the function
133                let now = wasm_timer::Instant::now();
134                func(scene, &mut runner_state);
135                metadata.execution_time = RDuration::from(now.elapsed());
136            }
137        }
138        runner_state.to_headless(runner);
139    }
140
141    //TODO in an ideal worl this should exist, since the ViewerDummy and RunnerDummy shouldn't exist
142    pub fn run_logic_systems_dummy(&mut self, scene: &mut Scene, runner: &mut RunnerDummy, autorun_flag: bool) {
143        let mut runner_state = RunnerState::from_dummy(runner);
144        for system_and_metadata in self.logic_systems.iter_mut() {
145            let metadata = &mut system_and_metadata.1;
146            let sys = &system_and_metadata.0;
147            if metadata.autorun == autorun_flag {
148                let func = sys.f;
149
150                //run and time the function
151                let now = wasm_timer::Instant::now();
152                func(scene, &mut runner_state);
153                metadata.execution_time = RDuration::from(now.elapsed());
154            }
155        }
156        runner_state.to_dummy(runner);
157    }
158
159    pub fn try_handle_event(&self, scene: &mut Scene, runner: &mut Runner, event: &Event) -> bool {
160        let mut runner_state = RunnerState::from(runner);
161        let mut handled = false;
162        for system_and_metadata in self.event_systems.iter() {
163            let sys = &system_and_metadata.0;
164            let func = sys.f;
165            handled |= func(scene, &mut runner_state, event);
166        }
167        runner_state.to(runner);
168        handled
169    }
170}
171
172pub(crate) struct InternalPlugins {
173    pub gpu_systems: RVec<Tuple2<GpuSystem, SystemMetadata>>,
174}
175
176impl Default for InternalPlugins {
177    fn default() -> Self {
178        Self { gpu_systems: RVec::new() }
179    }
180}
181impl InternalPlugins {
182    pub fn new() -> Self {
183        Self { gpu_systems: RVec::new() }
184    }
185    #[allow(clippy::needless_update)]
186    pub fn insert_plugin<T: InternalPlugin + 'static>(&mut self, plugin: &T) {
187        for sys in plugin.gpu_systems().iter() {
188            let metadata = SystemMetadata {
189                autorun: plugin.autorun(),
190                ..Default::default()
191            };
192            self.gpu_systems.push(Tuple2(sys.clone(), metadata));
193        }
194    }
195
196    pub fn run_gpu_systems(&mut self, gpu_res: &mut GpuResources, scene: &mut Scene, runner: &mut Runner, autorun_flag: bool) {
197        let mut runner_state = RunnerState::from(runner);
198
199        for system_and_metadata in self.gpu_systems.iter_mut() {
200            let metadata = &mut system_and_metadata.1;
201            let sys = &system_and_metadata.0;
202            if metadata.autorun == autorun_flag {
203                let func = sys.f;
204
205                //run and time the function
206                let now = wasm_timer::Instant::now();
207                func(scene, &mut runner_state, gpu_res);
208                metadata.execution_time = RDuration::from(now.elapsed());
209            }
210        }
211        runner_state.to(runner);
212
213        if runner_state.request_redraw {
214            gpu_res.request_redraw();
215        }
216    }
217}