#![cfg_attr(not(test), no_std)]
extern crate sys;
extern crate alloc;
use core::ffi::c_int;
use core::ffi::c_float;
use sys::traits::AsRaw;
use sys::ffi::SpriteQueryInfo;
use sys::ffi::LCDRect;
use sys::ffi::LCDSprite;
pub mod ext;
mod sprite;
pub mod api;
pub mod callback {
pub mod draw;
pub mod update;
pub mod collision;
}
pub mod prelude {
pub use super::sprite::*;
pub use super::api::Api as _;
pub use super::api::Default as DefaultSpriteApi;
pub use super::callback::draw::SpriteDraw;
pub use super::callback::update::SpriteUpdate;
pub use super::callback::collision::SpriteCollisionResponse;
pub use super::{TypedSprite, SpriteApi};
}
pub use sprite::*;
use crate::api::Api;
#[doc(alias = "sys::ffi::playdate_sprite::setAlwaysRedraw")]
pub fn set_always_redraw(value: bool) {
let f = api::Api::set_always_redraw(&api::Default);
unsafe { f(value.into()) }
}
#[doc(alias = "sys::ffi::playdate_sprite::addDirtyRect")]
pub fn add_dirty_rect(rect: LCDRect) {
let f = api::Api::add_dirty_rect(&api::Default);
unsafe { f(rect) }
}
#[doc(alias = "sys::ffi::playdate_sprite::drawSprites")]
pub fn draw_sprites() {
let f = api::Api::draw_sprites(&api::Default);
unsafe { f() }
}
#[doc(alias = "sys::ffi::playdate_sprite::updateAndDrawSprites")]
pub fn update_and_draw_sprites() {
let f = api::Api::update_and_draw_sprites(&api::Default);
unsafe { f() }
}
#[doc(alias = "sys::ffi::playdate_sprite::addSprite")]
pub fn add_sprite(sprite: &impl AnySprite) {
let f = sprite.api_ref().add_sprite();
unsafe { f(sprite.as_raw()) }
}
#[doc(alias = "sys::ffi::playdate_sprite::removeSprite")]
pub fn remove_sprite(sprite: &impl AnySprite) {
let f = sprite.api_ref().remove_sprite();
unsafe { f(sprite.as_raw()) }
}
#[doc(alias = "sys::ffi::playdate_sprite::removeSprites")]
pub fn remove_sprites(sprites: &[impl AnySprite]) {
let mut ptrs = alloc::vec::Vec::with_capacity(sprites.len());
ptrs.extend(sprites.into_iter().map(|sp| unsafe { sp.as_raw() }));
let f = sprites.first()
.map(|sp| sp.api_ref().remove_sprites())
.unwrap_or(api::Default.remove_sprites());
unsafe { f(ptrs.as_mut_ptr(), sprites.len() as _) }
drop(ptrs);
}
#[doc(alias = "sys::ffi::playdate_sprite::removeAllSprites")]
pub fn remove_all_sprites() {
let f = api::Api::remove_all_sprites(&api::Default);
unsafe { f() }
}
#[doc(alias = "sys::ffi::playdate_sprite::getSpriteCount")]
pub fn sprite_count() -> c_int {
let f = api::Api::get_sprite_count(&api::Default);
unsafe { f() }
}
#[doc(alias = "sys::ffi::playdate_sprite::setClipRectsInRange")]
pub fn set_clip_rects_in_range(clip: LCDRect, start_z: c_int, end_z: c_int) {
let f = api::Api::set_clip_rects_in_range(&api::Default);
unsafe { f(clip, start_z, end_z) }
}
#[doc(alias = "sys::ffi::playdate_sprite::clearClipRectsInRange")]
pub fn clear_clip_rects_in_range(start_z: c_int, end_z: c_int) {
let f = api::Api::clear_clip_rects_in_range(&api::Default);
unsafe { f(start_z, end_z) }
}
#[doc(alias = "sys::ffi::playdate_sprite::resetCollisionWorld")]
pub fn reset_collision_world() {
let f = api::Api::reset_collision_world(&api::Default);
unsafe { f() }
}
#[doc(alias = "sys::ffi::playdate_sprite::querySpritesAtPoint")]
pub fn query_sprites_at_point(x: c_float, y: c_float) -> &'static [SpriteRef] {
let mut len: c_int = 0;
let api = api::Default;
let f = api.query_sprites_at_point();
let ptr = unsafe { f(x, y, &mut len) };
let slice = unsafe { core::slice::from_raw_parts(ptr, len as _) };
unsafe { core::mem::transmute(slice) }
}
#[doc(alias = "sys::ffi::playdate_sprite::querySpritesInRect")]
pub fn query_sprites_in_rect(x: c_float, y: c_float, width: c_float, height: c_float) -> &'static [SpriteRef] {
let mut len: c_int = 0;
let f = api::Api::query_sprites_in_rect(&api::Default);
let ptr = unsafe { f(x, y, width, height, &mut len) };
let slice = unsafe { core::slice::from_raw_parts(ptr, len as _) };
unsafe { core::mem::transmute(slice) }
}
#[doc(alias = "sys::ffi::playdate_sprite::querySpritesAlongLine")]
pub fn query_sprites_along_line(x1: c_float, y1: c_float, x2: c_float, y2: c_float) -> &'static [SpriteRef] {
let mut len: c_int = 0;
let f = api::Api::query_sprites_along_line(&api::Default);
let ptr = unsafe { f(x1, y1, x2, y2, &mut len) };
let slice = unsafe { core::slice::from_raw_parts(ptr, len as _) };
unsafe { core::mem::transmute(slice) }
}
#[doc(alias = "sys::ffi::playdate_sprite::querySpriteInfoAlongLine")]
pub fn query_sprite_info_along_line(x1: c_float,
y1: c_float,
x2: c_float,
y2: c_float)
-> &'static [SpriteQueryInfo] {
let mut len: c_int = 0;
let f = api::Api::query_sprite_info_along_line(&api::Default);
let ptr = unsafe { f(x1, y1, x2, y2, &mut len) };
unsafe { core::slice::from_raw_parts(ptr, len as _) }
}
#[doc(alias = "sys::ffi::playdate_sprite::allOverlappingSprites")]
pub fn all_overlapping_sprites() -> &'static [SpriteRef] {
let f = api::Api::all_overlapping_sprites(&api::Default);
let mut len: c_int = 0;
let ptr = unsafe { f(&mut len) };
let slice = unsafe { core::slice::from_raw_parts(ptr, len as _) };
unsafe { core::mem::transmute(slice) }
}
pub trait AnySprite: AsRaw<Type = LCDSprite> + SpriteApi {}
impl<T: AnySprite> AnySprite for &'_ T {}
pub trait SpriteApi {
type Api: api::Api;
fn api(&self) -> Self::Api
where Self::Api: Copy;
fn api_ref(&self) -> &Self::Api;
}
impl<T: SpriteApi> SpriteApi for &'_ T {
type Api = T::Api;
fn api(&self) -> Self::Api
where Self::Api: Copy {
(*self).api()
}
fn api_ref(&self) -> &Self::Api { (*self).api_ref() }
}
pub trait TypedSprite: AsRaw<Type = LCDSprite> + SpriteApi {
type Userdata;
const FREE_ON_DROP: bool = true;
}
pub trait SpriteType {
type Api: api::Api;
type Userdata;
const FREE_ON_DROP: bool = false;
}
impl<T: TypedSprite> SpriteType for T {
type Api = <T as SpriteApi>::Api;
type Userdata = <T as TypedSprite>::Userdata;
const FREE_ON_DROP: bool = <T as TypedSprite>::FREE_ON_DROP;
}