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