From d86e3440c4a7f0c69f15edf0f1fb62d7832300c7 Mon Sep 17 00:00:00 2001 From: Lyon Beckers Date: Tue, 5 Sep 2023 22:00:01 -0230 Subject: [PATCH 1/4] add get/set userdata methods to sprite --- src/sprite.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/sprite.rs b/src/sprite.rs index ece33fb..dff687f 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -140,6 +140,19 @@ extern "C" fn get_sprite_collision_response( } impl SpriteInner { + pub fn get_userdata(&mut self) -> Result, Error> { + let ptr = pd_func_caller!((*self.playdate_sprite).getUserdata, self.raw_sprite)? as *mut T; + Ok(unsafe { Box::from_raw(ptr) }) + } + + pub fn set_userdata(&mut self, userdata: T) -> Result<(), Error> { + pd_func_caller!( + (*self.playdate_sprite).setUserdata, + self.raw_sprite, + Box::into_raw(Box::new(userdata)) as *mut core::ffi::c_void + ) + } + pub fn set_use_custom_draw(&mut self) -> Result<(), Error> { self.set_draw_function(unsafe { SPRITE_DRAW.expect("SPRITE_DRAW") }) } @@ -318,6 +331,20 @@ pub struct Sprite { } impl Sprite { + pub fn get_userdata(&mut self) -> Result, Error> { + self.inner + .try_borrow_mut() + .map_err(Error::msg)? + .get_userdata() + } + + pub fn set_userdata(&mut self, userdata: T) -> Result<(), Error> { + self.inner + .try_borrow_mut() + .map_err(Error::msg)? + .set_userdata(userdata) + } + pub fn set_use_custom_draw(&mut self) -> Result<(), Error> { self.inner .try_borrow_mut() From 859c72770a2e2bc02f1c4cbf77165f732f33682d Mon Sep 17 00:00:00 2001 From: Lyon Beckers Date: Fri, 8 Sep 2023 00:05:02 -0230 Subject: [PATCH 2/4] fixed userdata --- src/sprite.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/sprite.rs b/src/sprite.rs index dff687f..272c71d 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -140,16 +140,23 @@ extern "C" fn get_sprite_collision_response( } impl SpriteInner { - pub fn get_userdata(&mut self) -> Result, Error> { - let ptr = pd_func_caller!((*self.playdate_sprite).getUserdata, self.raw_sprite)? as *mut T; - Ok(unsafe { Box::from_raw(ptr) }) + pub fn get_userdata(&mut self) -> Result, Error> { + let ptr = + pd_func_caller!((*self.playdate_sprite).getUserdata, self.raw_sprite)? as *const T; + + let rc = unsafe { Rc::from_raw(ptr) }; + + unsafe { Rc::increment_strong_count(Rc::as_ptr(&rc)) } + Ok(rc) } - pub fn set_userdata(&mut self, userdata: T) -> Result<(), Error> { + pub fn set_userdata(&mut self, userdata: Rc) -> Result<(), Error> { + let ptr = Rc::into_raw(userdata); + pd_func_caller!( (*self.playdate_sprite).setUserdata, self.raw_sprite, - Box::into_raw(Box::new(userdata)) as *mut core::ffi::c_void + ptr as *mut core::ffi::c_void ) } @@ -331,14 +338,14 @@ pub struct Sprite { } impl Sprite { - pub fn get_userdata(&mut self) -> Result, Error> { + pub fn get_userdata(&self) -> Result, Error> { self.inner .try_borrow_mut() .map_err(Error::msg)? .get_userdata() } - pub fn set_userdata(&mut self, userdata: T) -> Result<(), Error> { + pub fn set_userdata(&mut self, userdata: Rc) -> Result<(), Error> { self.inner .try_borrow_mut() .map_err(Error::msg)? From 297ed967252f2d759b8c6606a688656e8a0cd243 Mon Sep 17 00:00:00 2001 From: Lyon Beckers Date: Sat, 9 Sep 2023 16:50:46 -0230 Subject: [PATCH 3/4] added a Userdata trait, use a Rc instead so that it is easier to drop --- src/sprite.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/sprite.rs b/src/sprite.rs index 272c71d..1b89628 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -140,9 +140,12 @@ extern "C" fn get_sprite_collision_response( } impl SpriteInner { - pub fn get_userdata(&mut self) -> Result, Error> { + pub fn get_userdata(&mut self) -> Result>, Error> + where + T: Userdata, + { let ptr = - pd_func_caller!((*self.playdate_sprite).getUserdata, self.raw_sprite)? as *const T; + pd_func_caller!((*self.playdate_sprite).getUserdata, self.raw_sprite)? as *const Box; let rc = unsafe { Rc::from_raw(ptr) }; @@ -150,7 +153,10 @@ impl SpriteInner { Ok(rc) } - pub fn set_userdata(&mut self, userdata: Rc) -> Result<(), Error> { + pub fn set_userdata(&mut self, userdata: Rc>) -> Result<(), Error> + where + T: Userdata, + { let ptr = Rc::into_raw(userdata); pd_func_caller!( @@ -307,8 +313,30 @@ impl SpriteInner { } } +pub trait Userdata {} + impl Drop for SpriteInner { fn drop(&mut self) { + fn free_userdata(sprite: &SpriteInner) -> Result<(), Error> { + let ptr = pd_func_caller!((*sprite.playdate_sprite).getUserdata, sprite.raw_sprite)?; + + if ptr as *const _ == core::ptr::null() { + // No userdata on this sprite, nothing to do + return Ok(()); + } + + let rc = unsafe { Rc::from_raw(ptr as *const Box) }; + + // Just for clarity, we're dropping the rc which will decrease the strong count + drop(rc); + + Ok(()) + } + + if let Err(err) = free_userdata(self) { + log_to_console!("error dropping userdata: {}", err); + } + pd_func_caller_log!((*self.playdate_sprite).freeSprite, self.raw_sprite); unsafe { if let Some(collision_responses) = SPRITE_COLLISION_RESPONSES.as_mut() { @@ -338,14 +366,20 @@ pub struct Sprite { } impl Sprite { - pub fn get_userdata(&self) -> Result, Error> { + pub fn get_userdata(&self) -> Result>, Error> + where + T: Userdata, + { self.inner .try_borrow_mut() .map_err(Error::msg)? .get_userdata() } - pub fn set_userdata(&mut self, userdata: Rc) -> Result<(), Error> { + pub fn set_userdata(&mut self, userdata: Rc>) -> Result<(), Error> + where + T: Userdata, + { self.inner .try_borrow_mut() .map_err(Error::msg)? @@ -529,6 +563,17 @@ impl SpriteManager { ) } + pub fn get_sprite_count(&self) -> Result { + pd_func_caller!((*self.playdate_sprite).getSpriteCount) + } + + pub fn remove_sprite(&self, sprite: &Sprite) -> Result<(), Error> { + pd_func_caller!( + (*self.playdate_sprite).removeSprite, + sprite.inner.borrow().raw_sprite + ) + } + pub fn add_dirty_rect(dirty_rect: LCDRect) -> Result<(), Error> { pd_func_caller!((*Self::get_mut().playdate_sprite).addDirtyRect, dirty_rect) } From 519cb6414baeb08434fcb88e795794150b494769 Mon Sep 17 00:00:00 2001 From: Lyon Beckers Date: Sat, 9 Sep 2023 21:38:27 -0230 Subject: [PATCH 4/4] do not use mut reference for get --- src/sprite.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sprite.rs b/src/sprite.rs index 1b89628..967084c 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -140,7 +140,7 @@ extern "C" fn get_sprite_collision_response( } impl SpriteInner { - pub fn get_userdata(&mut self) -> Result>, Error> + pub fn get_userdata(&self) -> Result>, Error> where T: Userdata, { @@ -370,10 +370,7 @@ impl Sprite { where T: Userdata, { - self.inner - .try_borrow_mut() - .map_err(Error::msg)? - .get_userdata() + self.inner.try_borrow().map_err(Error::msg)?.get_userdata() } pub fn set_userdata(&mut self, userdata: Rc>) -> Result<(), Error>