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::{
10    viewer::{GpuResources, Runner},
11    viewer_headless::RunnerHeadless,
12};
13
14use gloss_utils::abi_stable_aliases::std_types::{RDuration, RString, RVec, Tuple2};
15#[cfg(not(target_arch = "wasm32"))]
16use gloss_utils::abi_stable_aliases::StableAbi;
17
18use super::{
19    runner::RunnerState,
20    systems::{EventSystem, GuiSystem, LogicSystem, SystemMetadata},
21};
22
23#[repr(C)]
24#[cfg_attr(not(target_arch = "wasm32"), derive(StableAbi))]
25pub enum Event {
26    DroppedFile(RString),
27}
28
29pub trait Plugin {
30    fn event_systems(&self) -> Vec<EventSystem>;
31    fn logic_systems(&self) -> Vec<LogicSystem>;
32    fn gui_systems(&self) -> Vec<GuiSystem>;
33    fn autorun(&self) -> bool;
34}
35
36#[repr(C)]
37#[cfg_attr(not(target_arch = "wasm32"), derive(StableAbi))]
38pub struct Plugins {
39    pub event_systems: RVec<Tuple2<EventSystem, SystemMetadata>>,
40    pub logic_systems: RVec<Tuple2<LogicSystem, SystemMetadata>>,
41    pub gui_systems: RVec<Tuple2<GuiSystem, SystemMetadata>>,
42}
43impl Default for Plugins {
44    fn default() -> Self {
45        Self {
46            event_systems: RVec::new(),
47            logic_systems: RVec::new(),
48            gui_systems: RVec::new(),
49        }
50    }
51}
52impl Plugins {
53    pub fn new() -> Self {
54        Self {
55            event_systems: RVec::new(),
56            logic_systems: RVec::new(),
57            gui_systems: RVec::new(),
58        }
59    }
60    #[allow(clippy::needless_update)]
61    pub fn insert_plugin<T: Plugin + 'static>(&mut self, plugin: &T) {
62        for sys in plugin.event_systems().iter() {
63            let metadata = SystemMetadata {
64                autorun: plugin.autorun(),
65                ..Default::default()
66            };
67            self.event_systems.push(Tuple2(sys.clone(), metadata));
68        }
69        for sys in plugin.logic_systems().iter() {
70            let metadata = SystemMetadata {
71                autorun: plugin.autorun(),
72                ..Default::default()
73            };
74            self.logic_systems.push(Tuple2(sys.clone(), metadata));
75        }
76        for sys in plugin.gui_systems().iter() {
77            let metadata = SystemMetadata {
78                autorun: plugin.autorun(),
79                ..Default::default()
80            };
81            self.gui_systems.push(Tuple2(sys.clone(), metadata));
82        }
83    }
84    pub fn run_logic_systems(&mut self, gpu_res: &mut GpuResources, scene: &mut Scene, runner: &mut Runner, autorun_flag: bool) {
85        let mut runner_state = RunnerState::from(runner);
86
87        // gpu_res.gpu.device().poll(wgpu::Maintain::Wait);
88
89        for system_and_metadata in self.logic_systems.iter_mut() {
90            let metadata = &mut system_and_metadata.1;
91            let sys = &system_and_metadata.0;
92            if metadata.autorun == autorun_flag {
93                let func = sys.f;
94
95                //run and time the function
96                let now = wasm_timer::Instant::now();
97                func(scene, &mut runner_state);
98                // gpu_res.gpu.device().poll(wgpu::Maintain::Wait); // Sync
99                metadata.execution_time = RDuration::from(now.elapsed());
100            }
101        }
102        runner_state.to(runner);
103
104        if runner_state.request_redraw {
105            gpu_res.request_redraw();
106        }
107    }
108
109    pub fn run_logic_systems_headless(&mut self, scene: &mut Scene, runner: &mut RunnerHeadless, autorun_flag: bool) {
110        let mut runner_state = RunnerState::from_headless(runner);
111        for system_and_metadata in self.logic_systems.iter_mut() {
112            let metadata = &mut system_and_metadata.1;
113            let sys = &system_and_metadata.0;
114            if metadata.autorun == autorun_flag {
115                let func = sys.f;
116
117                //run and time the function
118                let now = wasm_timer::Instant::now();
119                func(scene, &mut runner_state);
120                metadata.execution_time = RDuration::from(now.elapsed());
121            }
122        }
123        runner_state.to_headless(runner);
124    }
125
126    pub fn try_handle_event(&self, scene: &mut Scene, runner: &mut Runner, event: &Event) -> bool {
127        let mut runner_state = RunnerState::from(runner);
128        let mut handled = false;
129        for system_and_metadata in self.event_systems.iter() {
130            let sys = &system_and_metadata.0;
131            let func = sys.f;
132            handled |= func(scene, &mut runner_state, event);
133        }
134        runner_state.to(runner);
135        handled
136    }
137}