diff --git a/build.rs b/build.rs index 989e72a..fd45ada 100644 --- a/build.rs +++ b/build.rs @@ -9,8 +9,7 @@ fn linking_raylib() { } #[cfg(feature = "no_link_raylib")] -fn linking_raylib() { -} +fn linking_raylib() {} fn main() { linking_raylib(); diff --git a/src/agnostic_interface.rs b/src/agnostic_interface.rs index ca1e777..0c09bda 100644 --- a/src/agnostic_interface.rs +++ b/src/agnostic_interface.rs @@ -41,6 +41,7 @@ pub trait MusicInterface { fn pause(&mut self) -> Result<(), String>; fn stop(&mut self) -> Result<(), String>; fn set_loop(&mut self, loop_enable: bool) -> Result<(), String>; + fn update(&mut self) -> Result<(), String>; } pub trait CameraInterface { diff --git a/src/agnostic_interface/raylib_impl.rs b/src/agnostic_interface/raylib_impl.rs index 957e814..9faa892 100644 --- a/src/agnostic_interface/raylib_impl.rs +++ b/src/agnostic_interface/raylib_impl.rs @@ -7,65 +7,310 @@ mod ffi { include!(concat!(env!("OUT_DIR"), "/raylib_bindings.rs")); } -use super::GameInterface; +use std::{ + cell::RefCell, + collections::HashMap, + ffi::CString, + os::raw::{c_char, c_int}, + rc::Rc, +}; + +use super::{FontInterface, GameInterface, ImageInterface, MusicInterface, SoundInterface}; + +fn fqcolor_to_color(c: crate::faux_quicksilver::Color) -> ffi::Color { + ffi::Color { + r: c.r, + g: c.g, + b: c.b, + a: c.a, + } +} + +#[derive(Clone, Debug)] +struct RaylibImage { + image: ffi::Image, +} + +#[derive(Clone, Debug)] +struct RaylibImageHandler { + image: Rc, +} + +impl ImageInterface for RaylibImageHandler { + fn draw( + &mut self, + x: f32, + y: f32, + color: crate::faux_quicksilver::Color, + ) -> Result<(), String> { + todo!() + } + + fn draw_sub( + &mut self, + sub_rect: crate::faux_quicksilver::Rectangle, + x: f32, + y: f32, + color: crate::faux_quicksilver::Color, + ) -> Result<(), String> { + todo!() + } + + fn draw_transform( + &mut self, + x: f32, + y: f32, + color: crate::faux_quicksilver::Color, + transform: crate::faux_quicksilver::Transform, + ) -> Result<(), String> { + todo!() + } + + fn draw_sub_transform( + &mut self, + sub_rect: crate::faux_quicksilver::Rectangle, + x: f32, + y: f32, + color: crate::faux_quicksilver::Color, + transform: crate::faux_quicksilver::Transform, + ) -> Result<(), String> { + todo!() + } + + fn get_w(&self) -> usize { + todo!() + } + + fn get_h(&self) -> usize { + todo!() + } + + fn get_wh_rect(&self) -> crate::faux_quicksilver::Rectangle { + todo!() + } +} + +#[derive(Clone, Debug)] +struct RaylibFont { + font: ffi::Font, +} + +#[derive(Clone, Debug)] +struct RaylibFontHandler { + font: Rc, +} + +impl FontInterface for RaylibFontHandler { + fn draw( + &mut self, + s: &str, + size: u32, + x: f32, + y: f32, + color: crate::faux_quicksilver::Color, + ) -> Result<(), String> { + todo!() + } +} + +#[derive(Clone, Debug)] +struct RaylibSound { + sound: ffi::Sound, +} + +#[derive(Clone, Debug)] +struct RaylibSoundHandler { + sound: Rc, +} + +impl SoundInterface for RaylibSoundHandler { + fn play(&mut self, vol: f32) -> Result<(), String> { + unsafe { + ffi::PlaySound(self.sound.sound); + } + Ok(()) + } +} + +#[derive(Clone, Debug)] +struct RaylibMusic { + music: ffi::Music, +} + +impl RaylibMusic { + pub fn update(&mut self) { + unsafe { + ffi::UpdateMusicStream(self.music); + } + } +} + +#[derive(Clone, Debug)] +struct RaylibMusicHandler { + music: Rc>, +} + +impl MusicInterface for RaylibMusicHandler { + fn play(&mut self, vol: f32) -> Result<(), String> { + unsafe { + ffi::SetMusicVolume(self.music.borrow().music, vol); + ffi::PlayMusicStream(self.music.borrow().music); + } + Ok(()) + } + + fn pause(&mut self) -> Result<(), String> { + unsafe { + ffi::PauseMusicStream(self.music.borrow().music); + } + Ok(()) + } + + fn stop(&mut self) -> Result<(), String> { + unsafe { + ffi::StopMusicStream(self.music.borrow().music); + } + Ok(()) + } + + fn set_loop(&mut self, loop_enable: bool) -> Result<(), String> { + self.music.borrow_mut().music.looping = loop_enable; + Ok(()) + } + + fn update(&mut self) -> Result<(), String> { + self.music.borrow_mut().update(); + Ok(()) + } +} struct RaylibGame { - width: f32, - height: f32, + images: HashMap>, + fonts: HashMap>, + sounds: HashMap>, + music: HashMap>>, } impl RaylibGame { - pub fn new_boxed(width: f32, height: f32) -> Box { + pub fn new_boxed(width: u32, height: u32) -> Box { + unsafe { + let string = "One and All LD45\0"; + ffi::InitWindow( + width as c_int, + height as c_int, + string.as_ptr() as *const c_char, + ); + } Box::new(Self { - width, - height, + images: HashMap::new(), + fonts: HashMap::new(), + sounds: HashMap::new(), + music: HashMap::new(), }) } } +impl Drop for RaylibGame { + fn drop(&mut self) { + unsafe { + for (_, image) in &self.images { + ffi::UnloadImage(image.image); + } + for (_, font) in &self.fonts { + ffi::UnloadFont(font.font); + } + for (_, sound) in &self.sounds { + ffi::UnloadSound(sound.sound); + } + for (_, music) in &self.music { + ffi::UnloadMusicStream(music.borrow().music); + } + ffi::CloseWindow(); + } + } +} + impl GameInterface for RaylibGame { fn get_dimensions(&self) -> Result<(f32, f32), String> { - Ok((self.width, self.height)) + unsafe { Ok((ffi::GetScreenWidth() as f32, ffi::GetScreenHeight() as f32)) } } fn get_key_pressed(&mut self, key: char) -> Result { - todo!() + unsafe { Ok(ffi::IsKeyPressed(key.to_ascii_uppercase() as c_int)) } } fn get_mouse_pressed(&mut self) -> Result, String> { - todo!() + unsafe { + if ffi::IsMouseButtonPressed(0) { + Ok(Some((ffi::GetTouchX() as f32, ffi::GetTouchY() as f32))) + } else { + Ok(None) + } + } } fn get_mouse_down(&mut self) -> Result, String> { - todo!() + unsafe { + if ffi::IsMouseButtonDown(0) { + Ok(Some((ffi::GetTouchX() as f32, ffi::GetTouchY() as f32))) + } else { + Ok(None) + } + } } fn get_mouse_xy(&self) -> Result<(f32, f32), String> { - todo!() + unsafe { Ok((ffi::GetTouchX() as f32, ffi::GetTouchY() as f32)) } } fn get_mouse_xy_vec(&self) -> Result { - todo!() + unsafe { + Ok(crate::faux_quicksilver::Vector { + x: ffi::GetTouchX() as f32, + y: ffi::GetTouchY() as f32, + }) + } } fn get_delta_time(&self) -> f32 { - todo!() + unsafe { ffi::GetFrameTime() } } fn clear_window(&mut self, color: crate::faux_quicksilver::Color) -> Result<(), String> { - todo!() + unsafe { + ffi::ClearBackground(fqcolor_to_color(color)); + } + Ok(()) } fn begin_drawing(&mut self) -> Result<(), String> { - todo!() + unsafe { + ffi::BeginDrawing(); + } + Ok(()) } fn end_drawing(&mut self) -> Result<(), String> { - todo!() + unsafe { + ffi::EndDrawing(); + } + Ok(()) } - fn draw_circle(&mut self, circle: crate::faux_quicksilver::Circle, color: crate::faux_quicksilver::Color) -> Result<(), String> { - todo!() + fn draw_circle( + &mut self, + circle: crate::faux_quicksilver::Circle, + color: crate::faux_quicksilver::Color, + ) -> Result<(), String> { + unsafe { + ffi::DrawCircle( + circle.x.round() as i32, + circle.y.round() as i32, + circle.r, + fqcolor_to_color(color), + ); + } + Ok(()) } fn draw_circle_ex( @@ -87,8 +332,21 @@ impl GameInterface for RaylibGame { todo!() } - fn draw_rect(&mut self, rect: crate::faux_quicksilver::Rectangle, color: crate::faux_quicksilver::Color) -> Result<(), String> { - todo!() + fn draw_rect( + &mut self, + rect: crate::faux_quicksilver::Rectangle, + color: crate::faux_quicksilver::Color, + ) -> Result<(), String> { + unsafe { + ffi::DrawRectangle( + rect.x.round() as i32, + rect.y.round() as i32, + rect.w.round() as i32, + rect.h.round() as i32, + fqcolor_to_color(color), + ); + } + Ok(()) } fn draw_rect_ex( @@ -110,20 +368,84 @@ impl GameInterface for RaylibGame { todo!() } - fn load_image(&mut self, path: &std::path::Path) -> Result, String> { - todo!() + fn load_image( + &mut self, + path: &std::path::Path, + ) -> Result, String> { + unsafe { + let path_str = path + .to_str() + .ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?; + let path_buf: Vec = path_str.as_bytes().into(); + let cstring: CString = CString::from_vec_unchecked(path_buf); + let image = ffi::LoadImage(cstring.as_ptr()); + let raylib_image_handler = RaylibImageHandler { + image: Rc::new(RaylibImage { image }), + }; + self.images + .insert(path_str.to_owned(), raylib_image_handler.image.clone()); + Ok(Box::new(raylib_image_handler)) + } } - fn load_font(&mut self, path: &std::path::Path) -> Result, String> { - todo!() + fn load_font( + &mut self, + path: &std::path::Path, + ) -> Result, String> { + unsafe { + let path_str = path + .to_str() + .ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?; + let path_buf: Vec = path_str.as_bytes().into(); + let cstring: CString = CString::from_vec_unchecked(path_buf); + let font = ffi::LoadFont(cstring.as_ptr()); + let raylib_font_handler = RaylibFontHandler { + font: Rc::new(RaylibFont { font }), + }; + self.fonts + .insert(path_str.to_owned(), raylib_font_handler.font.clone()); + Ok(Box::new(raylib_font_handler)) + } } - fn load_sound(&mut self, path: &std::path::Path) -> Result, String> { - todo!() + fn load_sound( + &mut self, + path: &std::path::Path, + ) -> Result, String> { + unsafe { + let path_str = path + .to_str() + .ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?; + let path_buf: Vec = path_str.as_bytes().into(); + let cstring: CString = CString::from_vec_unchecked(path_buf); + let sound = ffi::LoadSound(cstring.as_ptr()); + let raylib_sound_handler = RaylibSoundHandler { + sound: Rc::new(RaylibSound { sound }), + }; + self.sounds + .insert(path_str.to_owned(), raylib_sound_handler.sound.clone()); + Ok(Box::new(raylib_sound_handler)) + } } - fn load_music(&mut self, path: &std::path::Path) -> Result, String> { - todo!() + fn load_music( + &mut self, + path: &std::path::Path, + ) -> Result, String> { + unsafe { + let path_str = path + .to_str() + .ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?; + let path_buf: Vec = path_str.as_bytes().into(); + let cstring: CString = CString::from_vec_unchecked(path_buf); + let music = ffi::LoadMusicStream(cstring.as_ptr()); + let raylib_music_handler = RaylibMusicHandler { + music: Rc::new(RefCell::new(RaylibMusic { music })), + }; + self.music + .insert(path_str.to_owned(), raylib_music_handler.music.clone()); + Ok(Box::new(raylib_music_handler)) + } } fn get_camera(&mut self) -> Result, String> {