use std::any::Any; use imgui::DrawData; use crate::common::{Color, Rect}; use crate::framework::context::Context; use crate::framework::error::GameResult; use crate::framework::graphics::{BlendMode, VSyncMode}; use crate::game::Game; #[repr(C)] #[derive(Copy, Clone)] pub struct VertexData { pub position: (f32, f32), pub color: (u8, u8, u8, u8), pub uv: (f32, f32), } #[derive(Copy, Clone, PartialEq)] pub enum BackendShader { /// (scale, t, (frame_x, frame_y)) WaterFill(f32, f32, (f32, f32)), Fill, Texture, } pub trait Backend { fn create_event_loop(&self, ctx: &Context) -> GameResult>; } pub trait BackendEventLoop { fn run(&mut self, game: &mut Game, ctx: &mut Context); fn new_renderer(&self, ctx: *mut Context) -> GameResult>; } pub trait BackendRenderer { fn renderer_name(&self) -> String; fn clear(&mut self, color: Color); fn present(&mut self) -> GameResult; fn set_vsync_mode(&mut self, _mode: VSyncMode) -> GameResult { Ok(()) } fn prepare_draw(&mut self, _width: f32, _height: f32) -> GameResult { Ok(()) } fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult>; fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult>; fn set_blend_mode(&mut self, blend: BlendMode) -> GameResult; fn set_render_target(&mut self, texture: Option<&Box>) -> GameResult; fn draw_rect(&mut self, rect: Rect, color: Color) -> GameResult; fn draw_outline_rect(&mut self, rect: Rect, line_width: usize, color: Color) -> GameResult; fn set_clip_rect(&mut self, rect: Option) -> GameResult; fn imgui(&self) -> GameResult<&mut imgui::Context>; fn imgui_texture_id(&self, texture: &Box) -> GameResult; fn prepare_imgui(&mut self, ui: &imgui::Ui) -> GameResult; fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult; fn supports_vertex_draw(&self) -> bool { false } fn draw_triangle_list( &mut self, vertices: &[VertexData], texture: Option<&Box>, shader: BackendShader, ) -> GameResult; } pub trait BackendTexture { fn dimensions(&self) -> (u16, u16); fn add(&mut self, command: SpriteBatchCommand); fn clear(&mut self); fn draw(&mut self) -> GameResult; fn as_any(&self) -> &dyn Any; } pub trait BackendGamepad { fn set_rumble(&mut self, low_freq: u16, high_freq: u16, duration_ms: u32) -> GameResult; fn instance_id(&self) -> u32; } #[allow(unreachable_code)] pub fn init_backend(headless: bool, size_hint: (u16, u16)) -> GameResult> { if headless { return crate::framework::backend_null::NullBackend::new(); } #[cfg(all(feature = "backend-horizon"))] { return crate::framework::backend_horizon::HorizonBackend::new(); } #[cfg(all(feature = "backend-glutin"))] { return crate::framework::backend_glutin::GlutinBackend::new(); } #[cfg(feature = "backend-sdl")] { return crate::framework::backend_sdl2::SDL2Backend::new(size_hint); } log::warn!("No backend compiled in, using null backend instead."); crate::framework::backend_null::NullBackend::new() } pub enum SpriteBatchCommand { DrawRect(Rect, Rect), DrawRectFlip(Rect, Rect, bool, bool), DrawRectTinted(Rect, Rect, Color), DrawRectFlipTinted(Rect, Rect, bool, bool, Color), }