#![allow(clippy::print_stdout, clippy::enum_glob_use)]
use ready_active_safe::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
enum SessionMode {
Idle,
Ready,
Synchronized,
Visible,
Focused,
Stopping,
}
impl core::fmt::Display for SessionMode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug)]
enum XrEvent {
SessionStateChanged(SessionMode),
FrameReady,
RequestExit,
}
#[derive(Debug, PartialEq)]
enum XrCommand {
PrepareResources,
BeginFrameLoop,
SubmitFrame,
PollInput,
ReleaseResources,
EndSession,
}
struct XrSession;
impl Machine for XrSession {
type Mode = SessionMode;
type Event = XrEvent;
type Command = XrCommand;
fn initial_mode(&self) -> SessionMode {
SessionMode::Idle
}
fn on_event(
&self,
mode: &Self::Mode,
event: &Self::Event,
) -> Decision<Self::Mode, Self::Command> {
use SessionMode::*;
use XrCommand::*;
use XrEvent::*;
match (mode, event) {
(Idle, SessionStateChanged(Ready)) => transition(Ready).emit(PrepareResources),
(Ready, SessionStateChanged(Synchronized)) => {
transition(Synchronized).emit(BeginFrameLoop)
}
(Synchronized, SessionStateChanged(Visible)) => transition(Visible),
(Visible, SessionStateChanged(Focused)) => transition(Focused).emit(PollInput),
(Focused, FrameReady) => stay().emit_all([SubmitFrame, PollInput]),
(Visible, FrameReady) => stay().emit(SubmitFrame),
(mode, RequestExit) if *mode != Idle && *mode != Stopping => {
transition(Stopping).emit_all([ReleaseResources, EndSession])
}
_ => ignore(),
}
}
}
fn main() {
let session = XrSession;
let mut mode = session.initial_mode();
let events = [
XrEvent::SessionStateChanged(SessionMode::Ready),
XrEvent::SessionStateChanged(SessionMode::Synchronized),
XrEvent::SessionStateChanged(SessionMode::Visible),
XrEvent::SessionStateChanged(SessionMode::Focused),
XrEvent::FrameReady,
XrEvent::FrameReady,
XrEvent::RequestExit,
];
for event in &events {
let decision = session.decide(&mode, event);
println!("{mode:?} + {event:?} => {decision}");
let (next_mode, commands) = decision.apply(mode);
if !commands.is_empty() {
println!(" commands: {commands:?}");
}
mode = next_mode;
}
assert_eq!(mode, SessionMode::Stopping);
}