LD45/src/agnostic_interface/raylib_impl.rs
2023-02-23 15:09:13 +09:00

1072 lines
33 KiB
Rust

pub mod ffi {
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(clippy::approx_constant)]
include!(concat!(env!("OUT_DIR"), "/raylib_bindings.rs"));
}
use std::{
cell::RefCell,
collections::HashMap,
ffi::CString,
os::raw::{c_char, c_int},
path::{Path, PathBuf},
rc::Rc,
str::FromStr,
};
use crate::{
faux_quicksilver::{Transform, Vector},
shaders::{get_attrib_location, set_attr_2f, set_transform_3f},
};
use super::{
CameraInterface, FontInterface, GameInterface, ImageInterface, MusicInterface, ShaderInterface,
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,
}
}
fn fqrect_to_rect(r: crate::faux_quicksilver::Rectangle) -> ffi::Rectangle {
ffi::Rectangle {
x: r.x,
y: r.y,
width: r.w,
height: r.h,
}
}
fn fqvector_to_vector2(v: crate::faux_quicksilver::Vector) -> ffi::Vector2 {
ffi::Vector2 { x: v.x, y: v.y }
}
#[derive(Clone, Debug)]
pub struct RaylibShader {
shader: ffi::Shader,
}
impl RaylibShader {
pub fn get_shader_id(&self) -> ::std::os::raw::c_uint {
self.shader.id as ::std::os::raw::c_uint
}
fn set_transform_attrib(&mut self, transform: Transform) -> Result<(), String> {
let transform_cstr = CString::new("transform")
.map_err(|_| String::from("Failed to create \"transform\" CString!"))?;
let attr_loc = get_attrib_location(self, &transform_cstr);
set_transform_3f(attr_loc, transform);
Ok(())
}
fn begin_draw_shader(&self) -> Result<(), String> {
unsafe {
ffi::BeginShaderMode(self.shader);
}
Ok(())
}
fn end_draw_shader(&self) -> Result<(), String> {
unsafe {
ffi::EndShaderMode();
}
Ok(())
}
fn set_origin_attrib(&mut self, origin: Vector) -> Result<(), String> {
let origin_cstr = CString::new("origin")
.map_err(|_| String::from("Failed to create \"origin\" CString!"))?;
let attr_loc = get_attrib_location(self, &origin_cstr);
set_attr_2f(attr_loc, origin);
Ok(())
}
fn set_camera_attrib(&mut self, camera: Vector) -> Result<(), String> {
let camera_cstr = CString::new("camera")
.map_err(|_| String::from("Failed to create \"camera\" CString!"))?;
let attr_loc = get_attrib_location(self, &camera_cstr);
set_attr_2f(attr_loc, camera);
Ok(())
}
}
#[derive(Clone, Debug)]
struct RaylibShaderHandler {
shader: Rc<RefCell<RaylibShader>>,
}
impl ShaderInterface for RaylibShaderHandler {
fn set_transform_attrib(&mut self, transform: Transform) -> Result<(), String> {
self.shader.borrow_mut().set_transform_attrib(transform)
}
fn begin_draw_shader(&self) -> Result<(), String> {
self.shader.borrow().begin_draw_shader()
}
fn end_draw_shader(&self) -> Result<(), String> {
self.shader.borrow().end_draw_shader()
}
fn set_origin_attrib(&mut self, origin: Vector) -> Result<(), String> {
self.shader.borrow_mut().set_origin_attrib(origin)
}
fn set_camera_attrib(&mut self, camera: Vector) -> Result<(), String> {
self.shader.borrow_mut().set_camera_attrib(camera)
}
}
impl RaylibShaderHandler {
pub fn load_shader(vs: &Path, fs: &Path) -> Result<Self, String> {
unsafe {
let vs_cstr: CString = CString::from_vec_unchecked(
vs.to_str()
.ok_or_else(|| format!("Cannot convert path \"{vs:?}\" to str!"))?
.as_bytes()
.to_owned(),
);
let fs_cstr: CString = CString::from_vec_unchecked(
fs.to_str()
.ok_or_else(|| format!("Cannot convert path \"{fs:?}\" to str!"))?
.as_bytes()
.to_owned(),
);
Ok(Self {
shader: Rc::new(RefCell::new(RaylibShader {
shader: ffi::LoadShader(vs_cstr.as_ptr(), fs_cstr.as_ptr()),
})),
})
}
}
}
#[derive(Clone, Debug)]
struct RaylibImage {
image: ffi::Image,
texture: Option<ffi::Texture>,
}
#[derive(Clone, Debug)]
struct RaylibImageHandler {
image: Rc<RefCell<RaylibImage>>,
tr_or_cam_shader: Rc<RefCell<Option<RaylibShaderHandler>>>,
cam_shader: Rc<RefCell<Option<RaylibShaderHandler>>>,
camera: Rc<RefCell<Camera>>,
}
impl RaylibImageHandler {
fn image_to_texture(&mut self) -> Result<(), String> {
if self.image.borrow().texture.is_none() {
unsafe {
let texture = ffi::LoadTextureFromImage(self.image.borrow().image);
self.image.borrow_mut().texture = Some(texture);
}
}
Ok(())
}
}
impl ImageInterface for RaylibImageHandler {
fn draw(
&mut self,
x: f32,
y: f32,
color: crate::faux_quicksilver::Color,
) -> Result<(), String> {
self.image_to_texture()?;
if let Some(cam_shader) = self.cam_shader.borrow_mut().as_mut() {
cam_shader.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexture(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
x.round() as i32,
y.round() as i32,
fqcolor_to_color(color),
);
}
cam_shader.end_draw_shader()?;
} else {
unsafe {
ffi::DrawTexture(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
x.round() as i32,
y.round() as i32,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_sub(
&mut self,
sub_rect: crate::faux_quicksilver::Rectangle,
dest_rect: crate::faux_quicksilver::Rectangle,
color: crate::faux_quicksilver::Color,
) -> Result<(), String> {
self.image_to_texture()?;
if let Some(cam_shader) = self.cam_shader.borrow_mut().as_mut() {
cam_shader.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexturePro(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
fqrect_to_rect(sub_rect),
fqrect_to_rect(dest_rect),
ffi::Vector2 { x: 0.0, y: 0.0 },
0.0,
fqcolor_to_color(color),
);
}
cam_shader.end_draw_shader()?;
} else {
unsafe {
ffi::DrawTexturePro(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
fqrect_to_rect(sub_rect),
fqrect_to_rect(dest_rect),
ffi::Vector2 { x: 0.0, y: 0.0 },
0.0,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_transform(
&mut self,
x: f32,
y: f32,
color: crate::faux_quicksilver::Color,
transform: crate::faux_quicksilver::Transform,
origin: Vector,
) -> Result<(), String> {
self.image_to_texture()?;
if let Some(shader) = self.tr_or_cam_shader.borrow_mut().as_mut() {
shader.set_origin_attrib(origin)?;
shader.set_transform_attrib(transform)?;
shader.set_camera_attrib(self.camera.borrow().pos)?;
shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexture(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
x.round() as i32,
y.round() as i32,
fqcolor_to_color(color),
);
}
shader.end_draw_shader()?;
} else if let Some(cam_shader) = self.cam_shader.borrow_mut().as_mut() {
cam_shader.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexture(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
x.round() as i32,
y.round() as i32,
fqcolor_to_color(color),
);
}
cam_shader.end_draw_shader()?;
} else {
unsafe {
ffi::DrawTexture(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
x.round() as i32,
y.round() as i32,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_sub_transform(
&mut self,
sub_rect: crate::faux_quicksilver::Rectangle,
dest_rect: crate::faux_quicksilver::Rectangle,
color: crate::faux_quicksilver::Color,
transform: crate::faux_quicksilver::Transform,
origin: Vector,
) -> Result<(), String> {
self.image_to_texture()?;
if let Some(shader) = self.tr_or_cam_shader.borrow_mut().as_mut() {
shader.set_origin_attrib(origin)?;
shader.set_transform_attrib(transform)?;
shader.set_camera_attrib(self.camera.borrow().pos)?;
shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexturePro(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
fqrect_to_rect(sub_rect),
fqrect_to_rect(dest_rect),
ffi::Vector2 { x: 0.0, y: 0.0 },
0.0,
fqcolor_to_color(color),
);
}
shader.end_draw_shader()?;
} else if let Some(cam_shader) = self.cam_shader.borrow_mut().as_mut() {
cam_shader.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.begin_draw_shader()?;
unsafe {
ffi::DrawTexturePro(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
fqrect_to_rect(sub_rect),
fqrect_to_rect(dest_rect),
ffi::Vector2 { x: 0.0, y: 0.0 },
0.0,
fqcolor_to_color(color),
);
}
cam_shader.end_draw_shader()?;
} else {
unsafe {
ffi::DrawTexturePro(
*self
.image
.borrow()
.texture
.as_ref()
.ok_or_else(|| String::from("RaylibImage has no Texture!"))?,
fqrect_to_rect(sub_rect),
fqrect_to_rect(dest_rect),
ffi::Vector2 { x: 0.0, y: 0.0 },
0.0,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn get_w(&self) -> usize {
self.image.borrow().image.width as usize
}
fn get_h(&self) -> usize {
self.image.borrow().image.height as usize
}
fn get_wh_rect(&self) -> crate::faux_quicksilver::Rectangle {
crate::faux_quicksilver::Rectangle {
x: 0.0,
y: 0.0,
w: self.image.borrow().image.width as f32,
h: self.image.borrow().image.height as f32,
}
}
}
#[derive(Clone, Debug)]
struct RaylibFont {
font: ffi::Font,
}
#[derive(Clone, Debug)]
struct RaylibFontHandler {
font: Rc<RaylibFont>,
}
impl FontInterface for RaylibFontHandler {
fn draw(
&mut self,
s: &str,
size: u32,
x: f32,
y: f32,
color: crate::faux_quicksilver::Color,
) -> Result<(), String> {
unsafe {
let cstring = CString::from_vec_unchecked(s.as_bytes().into());
ffi::DrawTextEx(
self.font.font,
cstring.as_ptr(),
ffi::Vector2 { x, y },
size as f32,
(size / 10) as f32,
fqcolor_to_color(color),
);
}
Ok(())
}
}
#[derive(Clone, Debug)]
struct RaylibSound {
sound: ffi::Sound,
}
#[derive(Clone, Debug)]
struct RaylibSoundHandler {
sound: Rc<RaylibSound>,
}
impl SoundInterface for RaylibSoundHandler {
fn play(&mut self, vol: f32) -> Result<(), String> {
unsafe {
ffi::SetSoundVolume(self.sound.sound, vol);
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<RefCell<RaylibMusic>>,
}
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(())
}
}
#[derive(Debug, Clone)]
struct Camera {
pos: Vector,
}
impl Default for Camera {
fn default() -> Self {
Self {
pos: Vector { x: 0.0, y: 0.0 },
}
}
}
impl CameraInterface for Camera {
fn get_view_xy(&self) -> Result<(f32, f32), String> {
Ok((self.pos.x, self.pos.y))
}
fn set_view_xy(&mut self, x: f32, y: f32) -> Result<(), String> {
self.pos.x = x;
self.pos.y = y;
Ok(())
}
}
pub struct RaylibGame {
images: HashMap<String, Rc<RefCell<RaylibImage>>>,
fonts: HashMap<String, Rc<RaylibFont>>,
sounds: HashMap<String, Rc<RaylibSound>>,
music: HashMap<String, Rc<RefCell<RaylibMusic>>>,
shaders: HashMap<String, Rc<RefCell<RaylibShader>>>,
camera: Rc<RefCell<Camera>>,
}
impl RaylibGame {
#[cfg(not(target_arch = "wasm32"))]
fn native_setup() {
unsafe {
ffi::SetTargetFPS(60);
}
}
#[cfg(target_arch = "wasm32")]
fn native_setup() {}
pub fn new_boxed(width: u32, height: u32) -> Box<dyn GameInterface> {
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,
);
}
Self::native_setup();
unsafe {
while !ffi::IsAudioDeviceReady() {
ffi::InitAudioDevice();
}
}
let mut self_unboxed = Self {
images: HashMap::new(),
fonts: HashMap::new(),
sounds: HashMap::new(),
music: HashMap::new(),
shaders: HashMap::new(),
camera: Rc::new(RefCell::new(Camera::default())),
};
if let Err(e) = self_unboxed.load_transform_origin_shader() {
println!("WARNING: {e:?}");
}
if let Err(e) = self_unboxed.load_camera_shader() {
println!("WARNING: {e:?}");
}
Box::new(self_unboxed)
}
}
impl Drop for RaylibGame {
fn drop(&mut self) {
unsafe {
for shader in self.shaders.values() {
ffi::UnloadShader(shader.borrow().shader);
}
for image in self.images.values() {
if let Some(texture) = image.borrow_mut().texture.take() {
ffi::UnloadTexture(texture);
}
ffi::UnloadImage(image.borrow().image);
}
for font in self.fonts.values() {
ffi::UnloadFont(font.font);
}
for sound in self.sounds.values() {
ffi::UnloadSound(sound.sound);
}
for music in self.music.values() {
ffi::UnloadMusicStream(music.borrow().music);
}
ffi::CloseWindow();
}
}
}
impl GameInterface for RaylibGame {
fn get_dimensions(&self) -> Result<(f32, f32), String> {
unsafe { Ok((ffi::GetScreenWidth() as f32, ffi::GetScreenHeight() as f32)) }
}
fn get_key_pressed(&mut self, key: char) -> Result<bool, String> {
unsafe { Ok(ffi::IsKeyPressed(key.to_ascii_uppercase() as c_int)) }
}
fn get_mouse_pressed(&mut self) -> Result<Option<(f32, f32)>, String> {
unsafe {
if ffi::IsMouseButtonPressed(0) {
Ok(Some((ffi::GetTouchX() as f32, ffi::GetTouchY() as f32)))
} else {
Ok(None)
}
}
}
fn get_mouse_released(&mut self) -> Result<bool, String> {
unsafe {
if ffi::IsMouseButtonReleased(0) {
Ok(true)
} else {
Ok(false)
}
}
}
fn get_mouse_down(&mut self) -> Result<Option<(f32, f32)>, String> {
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> {
unsafe { Ok((ffi::GetTouchX() as f32, ffi::GetTouchY() as f32)) }
}
fn get_mouse_xy_vec(&self) -> Result<crate::faux_quicksilver::Vector, String> {
unsafe {
Ok(crate::faux_quicksilver::Vector {
x: ffi::GetTouchX() as f32,
y: ffi::GetTouchY() as f32,
})
}
}
fn get_delta_time(&self) -> f32 {
unsafe { ffi::GetFrameTime() }
}
fn clear_window(&mut self, color: crate::faux_quicksilver::Color) -> Result<(), String> {
unsafe {
ffi::ClearBackground(fqcolor_to_color(color));
}
Ok(())
}
fn begin_drawing(&mut self) -> Result<(), String> {
unsafe {
ffi::BeginDrawing();
}
Ok(())
}
fn end_drawing(&mut self) -> Result<(), String> {
unsafe {
ffi::EndDrawing();
}
Ok(())
}
fn draw_circle(
&mut self,
circle: crate::faux_quicksilver::Circle,
color: crate::faux_quicksilver::Color,
) -> Result<(), String> {
if let Some(cam_shader) = self.shaders.get_mut("camera") {
cam_shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.borrow().begin_draw_shader()?;
unsafe {
ffi::DrawCircle(
circle.x.round() as i32,
circle.y.round() as i32,
circle.r,
fqcolor_to_color(color),
);
}
cam_shader.borrow().end_draw_shader()?;
} else {
unsafe {
ffi::DrawCircle(
circle.x.round() as i32,
circle.y.round() as i32,
circle.r,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_circle_transform(
&mut self,
circle: crate::faux_quicksilver::Circle,
color: crate::faux_quicksilver::Color,
transform: crate::faux_quicksilver::Transform,
origin: Vector,
) -> Result<(), String> {
if let Some(shader) = self.shaders.get_mut("transform_origin") {
shader.borrow_mut().set_origin_attrib(origin)?;
shader.borrow_mut().set_transform_attrib(transform)?;
shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
shader.borrow().begin_draw_shader()?;
unsafe {
ffi::DrawCircle(
circle.x.round() as i32,
circle.y.round() as i32,
circle.r,
fqcolor_to_color(color),
);
}
shader.borrow().end_draw_shader()?;
} else if let Some(cam_shader) = self.shaders.get_mut("camera") {
cam_shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.borrow().begin_draw_shader()?;
unsafe {
ffi::DrawCircle(
circle.x.round() as i32,
circle.y.round() as i32,
circle.r,
fqcolor_to_color(color),
);
}
cam_shader.borrow().end_draw_shader()?;
} else {
unsafe {
ffi::DrawCircle(
circle.x.round() as i32,
circle.y.round() as i32,
circle.r,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_rect(
&mut self,
rect: crate::faux_quicksilver::Rectangle,
color: crate::faux_quicksilver::Color,
) -> Result<(), String> {
if let Some(cam_shader) = self.shaders.get_mut("camera") {
cam_shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.borrow().begin_draw_shader()?;
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),
);
}
cam_shader.borrow().end_draw_shader()?;
} else {
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(
&mut self,
rect: crate::faux_quicksilver::Rectangle,
color: crate::faux_quicksilver::Color,
origin: crate::faux_quicksilver::Vector,
rot: f32,
) -> Result<(), String> {
if let Some(cam_shader) = self.shaders.get_mut("camera") {
cam_shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.borrow().begin_draw_shader()?;
unsafe {
ffi::DrawRectanglePro(
fqrect_to_rect(rect),
fqvector_to_vector2(origin),
rot,
fqcolor_to_color(color),
);
}
cam_shader.borrow().end_draw_shader()?;
} else {
unsafe {
ffi::DrawRectanglePro(
fqrect_to_rect(rect),
fqvector_to_vector2(origin),
rot,
fqcolor_to_color(color),
);
}
}
Ok(())
}
fn draw_rect_transform(
&mut self,
rect: crate::faux_quicksilver::Rectangle,
color: crate::faux_quicksilver::Color,
transform: crate::faux_quicksilver::Transform,
origin: Vector,
) -> Result<(), String> {
if let Some(shader) = self.shaders.get_mut("transform_origin") {
shader.borrow_mut().set_origin_attrib(origin)?;
shader.borrow_mut().set_transform_attrib(transform)?;
shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
shader.borrow().begin_draw_shader()?;
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),
);
}
shader.borrow().end_draw_shader()?;
} else if let Some(cam_shader) = self.shaders.get_mut("camera") {
cam_shader
.borrow_mut()
.set_camera_attrib(self.camera.borrow().pos)?;
cam_shader.borrow().begin_draw_shader()?;
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),
);
}
cam_shader.borrow().end_draw_shader()?;
} else {
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 load_image(
&mut self,
path: &std::path::Path,
) -> Result<Box<dyn super::ImageInterface>, String> {
unsafe {
let path_str = path
.to_str()
.ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?;
let path_buf: Vec<u8> = path_str.as_bytes().into();
let cstring: CString = CString::from_vec_unchecked(path_buf);
let image = ffi::LoadImage(cstring.as_ptr());
let tr_or_cam_shader: Option<RaylibShaderHandler> = self
.shaders
.get("transform_origin")
.map(|shader| RaylibShaderHandler {
shader: shader.clone(),
});
let cam_shader: Option<RaylibShaderHandler> =
self.shaders
.get("camera")
.map(|shader| RaylibShaderHandler {
shader: shader.clone(),
});
let raylib_image_handler = RaylibImageHandler {
image: Rc::new(RefCell::new(RaylibImage {
image,
texture: None,
})),
tr_or_cam_shader: Rc::new(RefCell::new(tr_or_cam_shader)),
cam_shader: Rc::new(RefCell::new(cam_shader)),
camera: self.camera.clone(),
};
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<Box<dyn super::FontInterface>, String> {
unsafe {
let path_str = path
.to_str()
.ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?;
let path_buf: Vec<u8> = 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<Box<dyn super::SoundInterface>, String> {
unsafe {
let path_str = path
.to_str()
.ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?;
let cstring: CString = CString::from_vec_unchecked(path_str.as_bytes().into());
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<Box<dyn super::MusicInterface>, String> {
unsafe {
let path_str = path
.to_str()
.ok_or_else(|| format!("Failed to convert \"{path:?}\" to str!"))?;
let path_buf: Vec<u8> = 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 load_shader(
&mut self,
name: String,
vs: &Path,
fs: &Path,
) -> Result<Box<dyn ShaderInterface>, String> {
let raylib_shader = RaylibShaderHandler::load_shader(vs, fs)?;
self.shaders.insert(name, raylib_shader.shader.clone());
Ok(Box::new(raylib_shader))
}
fn get_camera(&mut self) -> Result<Box<dyn super::CameraInterface>, String> {
Ok(Box::new(self.camera.borrow().clone()))
}
fn get_default_camera(&mut self) -> Result<Box<dyn super::CameraInterface>, String> {
Ok(Box::<Camera>::default())
}
fn set_camera(&mut self, camera: &dyn super::CameraInterface) -> Result<(), String> {
self.camera.borrow_mut().pos = camera.get_view_xy()?.into();
Ok(())
}
fn set_camera_xy(&mut self, x: f32, y: f32) -> Result<(), String> {
self.camera.borrow_mut().pos = Vector { x, y };
Ok(())
}
fn xy_to_world(&self, x: f32, y: f32) -> Result<Vector, String> {
Ok(Vector {
x: x + self.camera.borrow().pos.x,
y: y + self.camera.borrow().pos.y,
})
}
fn vec_to_world(&self, vec: Vector) -> Result<Vector, String> {
Ok(Vector {
x: vec.x + self.camera.borrow().pos.x,
y: vec.y + self.camera.borrow().pos.y,
})
}
}
impl RaylibGame {
fn load_transform_origin_shader(&mut self) -> Result<Box<dyn ShaderInterface>, String> {
self.load_shader(
String::from("transform_origin"),
&PathBuf::from_str("static/transform.vs")
.map_err(|_| String::from("Failed to convert \"static/transform.vs\" to path!"))?,
&PathBuf::from_str("static/simple.fs")
.map_err(|_| String::from("Failed to convert \"static/simple.fs\" to path!"))?,
)
}
fn load_camera_shader(&mut self) -> Result<Box<dyn ShaderInterface>, String> {
self.load_shader(
String::from("camera"),
&PathBuf::from_str("static/camera.vs")
.map_err(|_| String::from("Failed to convert \"static/camera.vs\" to path!"))?,
&PathBuf::from_str("static/simple.fs")
.map_err(|_| String::from("Failed to convert \"static/camera.vs\" to path!"))?,
)
}
}