Skip to content

Commit

Permalink
Api handlers, entry-point and various improvements (#118)
Browse files Browse the repository at this point in the history
* Add event-handler example for sys

* Add update-handler examples for system, improve set_update_callback and Handler

* Improve update-handler examples for system, add update-handler on-trait

* Improve playdate-display API and docs

* improve gfx api,
bump display following prev. commit

* little fix for sound api

* Add hl- example 🎉

* fix `init`/`run` src templates rel to deps (closes #117)
  • Loading branch information
boozook authored Sep 25, 2023
1 parent f6473b8 commit ae7b51d
Show file tree
Hide file tree
Showing 33 changed files with 1,188 additions and 190 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ repository = "https://github.com/boozook/playdate.git"
[workspace.dependencies]
color = { version = "0.1", path = "api/color", package = "playdate-color", default-features = false }
ctrl = { version = "0.1", path = "api/ctrl", package = "playdate-controls", default-features = false }
display = { version = "0.1", path = "api/display", package = "playdate-display", default-features = false }
display = { version = "0.2", path = "api/display", package = "playdate-display", default-features = false }
fs = { version = "0.1", path = "api/fs", package = "playdate-fs", default-features = false }
gfx = { version = "0.2", path = "api/gfx", package = "playdate-graphics", default-features = false }
menu = { version = "0.1", path = "api/menu", package = "playdate-menu", default-features = false }
sound = { version = "0.1", path = "api/sound", package = "playdate-sound", default-features = false }
sprite = { version = "0.1", path = "api/sprite", package = "playdate-sprite", default-features = false }
system = { version = "0.1", path = "api/system", package = "playdate-system", default-features = false }
system = { version = "0.2", path = "api/system", package = "playdate-system", default-features = false }
sys = { version = "0.1", path = "api/sys", package = "playdate-sys", default-features = false }

build = { version = "0.2", path = "support/build", package = "playdate-build", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion api/display/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-display"
version = "0.1.3"
version = "0.2.0"
readme = "README.md"
description = "High-level Display API built on-top of Playdate API"
keywords = ["playdate", "sdk", "api", "gamedev"]
Expand Down
88 changes: 85 additions & 3 deletions api/display/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![cfg_attr(not(test), no_std)]
extern crate sys;

use core::ffi::c_char;
use core::ffi::c_float;
use core::ffi::c_int;
use core::ffi::c_uint;
Expand All @@ -10,6 +9,14 @@ use core::ffi::c_uint;
#[derive(Debug, Clone, Copy)]
pub struct Display<Api = api::Default>(Api);

impl Display<api::Default> {
/// Creates default [`Display`] without type parameter requirement.
///
/// Uses ZST [`api::Default`].
#[allow(non_snake_case)]
pub fn Default() -> Self { Self(Default::default()) }
}

impl<Api: Default + api::Api> Default for Display<Api> {
fn default() -> Self { Self(Default::default()) }
}
Expand All @@ -23,56 +30,117 @@ impl<Api: api::Api> Display<Api> {
}


impl Display<api::Default> {
pub const COLUMNS: u32 = sys::ffi::LCD_COLUMNS;
pub const ROWS: u32 = sys::ffi::LCD_ROWS;
pub const ROW_SIZE: u32 = sys::ffi::LCD_ROWSIZE;
pub const SCREEN_RECT: sys::ffi::LCDRect = sys::ffi::LCDRect { left: 0,
right: 0,
top: Self::COLUMNS as _,
bottom: Self::ROWS as _ };
}


impl<Api: api::Api> Display<Api> {
/// Returns the width of the display, taking the current scale into account;
///
/// e.g., if the scale is `2`, this function returns `200` instead of `400`.
///
/// See also [`Display::COLUMNS`].
///
/// Equivalent to [`sys::ffi::playdate_display::getWidth`]
#[doc(alias = "sys::ffi::playdate_display::getWidth")]
pub fn width(&self) -> c_int {
let f = self.0.get_width();
unsafe { f() }
}

/// Returns the height of the display, taking the current scale into account;
///
/// e.g., if the scale is `2`, this function returns `120` instead of `240`.
///
/// See also [`Display::ROWS`] and [`Display::ROW_SIZE`].
///
/// Equivalent to [`sys::ffi::playdate_display::getHeight`]
#[doc(alias = "sys::ffi::playdate_display::getHeight")]
pub fn height(&self) -> c_int {
let f = self.0.get_height();
unsafe { f() }
}

/// Sets the nominal refresh rate in frames per second.
///
/// Default is 20 fps, the maximum rate supported by the hardware for full-frame updates.
///
/// Equivalent to [`sys::ffi::playdate_display::setRefreshRate`]
#[doc(alias = "sys::ffi::playdate_display::setRefreshRate")]
pub fn set_refresh_rate(&self, rate: c_float) {
let f = self.0.set_refresh_rate();
unsafe { f(rate) }
}

/// If `value` is `true`, the frame buffer is drawn inverted—black instead of white, and vice versa.
///
/// Equivalent to [`sys::ffi::playdate_display::setInverted`]
#[doc(alias = "sys::ffi::playdate_display::setInverted")]
pub fn set_inverted(&self, value: bool) {
let f = self.0.set_inverted();
unsafe { f(value as _) }
}

/// Sets the display scale factor.
///
/// The top-left corner of the frame buffer is scaled up to fill the display;
///
/// e.g., if the scale is set to [`DisplayScale::Quad`],
/// the pixels in rectangle `[0, 100] x [0, 60]` are drawn on the screen as `4 x 4` squares.
///
/// Equivalent to [`sys::ffi::playdate_display::setScale`]
#[doc(alias = "sys::ffi::playdate_display::setScale")]
pub fn set_scale(&self, scale: DisplayScale) { self.set_scale_raw(scale.into()); }

/// Sets the display scale factor.
///
/// Valid values for `scale` are `1`, `2`, `4`, and `8`.
///
/// The top-left corner of the frame buffer is scaled up to fill the display;
/// e.g., if the scale is set to `4`, the pixels in rectangle `[0, 100] x [0, 60]` are drawn on the screen as `4 x 4` squares.
///
/// See also [`Display::set_scale`].
///
/// Equivalent to [`sys::ffi::playdate_display::setScale`]
#[doc(alias = "sys::ffi::playdate_display::setScale")]
pub fn set_scale(&self, scale: c_uint) {
pub fn set_scale_raw(&self, scale: c_uint) {
let f = self.0.set_scale();
unsafe { f(scale) }
}

/// Adds a mosaic effect to the display.
///
/// Valid `x` and `y` values are between `0` and `3`, inclusive.
///
/// Equivalent to [`sys::ffi::playdate_display::setMosaic`]
#[doc(alias = "sys::ffi::playdate_display::setMosaic")]
pub fn set_mosaic(&self, x: c_uint, y: c_uint) {
let f = self.0.set_mosaic();
unsafe { f(x, y) }
}

/// Flips the display on the `x` or `y` axis, or both.
///
/// Equivalent to [`sys::ffi::playdate_display::setFlipped`]
#[doc(alias = "sys::ffi::playdate_display::setFlipped")]
pub fn set_flipped(&self, x: bool, y: bool) {
let f = self.0.set_flipped();
unsafe { f(x as _, y as _) }
}

/// Offsets the display by the given amount.
///
/// Areas outside of the displayed area are filled with the current background color.
///
/// See also [`playdate-graphics::set_background_color`].
///
/// Equivalent to [`sys::ffi::playdate_display::setOffset`]
#[doc(alias = "sys::ffi::playdate_display::setOffset")]
pub fn set_offset(&self, x: c_int, y: c_int) {
Expand All @@ -82,8 +150,22 @@ impl<Api: api::Api> Display<Api> {
}


#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DisplayScale {
Normal = 1,
Double = 2,
Quad = 4,
Eight = 8,
}

impl Into<c_uint> for DisplayScale {
#[inline(always)]
fn into(self) -> c_uint { (self as u8).into() }
}


pub mod api {
use core::ffi::c_char;
use core::ffi::c_float;
use core::ffi::c_int;
use core::ffi::c_uint;
Expand Down
2 changes: 1 addition & 1 deletion api/gfx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-graphics"
version = "0.2.2"
version = "0.2.3"
readme = "README.md"
description = "High-level graphics API built on-top of Playdate API"
keywords = ["playdate", "sdk", "api", "gamedev"]
Expand Down
4 changes: 2 additions & 2 deletions api/gfx/examples/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ impl State {
for (i, code) in RUST.into_iter().enumerate() {
let mut advance = 0;
let (glyph, bitmap_ref) = text::get_page_glyph_with_bitmap(&page, code, &mut advance).unwrap();
let mut char = bitmap_ref.into_bitmap();

let kern = RUST.get(i + 1)
.map(|next| text::get_glyph_kerning(&glyph, code, *next))
.unwrap_or_default();

let w = char.bitmap_data().map(|bd| bd.width).unwrap();
let char = bitmap_ref.into_bitmap();
let w = char.size().map(|(w, h)| w).unwrap();
let x = OFFSET + i as i32 * w;
let y = OFFSET + kern;

Expand Down
26 changes: 26 additions & 0 deletions api/gfx/src/bitmap/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,32 @@ impl<Api: api::Api, const FOD: bool> Bitmap<Api, FOD> {
}


/// Returns `(width, height)` of the bitmap.
///
/// Can return error if there is no bitmap-data or any internal error occurred.
///
/// Calls [`sys::ffi::playdate_graphics::getBitmapData`].
#[doc(alias = "sys::ffi::playdate_graphics::getBitmapData")]
pub fn size(&self) -> Result<(c_int, c_int), Error> {
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut row_bytes: c_int = 0;

let f = self.1.get_bitmap_data();
unsafe {
f(
self.0,
&mut width,
&mut height,
&mut row_bytes,
core::ptr::null_mut(),
core::ptr::null_mut(),
)
};

Ok((width, height))
}

/// Returns mutable borrow of bitmap-data by this bitmap.
///
/// Calls [`sys::ffi::playdate_graphics::getBitmapData`].
Expand Down
7 changes: 2 additions & 5 deletions api/gfx/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,10 @@ pub fn draw_text_cstr(text: &CStr, encoding: StringEncoding, x: c_int, y: c_int)
///
/// Equivalent to [`sys::ffi::playdate_graphics::getTextWidth`].
#[doc(alias = "sys::ffi::playdate_graphics::getTextWidth")]
pub fn get_text_width<S: AsRef<str>>(text: S,
font: Option<&LCDFont>,
tracking: c_int)
-> Result<c_int, NulError> {
pub fn get_text_width<S: AsRef<str>>(text: S, font: Option<&Font>, tracking: c_int) -> Result<c_int, NulError> {
let s = CString::new(text.as_ref())?;
let f = *sys::api!(graphics.getTextWidth);
let font = font.map(|font| font as *const LCDFont as *mut LCDFont)
let font = font.map(|font| unsafe { font.as_raw() })
.unwrap_or(core::ptr::null_mut());
let res = unsafe {
f(
Expand Down
Loading

0 comments on commit ae7b51d

Please sign in to comment.