Skip to content

Commit

Permalink
Merge pull request #159 from boozook/ui/crank-indicator
Browse files Browse the repository at this point in the history
Add crank-indicator ui component
  • Loading branch information
boozook authored Oct 5, 2023
2 parents 310a344 + fed9527 commit 8c2d09c
Show file tree
Hide file tree
Showing 9 changed files with 760 additions and 3 deletions.
15 changes: 14 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = [
"cargo",
"api/*",
"support/*",
# "components/*"
"components/*"
]
default-members = ["cargo", "support/tool", "support/bindgen"]
exclude = ["cargo/tests/crates/**/*"]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ This project allows you to create games for the [Playdate handheld gaming system
* [Modular low- & high- level API][api-dir]
- with [examples][ctrl-examples-dir]
* __All the parts of API are accumulated in [One Crate][playdate-crate]__ ([git][playdate-crate-git])
* UI components
- [crank-indicator][crank-indicator-gh] (port from [lua version][crank-indicator-lua]), requires SDK 2.1

Welcome to [discussions][] and [issues][] for any questions and suggestions.
Take a look at [videos](#demo) or [do something great](#usage).


[crank-indicator-gh]: https://github.com/boozook/playdate/tree/main/components/crank-indicator
[crank-indicator-lua]: https://sdk.play.date/Inside%20Playdate.html#C-ui.crankIndicator


## Prerequisites

Follow the instructions for:
Expand Down
2 changes: 1 addition & 1 deletion api/sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-sys"
version = "0.2.6"
version = "0.2.7"
build = "src/build.rs"
readme = "README.md"
description = "Low-level Playdate API bindings"
Expand Down
99 changes: 99 additions & 0 deletions components/crank-indicator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
[package]
name = "playdate-ui-crank-indicator"
version = "0.1.0"
readme = "README.md"
description = "Crank Indicator UI component."
edition.workspace = true
license.workspace = true
authors.workspace = true
homepage.workspace = true
repository.workspace = true


[features]
default = [
"sys/default",
"gfx/default",
"display/default",
"sprite/default",
"system/default",
]

# playdate-sys features, should be shared because it's build configuration:

bindgen-runtime = [
"sys/bindgen-runtime",
"gfx/bindgen-runtime",
"display/bindgen-runtime",
"sprite/bindgen-runtime",
"system/bindgen-runtime",
]
bindgen-static = [
"sys/bindgen-static",
"gfx/bindgen-static",
"display/bindgen-static",
"sprite/bindgen-static",
"system/bindgen-static",
]

bindings-derive-debug = [
"sys/bindings-derive-debug",
"gfx/bindings-derive-debug",
"display/bindings-derive-debug",
"sprite/bindings-derive-debug",
"system/bindings-derive-debug",
]


[dependencies]
sys = { workspace = true, default-features = false }
system = { workspace = true, default-features = false }
display = { workspace = true, default-features = false }
# feature `sdk_2_1` not used really, it's just because linked assets exists only in SDK starting from 2.1.
gfx = { workspace = true, default-features = false, features = ["sdk_2_1"] }
sprite = { workspace = true, default-features = false, features = ["sdk_2_1"] }


[dev-dependencies]
ctrl = { workspace = true, default-features = false }
menu = { workspace = true, default-features = false }


[[example]]
name = "example"
crate-type = ["dylib", "staticlib"]
path = "examples/example.rs"
required-features = [
"sys/lang-items",
"sys/entry-point",
"sys/try-trait-v2",
"system/try-trait-v2",
]


[package.metadata.playdate]
bundle-id = "rs.playdate.ui.crank.indicator"

[package.metadata.playdate.assets]
"ui/crank-ind/" = "${PLAYDATE_SDK_PATH}/CoreLibs/assets/crank/*.png"


[package.metadata.docs.rs]
all-features = false
features = [
"sys/bindings-derive-default",
"sys/bindings-derive-eq",
"sys/bindings-derive-copy",
"bindings-derive-debug",
"sys/bindings-derive-hash",
"sys/bindings-derive-ord",
"sys/bindings-derive-partialeq",
"sys/bindings-derive-partialord",
]
rustdoc-args = ["--cfg", "docsrs", "--show-type-layout"]
default-target = "thumbv7em-none-eabihf"
cargo-args = [
"-Zunstable-options",
"-Zrustdoc-scrape-examples",
"-Zbuild-std=core,alloc",
]
30 changes: 30 additions & 0 deletions components/crank-indicator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Playdate Crank-Indicator Alert

Requires SDK 2.1.

Optimized port of [official lua version][crank-indicator-lua], implemented as sprite.

> Small system-styled indicator, alerting the player that this game will use the crank.
<img src="https://github.com/boozook/playdate/assets/888526/1a0cce5d-7e0b-471d-85ad-19fa1dcd9fc3" align="right">

See [examples][crank-indicator-examples] to learn how to use.
```rust
use playdate_ui_crank_indicator::CrankIndicator;
use playdate_display::DisplayScale;
use playdate_sprite::add_sprite;

let crank = CrankIndicator::new(DisplayScale::Normal)?;
add_sprite(&crank);
```


[crank-indicator-gh]: https://github.com/boozook/playdate/tree/main/components/crank-indicator
[crank-indicator-examples]: https://github.com/boozook/playdate/tree/main/components/crank-indicator/examples
[crank-indicator-lua]: https://sdk.play.date/Inside%20Playdate.html#C-ui.crankIndicator



- - -

This software is not sponsored or supported by Panic.
25 changes: 25 additions & 0 deletions components/crank-indicator/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Examples


There is one example that demonstrates `CrankIndicator` in various modes and environments.

Use controls to change:
- `<-` & `->` arrows to change global render offset
- `^` & `` arrows to change global render scale factor
- use system menu to change framerate


![example](https://github.com/boozook/playdate/assets/888526/70fe1d74-4cea-4fd4-ab2b-8e56d178c3b7)


# How to run

```bash
cargo playdate run -p=playdate-ui-crank-indicator --example=example --features=sys/lang-items,sys/entry-point,sys/try-trait-v2,system/try-trait-v2
```

More information how to use [cargo-playdate][] in help: `cargo playdate --help`.



[cargo-playdate]: https://crates.io/crates/cargo-playdate
149 changes: 149 additions & 0 deletions components/crank-indicator/examples/example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#![no_std]
#[macro_use]
extern crate alloc;

#[macro_use]
extern crate sys;
extern crate playdate_ui_crank_indicator as ui;

use core::ffi::*;
use core::ptr::NonNull;

use sys::EventLoopCtrl;
use sys::ffi::PlaydateAPI;
use ctrl::buttons::PDButtonsExt;
use display::DisplayScale;
use menu::OptionsMenuItem;
use ui::CrankIndicator;
use system::prelude::*;


/// App state
struct State {
/// system draw offset
offset: (c_int, c_int),
/// system scale mode
scale: DisplayScale,
/// custom system menu
fps: OptionsMenuItem<bool, menu::api::Cache, true>,

/// our neat indicator
crank: Option<CrankIndicator>,

// cached endpoints
system: system::System<system::api::Cache>,
display: display::Display<display::api::Cache>,
gfx: gfx::Graphics<gfx::api::Cache>,
btns: ctrl::peripherals::Buttons<ctrl::api::Cache>,
}

impl State {
fn new() -> Result<Self, gfx::error::ApiError> {
fn fps_changed(value: &mut bool) { *value = true }

let fps = OptionsMenuItem::new("FPS", ["20", "50", "Inf"], Some(fps_changed), false).unwrap();

let crank = CrankIndicator::new(DisplayScale::Normal)?;
sprite::add_sprite(&crank);

Ok(Self { offset: (0, 0),
scale: DisplayScale::Normal,
crank: crank.into(),
fps,
gfx: gfx::Graphics::new(),
system: system::System::new(),
display: display::Display::new(),
btns: ctrl::peripherals::Buttons::new() })
}


/// Updates the state
fn update(&mut self) -> UpdateCtrl {
sprite::update_and_draw_sprites();

// save current scale to compare
let old_scale = self.scale;

// react to input
let buttons = self.btns.get();
if buttons.released.right() {
self.offset.0 += 6;
self.offset.1 += 2;
self.gfx.set_draw_offset(self.offset.0, self.offset.1);
} else if buttons.released.left() {
self.offset.0 -= 6;
self.offset.1 -= 2;
self.gfx.set_draw_offset(self.offset.0, self.offset.1);
} else if buttons.released.up() {
self.scale = match self.scale {
DisplayScale::Normal => DisplayScale::Double,
DisplayScale::Double => DisplayScale::Quad,
DisplayScale::Quad => DisplayScale::Eight,
DisplayScale::Eight => DisplayScale::Eight,
};
self.display.set_scale(self.scale);
} else if buttons.released.down() {
self.scale = match self.scale {
DisplayScale::Normal => DisplayScale::Normal,
DisplayScale::Double => DisplayScale::Normal,
DisplayScale::Quad => DisplayScale::Double,
DisplayScale::Eight => DisplayScale::Quad,
};
self.display.set_scale(self.scale);
}

// create or remove indicator
if buttons.released.a() {
self.crank.take();
let crank = CrankIndicator::new(self.scale)?;
sprite::add_sprite(&crank);
self.crank = crank.into();
} else if buttons.released.b() {
self.crank.take();
}

// update changed scale for indicator
if old_scale != self.scale {
self.crank.as_mut().map(|crank| crank.set_scale(self.scale));
}

// update frame rate if changed
self.fps.get_userdata().filter(|v| **v).map(|value| {
let fps = match self.fps.selected_option() {
0 => 20.,
1 => 50.,
_ => 0.,
};
self.display.set_refresh_rate(fps);
*value = false;
});

// draw state (offset, scale, fps)
self.gfx
.draw_text(format!("{}x, {:?}", self.scale, self.offset), 18, 0)?;
self.system.draw_fps(0, 0);

UpdateCtrl::Continue
}
}


#[no_mangle]
fn event_handler(_: NonNull<PlaydateAPI>, event: SystemEvent, _: u32) -> EventLoopCtrl {
// Ignore any other events, just for this minimalistic example
if !matches!(event, SystemEvent::Init) {
return EventLoopCtrl::Continue;
}

let state = State::new()?;
state.display.set_refresh_rate(20.);

let system = state.system;
system.set_update_callback_boxed(State::update, state);

EventLoopCtrl::Continue
}


// Needed for debug build
ll_symbols!();
Loading

0 comments on commit 8c2d09c

Please sign in to comment.