#[cfg(doc)]
use crate::RunFrame;
use crate::is;
use crate::{
RunApp, RunBackend, RunControl, RunDriverError, RunDriverFrameError, RunPhase, RunPresent,
RunRender, RunStep, Runtime, RuntimeTick,
};
#[doc = crate::_tags!(runtime)]
#[doc = crate::_doc_meta!{location("run")}]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct RunDriver<T> {
runtime: Runtime<T>,
}
#[rustfmt::skip]
impl<T> RunDriver<T> {
pub const fn new(runtime: Runtime<T>) -> Self { Self { runtime } }
pub const fn runtime(&self) -> &Runtime<T> { &self.runtime }
pub const fn runtime_mut(&mut self) -> &mut Runtime<T> { &mut self.runtime }
pub const fn tick(&self) -> RuntimeTick { self.runtime.tick() }
pub const fn phase(&self) -> RunPhase { self.runtime.phase() }
pub const fn can_advance(&self) -> bool { self.runtime.can_advance() }
pub const fn start(&mut self) -> bool { self.runtime.transition(RunPhase::Running) }
pub const fn stop(&mut self) -> bool { self.runtime.transition(RunPhase::Stopped) }
}
impl<T> RunDriver<T> {
pub fn step<B, A>(
&mut self,
backend: &mut B,
app: &mut A,
events: &mut [A::Event],
) -> Result<RunControl, RunDriverError<B::Error, A::Error>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
{
if !self.runtime.can_advance() {
return Err(RunDriverError::InvalidPhase(self.runtime.phase()));
}
let written = backend.collect_events(events).map_err(RunDriverError::Backend)?;
let step = RunStep::new(self.runtime.tick(), self.runtime.phase(), &events[..written]);
let control = app.run_step(step).map_err(RunDriverError::App)?;
match control {
RunControl::Continue => self.runtime.tick_once(),
RunControl::Stop => {
self.runtime.transition(RunPhase::Stopped);
}
}
Ok(control)
}
pub fn run<B, A>(
&mut self,
backend: &mut B,
app: &mut A,
events: &mut [A::Event],
) -> Result<(), RunDriverError<B::Error, A::Error>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
{
self.start();
while self.runtime.can_advance() {
is! { matches!(self.step(backend, app, events)?, RunControl::Stop), break }
}
Ok(())
}
}
impl<T> RunDriver<T> {
pub fn step_frame<B, A, R, P, S: ?Sized, RE, PE>(
&mut self,
backend: &mut B,
app: &mut A,
renderer: &mut R,
presenter: &mut P,
scene: &S,
events: &mut [A::Event],
) -> Result<RunControl, RunDriverFrameError<B::Error, A::Error, RE, PE>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
for<'a> R: RunRender<S, A::Event, B::Context<'a>, Error = RE>,
for<'a> P: RunPresent<
A::Event,
B::Context<'a>,
Input<'a> = <R as RunRender<S, A::Event, B::Context<'a>>>::Output<'a>,
Error = PE,
>,
{
crate::_run_driver_step_run_frame_body!(@check
self.runtime, backend, app, renderer, presenter, scene(scene), events, control,
self.runtime.tick_once(), self.runtime.transition(RunPhase::Stopped));
Ok(control)
}
pub fn run_frame<B, A, R, P, S: ?Sized, RE, PE>(
&mut self,
backend: &mut B,
app: &mut A,
renderer: &mut R,
presenter: &mut P,
scene: &S,
events: &mut [A::Event],
) -> Result<(), RunDriverFrameError<B::Error, A::Error, RE, PE>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
for<'a> R: RunRender<S, A::Event, B::Context<'a>, Error = RE>,
for<'a> P: RunPresent<
A::Event,
B::Context<'a>,
Input<'a> = <R as RunRender<S, A::Event, B::Context<'a>>>::Output<'a>,
Error = PE,
>,
{
self.start();
while self.runtime.can_advance() {
crate::_run_driver_step_run_frame_body!(
self.runtime,
backend,
app,
renderer,
presenter,
scene(scene),
events,
control,
self.runtime.tick_once(),
self.runtime.transition(RunPhase::Stopped),
break
);
}
Ok(())
}
}
impl<T> RunDriver<T> {
pub fn step_frame_from_app<B, A, R, P, S: ?Sized, Q, RE, PE>(
&mut self,
backend: &mut B,
app: &mut A,
renderer: &mut R,
presenter: &mut P,
scene_of: Q,
events: &mut [A::Event],
) -> Result<RunControl, RunDriverFrameError<B::Error, A::Error, RE, PE>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
Q: for<'a> Fn(&'a A) -> &'a S,
for<'a> R: RunRender<S, A::Event, B::Context<'a>, Error = RE>,
for<'a> P: RunPresent<
A::Event,
B::Context<'a>,
Input<'a> = <R as RunRender<S, A::Event, B::Context<'a>>>::Output<'a>,
Error = PE,
>,
{
crate::_run_driver_step_run_frame_body!(@check
self.runtime, backend, app, renderer, presenter, scene_of(scene_of), events, control,
self.runtime.tick_once(), self.runtime.transition(RunPhase::Stopped));
Ok(control)
}
pub fn run_frame_from_app<B, A, R, P, S: ?Sized, Q, RE, PE>(
&mut self,
backend: &mut B,
app: &mut A,
renderer: &mut R,
presenter: &mut P,
scene_of: Q,
events: &mut [A::Event],
) -> Result<(), RunDriverFrameError<B::Error, A::Error, RE, PE>>
where
B: RunBackend<Event = A::Event>,
A: RunApp,
Q: for<'a> Fn(&'a A) -> &'a S,
for<'a> R: RunRender<S, A::Event, B::Context<'a>, Error = RE>,
for<'a> P: RunPresent<
A::Event,
B::Context<'a>,
Input<'a> = <R as RunRender<S, A::Event, B::Context<'a>>>::Output<'a>,
Error = PE,
>,
{
self.start();
while self.runtime.can_advance() {
crate::_run_driver_step_run_frame_body!(
self.runtime,
backend,
app,
renderer,
presenter,
scene_of(scene_of),
events,
control,
self.runtime.tick_once(),
self.runtime.transition(RunPhase::Stopped),
break
);
}
Ok(())
}
}