1use core::marker::PhantomData;
2use core::ops::Deref;
3
4use sys::ffi::LCDSprite;
5use sys::traits::AsRaw;
6
7use crate::{Sprite, SpriteApi, TypedSprite, SpriteRef, AnySprite, SharedSprite, SpriteType};
8use crate::api::{self, Api};
9
10
11impl<UD, Api: api::Api, const FOD: bool> Sprite<UD, Api, FOD> {
13 pub fn into_update_handler<T: SpriteUpdate<Userdata = UD>>(self) -> Handle<FOD, Self, T>
15 where T::Api: Default {
16 Handle::new(self)
17 }
18}
19
20
21pub trait SpriteUpdate: Sized + SpriteType {
22 fn on_update(sprite: &Handle<false, SharedSprite<Self::Userdata, Self::Api>, Self>);
23
24 unsafe extern "C" fn proxy(sprite: *mut LCDSprite)
25 where Self::Api: Default {
26 Self::on_update(&Handle::new_unchanged(SpriteRef::from(sprite).into()))
27 }
28}
29
30
31pub struct Handle<const FOD: bool, T, H>(pub(super) T, PhantomData<H>)
32 where T: TypedSprite + Sized,
33 H: SpriteUpdate;
34
35impl<const FOD: bool, T, H> AnySprite for Handle<FOD, T, H>
36 where T: TypedSprite + Sized,
37 H: SpriteUpdate,
38 T: AnySprite
39{
40}
41impl<const FOD: bool, T, H> SpriteApi for Handle<FOD, T, H>
42 where T: TypedSprite + Sized,
43 H: SpriteUpdate,
44 T: SpriteApi
45{
46 type Api = <T as SpriteApi>::Api;
47
48 fn api(&self) -> Self::Api
49 where Self::Api: Copy {
50 self.0.api()
51 }
52
53 fn api_ref(&self) -> &Self::Api { self.0.api_ref() }
54}
55
56impl<const FOD: bool, T, H> AsRaw for Handle<FOD, T, H>
57 where T: TypedSprite + Sized,
58 H: SpriteUpdate,
59 T: AsRaw
60{
61 type Type = <T as AsRaw>::Type;
62 unsafe fn as_raw(&self) -> *mut Self::Type { self.0.as_raw() }
63}
64
65impl<const FOD: bool, T, H> Handle<FOD, T, H>
66 where T: TypedSprite + Sized,
67 H: SpriteUpdate
68{
69 #[must_use = "Sprite"]
73 pub fn into_inner(self) -> T {
74 let ptr = unsafe { self.0.as_raw() };
75 let f = self.0.api_ref().set_update_function();
76 unsafe { f(ptr, None) };
77 self.0
78 }
79}
80
81
82impl<const FOD: bool, T, H> AsRef<Sprite<T::Userdata, T::Api, FOD>> for Handle<FOD, T, H>
83 where T: TypedSprite + AsRef<Sprite<T::Userdata, T::Api, FOD>>,
84 H: SpriteUpdate
85{
86 fn as_ref(&self) -> &Sprite<T::Userdata, T::Api, FOD> { self.0.as_ref() }
87}
88
89
90impl<const FOD: bool, T, H> AsMut<Sprite<T::Userdata, T::Api, FOD>> for Handle<FOD, T, H>
91 where T: TypedSprite + AsMut<Sprite<T::Userdata, T::Api, FOD>>,
92 H: SpriteUpdate
93{
94 fn as_mut(&mut self) -> &mut Sprite<T::Userdata, T::Api, FOD> { self.0.as_mut() }
95}
96
97
98impl<const FOD: bool, T, H> Deref for Handle<FOD, T, H>
99 where T: TypedSprite + AsRef<Sprite<T::Userdata, T::Api, FOD>>,
100 H: SpriteUpdate
101{
102 type Target = Sprite<T::Userdata, T::Api, FOD>;
103 fn deref(&self) -> &Self::Target { self.0.as_ref() }
104}
105
106
107impl<const FOD: bool, T, H> Handle<FOD, T, H>
108 where T: TypedSprite + SpriteApi,
109 H: SpriteUpdate
110{
111 pub(super) fn new(sprite: T) -> Self
112 where H::Api: Default {
113 let f = sprite.api_ref().set_update_function();
114 unsafe { f(sprite.as_raw(), Some(H::proxy)) };
115 Self::new_unchanged(sprite)
116 }
117
118 fn new_unchanged(sprite: T) -> Self { Self(sprite, PhantomData::<H>) }
119}
120
121
122pub mod l2 {
123 use core::ops::Deref;
124 use core::marker::PhantomData;
125
126 use sys::traits::AsRaw;
127
128 use crate::AnySprite;
129 use crate::Sprite;
130 use crate::SpriteApi;
131 use crate::TypedSprite;
132 use crate::api;
133 use crate::callback::draw;
134 use crate::callback::collision;
135
136 use super::SpriteUpdate;
137
138
139 impl<UD, Api, const FOD: bool, H> collision::Handle<FOD, Sprite<UD, Api, FOD>, H>
140 where Api: api::Api,
141 H: collision::SpriteCollisionResponse
142 {
143 pub fn into_update_handler<T: SpriteUpdate<Userdata = UD>>(
145 self)
146 -> Handle<FOD, Sprite<UD, Api, FOD>, Self, T>
147 where T::Api: Default {
148 Handle::new(self)
149 }
150 }
151
152 impl<UD, Api, const FOD: bool, H> draw::Handle<FOD, Sprite<UD, Api, FOD>, H>
153 where Api: api::Api,
154 H: draw::SpriteDraw
155 {
156 pub fn into_update_handler<T: SpriteUpdate<Userdata = UD>>(
158 self)
159 -> Handle<FOD, Sprite<UD, Api, FOD>, Self, T>
160 where T::Api: Default {
161 Handle::new(self)
162 }
163 }
164
165 impl<UD, Api, const FOD: bool, H, H0>
166 draw::l2::Handle<FOD, Sprite<UD, Api, FOD>, collision::Handle<FOD, Sprite<UD, Api, FOD>, H0>, H>
167 where Api: api::Api,
168 H: draw::SpriteDraw,
169 H0: collision::SpriteCollisionResponse
170 {
171 pub fn into_update_handler<T: SpriteUpdate<Userdata = UD>>(
173 self)
174 -> Handle<FOD, Sprite<UD, Api, FOD>, Self, T>
175 where T::Api: Default {
176 Handle::new(self)
177 }
178 }
179
180 impl<UD, Api, const FOD: bool, H, H0>
181 collision::l2::Handle<FOD, Sprite<UD, Api, FOD>, draw::Handle<FOD, Sprite<UD, Api, FOD>, H0>, H>
182 where Api: api::Api,
183 H: collision::SpriteCollisionResponse,
184 H0: draw::SpriteDraw
185 {
186 pub fn into_update_handler<T: SpriteUpdate<Userdata = UD>>(
188 self)
189 -> Handle<FOD, Sprite<UD, Api, FOD>, Self, T>
190 where T::Api: Default {
191 Handle::new(self)
192 }
193 }
194
195
196 pub struct Handle<const FOD: bool, Sp, T, H>(pub(super) T, PhantomData<Sp>, PhantomData<H>)
197 where T: Sized,
198 Sp: TypedSprite,
199 H: SpriteUpdate;
200
201
202 impl<const FOD: bool, Sp, T, H> AnySprite for Handle<FOD, Sp, T, H>
203 where Sp: TypedSprite,
204 T: AnySprite,
205 H: SpriteUpdate
206 {
207 }
208 impl<const FOD: bool, Sp, T, H> SpriteApi for Handle<FOD, Sp, T, H>
209 where Sp: TypedSprite,
210 T: SpriteApi,
211 H: SpriteUpdate
212 {
213 type Api = <T as SpriteApi>::Api;
214
215 fn api(&self) -> Self::Api
216 where Self::Api: Copy {
217 self.0.api()
218 }
219
220 fn api_ref(&self) -> &Self::Api { self.0.api_ref() }
221 }
222
223 impl<const FOD: bool, Sp, T, H> AsRaw for Handle<FOD, Sp, T, H>
224 where Sp: TypedSprite,
225 T: AsRaw,
226 H: SpriteUpdate
227 {
228 type Type = <T as AsRaw>::Type;
229 unsafe fn as_raw(&self) -> *mut Self::Type { self.0.as_raw() }
230 }
231
232
233 impl<const FOD: bool, Sp, T, H> Handle<FOD, Sp, T, H>
234 where T: AsRef<Sp>,
235 Sp: TypedSprite,
236 H: SpriteUpdate
237 {
238 #[must_use = "Sprite"]
242 pub fn into_inner(self) -> T {
243 use crate::api::Api;
244
245 let ptr = unsafe { self.0.as_ref().as_raw() };
246 let f = self.0.as_ref().api_ref().set_update_function();
247 unsafe { f(ptr, None) };
248 self.0
249 }
250 }
251
252
253 impl<const FOD: bool, Sp, T, H> AsRef<Sprite<Sp::Userdata, Sp::Api, FOD>> for Handle<FOD, Sp, T, H>
254 where T: AsRef<Sprite<Sp::Userdata, Sp::Api, FOD>>,
255 Sp: TypedSprite,
256 H: SpriteUpdate
257 {
258 fn as_ref(&self) -> &Sprite<Sp::Userdata, Sp::Api, FOD> { self.0.as_ref() }
259 }
260
261
262 impl<const FOD: bool, Sp, T, H> Deref for Handle<FOD, Sp, T, H>
263 where T: AsRef<Sprite<Sp::Userdata, Sp::Api, FOD>>,
264 Sp: TypedSprite,
265 H: SpriteUpdate
266 {
267 type Target = Sprite<Sp::Userdata, Sp::Api, FOD>;
268 fn deref(&self) -> &Self::Target { self.0.as_ref() }
269 }
270
271
272 impl<const FOD: bool, Sp, T, H> Handle<FOD, Sp, T, H>
273 where T: AsRef<Sp>,
274 Sp: TypedSprite + SpriteApi,
275 H: SpriteUpdate
276 {
277 pub(super) fn new(sprite: T) -> Self
278 where H::Api: Default {
279 use crate::api::Api;
280
281 let f = sprite.as_ref().api_ref().set_update_function();
282 unsafe { f(sprite.as_ref().as_raw(), Some(H::proxy)) };
283 Self::new_unchanged(sprite)
284 }
285
286 fn new_unchanged(sprite: T) -> Self { Self(sprite, PhantomData::<Sp>, PhantomData::<H>) }
287 }
288}