playdate_sprite/callback/
update.rs

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
11// This is mostly probably should be implemented for OwnedSprite only.
12impl<UD, Api: api::Api, const FOD: bool> Sprite<UD, Api, FOD> {
13	/// Sets the update function for the this sprite.
14	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	/// - Unregister inner callback for sprite
70	/// - Unwrap, return the underlying sprite
71	/// - Remove the update handler
72	#[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		/// Sets the update function for the this sprite.
144		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		/// Sets the update function for the this sprite.
157		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		/// Sets the update function for the this sprite.
172		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		/// Sets the update function for the this sprite.
187		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		/// - Unregister inner callback for sprite
239		/// - Unwrap, return the underlying sprite
240		/// - Remove the collision response handler
241		#[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}