1mod priority;
2
3use core::mem;
4
5pub use self::priority::Priority;
6use crate::{
7 PadAxisUpdate,
8 bindings::{Gui_Add, Gui_Remove, InputDevice, Screen, ScreenVTABLE, cc_string},
9 std_types::{Box, c_char, c_int, c_void},
10};
11
12pub struct OwnedScreen {
13 pub screen: Box<Screen>,
14 vtable: Box<ScreenVTABLE>,
15 added: bool,
16}
17
18impl OwnedScreen {
19 pub fn new() -> Self {
20 let mut vtable = Box::new(ScreenVTABLE {
21 Init: Some(Init),
22 Update: Some(Update),
23 Free: Some(Free),
24 Render: Some(Render),
25 BuildMesh: Some(BuildMesh),
26 HandlesInputDown: Some(HandlesInputDown),
27 OnInputUp: Some(OnInputUp),
28 HandlesKeyPress: Some(HandlesKeyPress),
29 HandlesTextChanged: Some(HandlesTextChanged),
30 HandlesPointerDown: Some(HandlesPointerDown),
31 OnPointerUp: Some(OnPointerUp),
32 HandlesPointerMove: Some(HandlesPointerMove),
33 HandlesMouseScroll: Some(HandlesMouseScroll),
34 Layout: Some(Layout),
35 ContextLost: Some(ContextLost),
36 ContextRecreated: Some(ContextRecreated),
37 HandlesPadAxis: Some(HandlesPadAxis),
38 });
39
40 let screen = Box::new(unsafe {
41 let mut screen: Screen = mem::zeroed();
42 screen.VTABLE = vtable.as_mut();
43 screen
44 });
45
46 Self {
47 screen,
48 vtable,
49 added: false,
50 }
51 }
52
53 pub fn add<T: Into<Priority>>(&mut self, priority: T) {
54 if self.added {
55 return;
56 }
57 unsafe {
58 Gui_Add(self.screen.as_mut(), priority.into().to_u8() as _);
60 }
61 self.added = true;
62 }
63
64 pub fn remove(&mut self) {
65 if self.added {
66 unsafe {
67 Gui_Remove(self.screen.as_mut());
68 }
69 self.added = false;
70 }
71 }
72
73 pub fn on_init(&mut self, f: unsafe extern "C" fn(elem: *mut c_void)) -> &mut Self {
75 self.vtable.as_mut().Init = Some(f);
76 self
77 }
78
79 pub fn on_update(
81 &mut self,
82 f: unsafe extern "C" fn(elem: *mut c_void, delta: f32),
83 ) -> &mut Self {
84 self.vtable.as_mut().Update = Some(f);
85 self
86 }
87
88 pub fn on_free(&mut self, f: unsafe extern "C" fn(elem: *mut c_void)) -> &mut Self {
90 self.vtable.as_mut().Free = Some(f);
91 self
92 }
93
94 pub fn on_render(
96 &mut self,
97 f: unsafe extern "C" fn(elem: *mut c_void, delta: f32),
98 ) -> &mut Self {
99 self.vtable.as_mut().Render = Some(f);
100 self
101 }
102
103 pub fn on_build_mesh(&mut self, f: unsafe extern "C" fn(elem: *mut c_void)) -> &mut Self {
105 self.vtable.as_mut().BuildMesh = Some(f);
106 self
107 }
108
109 pub fn on_handles_input_down(
111 &mut self,
112 f: unsafe extern "C" fn(elem: *mut c_void, key: c_int, device: *mut InputDevice) -> c_int,
113 ) -> &mut Self {
114 self.vtable.as_mut().HandlesInputDown = Some(f);
115 self
116 }
117
118 pub fn on_on_input_up(
120 &mut self,
121 f: unsafe extern "C" fn(elem: *mut c_void, key: c_int, device: *mut InputDevice),
122 ) -> &mut Self {
123 self.vtable.as_mut().OnInputUp = Some(f);
124 self
125 }
126
127 pub fn on_handles_key_press(
129 &mut self,
130 f: unsafe extern "C" fn(elem: *mut c_void, keyChar: c_char) -> c_int,
131 ) -> &mut Self {
132 self.vtable.as_mut().HandlesKeyPress = Some(f);
133 self
134 }
135
136 pub fn on_handles_text_changed(
139 &mut self,
140 f: unsafe extern "C" fn(elem: *mut c_void, str: *const cc_string) -> c_int,
141 ) -> &mut Self {
142 self.vtable.as_mut().HandlesTextChanged = Some(f);
143 self
144 }
145
146 pub fn on_handles_pointer_down(
148 &mut self,
149 f: unsafe extern "C" fn(elem: *mut c_void, id: c_int, x: c_int, y: c_int) -> c_int,
150 ) -> &mut Self {
151 self.vtable.as_mut().HandlesPointerDown = Some(f);
152 self
153 }
154
155 pub fn on_on_pointer_up(
157 &mut self,
158 f: unsafe extern "C" fn(elem: *mut c_void, id: c_int, x: c_int, y: c_int),
159 ) -> &mut Self {
160 self.vtable.as_mut().OnPointerUp = Some(f);
161 self
162 }
163
164 pub fn on_handles_pointer_move(
166 &mut self,
167 f: unsafe extern "C" fn(elem: *mut c_void, id: c_int, x: c_int, y: c_int) -> c_int,
168 ) -> &mut Self {
169 self.vtable.as_mut().HandlesPointerMove = Some(f);
170 self
171 }
172
173 pub fn on_handles_mouse_scroll(
175 &mut self,
176 f: unsafe extern "C" fn(elem: *mut c_void, delta: f32) -> c_int,
177 ) -> &mut Self {
178 self.vtable.as_mut().HandlesMouseScroll = Some(f);
179 self
180 }
181
182 pub fn on_layout(&mut self, f: unsafe extern "C" fn(elem: *mut c_void)) -> &mut Self {
184 self.vtable.as_mut().Layout = Some(f);
185 self
186 }
187
188 pub fn on_context_lost(&mut self, f: unsafe extern "C" fn(elem: *mut c_void)) -> &mut Self {
190 self.vtable.as_mut().ContextLost = Some(f);
191 self
192 }
193
194 pub fn on_context_recreated(
196 &mut self,
197 f: unsafe extern "C" fn(elem: *mut c_void),
198 ) -> &mut Self {
199 self.vtable.as_mut().ContextRecreated = Some(f);
200 self
201 }
202
203 pub fn on_handles_pad_axis(
205 &mut self,
206 f: unsafe extern "C" fn(elem: *mut c_void, upd: *mut PadAxisUpdate) -> c_int,
207 ) -> &mut Self {
208 self.vtable.as_mut().HandlesPadAxis = Some(f);
209 self
210 }
211}
212
213impl Default for OwnedScreen {
214 fn default() -> Self {
215 Self::new()
216 }
217}
218
219impl Drop for OwnedScreen {
220 fn drop(&mut self) {
221 #[cfg(not(test))]
222 self.remove();
223 }
224}
225
226unsafe extern "C" fn Init(_elem: *mut c_void) {}
228unsafe extern "C" fn Update(_elem: *mut c_void, _delta: f32) {}
229unsafe extern "C" fn Free(_elem: *mut c_void) {}
230unsafe extern "C" fn Render(_elem: *mut c_void, _delta: f32) {}
231unsafe extern "C" fn BuildMesh(_elem: *mut c_void) {}
232unsafe extern "C" fn HandlesInputDown(
233 _elem: *mut c_void,
234 _key: c_int,
235 _device: *mut InputDevice,
236) -> c_int {
237 0
238}
239unsafe extern "C" fn OnInputUp(_elem: *mut c_void, _key: c_int, _device: *mut InputDevice) {}
240unsafe extern "C" fn HandlesKeyPress(_elem: *mut c_void, _keyChar: c_char) -> c_int {
241 0
242}
243unsafe extern "C" fn HandlesTextChanged(_elem: *mut c_void, _str: *const cc_string) -> c_int {
244 0
245}
246unsafe extern "C" fn HandlesPointerDown(
247 _elem: *mut c_void,
248 _id: c_int,
249 _x: c_int,
250 _y: c_int,
251) -> c_int {
252 0
253}
254unsafe extern "C" fn OnPointerUp(_elem: *mut c_void, _id: c_int, _x: c_int, _y: c_int) {}
255unsafe extern "C" fn HandlesPointerMove(
256 _elem: *mut c_void,
257 _id: c_int,
258 _x: c_int,
259 _y: c_int,
260) -> c_int {
261 0
262}
263unsafe extern "C" fn HandlesMouseScroll(_elem: *mut c_void, _delta: f32) -> c_int {
264 0
265}
266unsafe extern "C" fn Layout(_elem: *mut c_void) {}
267unsafe extern "C" fn ContextLost(_elem: *mut c_void) {}
268unsafe extern "C" fn ContextRecreated(_elem: *mut c_void) {}
269unsafe extern "C" fn HandlesPadAxis(_elem: *mut c_void, _upd: *mut PadAxisUpdate) -> c_int {
270 0
271}
272
273#[test]
274fn test_screen() {
275 extern "C" fn init(_elem: *mut c_void) {
276 }
278
279 let _screen = OwnedScreen::new().on_init(init);
280 let mut screen = OwnedScreen::new();
281 screen.on_init(init);
282}