-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #159 from boozook/ui/crank-indicator
Add crank-indicator ui component
- Loading branch information
Showing
9 changed files
with
760 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!(); |
Oops, something went wrong.