use crate::{connectors::*, scene::Scene, state::State};
use resolution::current_resolution;
use rscenes_raylib_connector::{
assets::{TraceLogLevel, TraceLogLevelExt},
interface::*,
};
#[derive(Default)]
pub struct Rscenes {
pub title: String,
pub window_size: (i32, i32),
setups: Vec<Box<dyn SetupCallback>>,
scenes: Vec<Box<dyn Scene>>,
}
impl Rscenes {
pub fn add_setup(&mut self, callback: impl SetupCallback) -> &mut Self {
self.setups.push(Box::new(callback));
self
}
pub fn set_init(&mut self, scene: Box<dyn Scene>) -> &mut Self {
self.scenes.push(scene);
self
}
pub fn start(&mut self) {
if self.scenes.is_empty() {
TraceLogLevel::Fatal.log("no initial scene supplied");
}
if let Err(err) = self.setup() {
TraceLogLevel::Fatal.log(format!("loading setup: {:?}", err));
}
let mut reloaded = true;
let plain_connector = PlainConnector;
let connector_3d = Connector3D;
let connector_2d = Connector2D;
let mut track_loaded_scenes: Vec<usize> = Vec::with_capacity(self.scenes.len() + 1);
'mainloop: while !plain_connector.window_should_close() {
let scene = match self.scenes.last_mut() {
Some(scene) => scene,
None => break 'mainloop,
};
if reloaded {
let scene_id = scene.id();
let first_load = !track_loaded_scenes.contains(&scene_id);
if first_load {
track_loaded_scenes.push(scene_id);
if let Err(err) = scene.on_setup(plain_connector) {
TraceLogLevel::Fatal
.log(format!("setting {:?} scene up: {:?}", scene, err));
}
}
if let Err(err) = scene.on_load(plain_connector) {
if first_load {
TraceLogLevel::Fatal
} else {
TraceLogLevel::Error
}
.log(format!("reloading {:?} scene: {:?}", scene, err));
}
reloaded = false;
}
plain_connector.begin_drawing();
match scene.on_update(plain_connector, plain_connector.get_frame_time()) {
Ok(State::Keep) => {
if let Err(err) = scene.draw_2d(connector_2d) {
TraceLogLevel::Error
.log(format!("drawing shapes (2D): {:?} {:?}", scene, err));
}
if let Err(err) = scene.draw_3d(connector_3d) {
TraceLogLevel::Error
.log(format!("drawing models (3D): {:?} {:?}", scene, err));
}
if let Err(err) = scene.draw_hud(connector_2d) {
TraceLogLevel::Error
.log(format!("drawing HUD (2D): {:?} {:?}", scene, err));
}
}
Ok(State::Next(next_scene)) => {
{
if let Err(err) = scene.on_exit(plain_connector) {
TraceLogLevel::Error
.log(format!("exiting {:?} scene: {:?}", scene, err));
}
}
self.scenes.push(next_scene);
reloaded = true;
}
Ok(State::Prev(count)) => {
for _ in 0..count {
if let Some(mut scene) = self.scenes.pop() {
if let Err(err) = scene.on_exit(plain_connector) {
TraceLogLevel::Error
.log(format!("exiting {:?} scene: {:?}", scene, err));
}
}
}
reloaded = true;
}
Ok(State::Quit) => {
if let Err(err) = scene.on_exit(plain_connector) {
TraceLogLevel::Error.log(format!("exiting {:?} scene: {:?}", scene, err));
}
plain_connector.close_window();
break;
}
Err(err) => {
TraceLogLevel::Error.log(format!("updating {:?} scene: {}", scene, err))
}
}
plain_connector.end_drawing();
}
}
pub fn screen_size(&self) -> (i32, i32) {
current_resolution().unwrap_or((800, 600))
}
fn setup(&mut self) -> Result<(), String> {
let connector = PlainConnector;
connector.set_target_fps(60);
let (width, height) = match self.window_size {
(0, 0) => self.screen_size(),
(0, height) => {
let (width, _) = self.screen_size();
(width, height)
}
(width, 0) => {
let (_, height) = self.screen_size();
(width, height)
}
(width, height) => (width, height),
};
connector.init_window(width, height, &self.title);
for callback in self.setups.iter() {
callback(connector)?;
}
Ok(())
}
}
pub trait SetupCallback = Fn(PlainConnector) -> Result<(), String> + 'static;