openxr_session/
openxr_session.rs1#![allow(clippy::print_stdout, clippy::enum_glob_use)]
7
8use ready_active_safe::prelude::*;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
15enum SessionMode {
16 Idle,
18 Ready,
20 Synchronized,
22 Visible,
24 Focused,
26 Stopping,
28}
29
30impl core::fmt::Display for SessionMode {
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 write!(f, "{self:?}")
33 }
34}
35
36#[derive(Debug)]
38enum XrEvent {
39 SessionStateChanged(SessionMode),
41 FrameReady,
43 RequestExit,
45}
46
47#[derive(Debug, PartialEq)]
49enum XrCommand {
50 PrepareResources,
52 BeginFrameLoop,
54 SubmitFrame,
56 PollInput,
58 ReleaseResources,
60 EndSession,
62}
63
64struct XrSession;
65
66impl Machine for XrSession {
67 type Mode = SessionMode;
68 type Event = XrEvent;
69 type Command = XrCommand;
70
71 fn initial_mode(&self) -> SessionMode {
72 SessionMode::Idle
73 }
74
75 fn on_event(
76 &self,
77 mode: &Self::Mode,
78 event: &Self::Event,
79 ) -> Decision<Self::Mode, Self::Command> {
80 use SessionMode::*;
81 use XrCommand::*;
82 use XrEvent::*;
83
84 match (mode, event) {
85 (Idle, SessionStateChanged(Ready)) => transition(Ready).emit(PrepareResources),
86 (Ready, SessionStateChanged(Synchronized)) => {
87 transition(Synchronized).emit(BeginFrameLoop)
88 }
89 (Synchronized, SessionStateChanged(Visible)) => transition(Visible),
90 (Visible, SessionStateChanged(Focused)) => transition(Focused).emit(PollInput),
91 (Focused, FrameReady) => stay().emit_all([SubmitFrame, PollInput]),
92 (Visible, FrameReady) => stay().emit(SubmitFrame),
93 (mode, RequestExit) if *mode != Idle && *mode != Stopping => {
94 transition(Stopping).emit_all([ReleaseResources, EndSession])
95 }
96 _ => ignore(),
97 }
98 }
99}
100
101fn main() {
102 let session = XrSession;
103 let mut mode = session.initial_mode();
104
105 let events = [
106 XrEvent::SessionStateChanged(SessionMode::Ready),
107 XrEvent::SessionStateChanged(SessionMode::Synchronized),
108 XrEvent::SessionStateChanged(SessionMode::Visible),
109 XrEvent::SessionStateChanged(SessionMode::Focused),
110 XrEvent::FrameReady,
111 XrEvent::FrameReady,
112 XrEvent::RequestExit,
113 ];
114
115 for event in &events {
116 let decision = session.decide(&mode, event);
117 println!("{mode:?} + {event:?} => {decision}");
118
119 let (next_mode, commands) = decision.apply(mode);
120 if !commands.is_empty() {
121 println!(" commands: {commands:?}");
122 }
123
124 mode = next_mode;
125 }
126
127 assert_eq!(mode, SessionMode::Stopping);
128}