Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for updating state in serial message callback #375

Merged
5 changes: 5 additions & 0 deletions api/system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ required-features = ["sys/entry-point", "sys/lang-items"]
name = "set-serial-message-callback"
crate-type = ["dylib", "staticlib"]
path = "examples/set-serial-message-callback.rs"

[[example]]
name = "update-state-in-serial-message-callback"
crate-type = ["dylib", "staticlib"]
path = "examples/update-state-in-serial-message-callback.rs"
required-features = ["sys/entry-point", "sys/lang-items"]

[package.metadata.playdate]
Expand Down
2 changes: 2 additions & 0 deletions api/system/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ cargo playdate run -p=playdate-system --example=handler-boxed --features=sys/lan
cargo playdate run -p=playdate-system --example=handler-pinned --features=sys/lang-items,sys/entry-point

cargo playdate run -p=playdate-system --example=set-serial-message-callback --features=sys/lang-items,sys/entry-point

cargo playdate run -p=playdate-system --example=update-state-in-serial-message-callback --features=sys/lang-items,sys/entry-point
```

More information how to use [cargo-playdate][] in help: `cargo playdate --help`.
Expand Down
82 changes: 82 additions & 0 deletions api/system/examples/update-state-in-serial-message-callback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#![no_std]
extern crate alloc;

#[macro_use]
extern crate sys;
extern crate playdate_system as system;

use alloc::string::String;
use core::ptr::NonNull;

use sys::EventLoopCtrl;
use sys::ffi::*;
use system::System;
use system::event::SystemEventExt as _;
use system::prelude::*;

struct State {
initialized: bool,
latest_message: Option<String>,
}

impl State {
fn new() -> Self {
Self { initialized: false,
latest_message: None }
}

/// System event handler
fn event(&'static mut self, event: SystemEvent) -> EventLoopCtrl {
match event {
SystemEvent::Init => {
System::Default().set_serial_message_callback(Some(|msg| {
self.latest_message = Some(msg);
}));

// Verify that `set_serial_message_callback` doesn't prevent us from
// updating other parts of `State`
self.initialized = true;

println!("Game init complete");
},
_ => {},
}
EventLoopCtrl::Continue
}
}

impl Update for State {
fn update(&mut self) -> UpdateCtrl {
if let Some(latest_message) = self.latest_message.clone() {
println!("Latest message: {:#?}", latest_message);
self.latest_message = None;
}
boozook marked this conversation as resolved.
Show resolved Hide resolved
UpdateCtrl::Continue
}
}

/// Entry point
#[no_mangle]
pub fn event_handler(_api: NonNull<PlaydateAPI>, event: SystemEvent, _sim_key_code: u32) -> EventLoopCtrl {
pub static mut STATE: Option<State> = None;

if unsafe { STATE.is_none() } {
let state = State::new();
unsafe { STATE = Some(state) }
}

// We call `set_update_handler` here because it requires (mutably) borrowing
// all of `State`.
//
// If we were to do this inside of `event` it would prevent us from being able
// to (mutably) borrow any of `State`, which means we couldn't update any
// state inside of our `set_serial_message_callback` closure.
if event == SystemEvent::Init {
unsafe { STATE.as_mut().expect("impossible").set_update_handler() }
boozook marked this conversation as resolved.
Show resolved Hide resolved
}

unsafe { STATE.as_mut().expect("impossible").event(event) }
boozook marked this conversation as resolved.
Show resolved Hide resolved
}

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