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