#[macro_use]
mod macros;
pub mod audio;
pub mod automation;
pub mod callbacks;
pub mod camera;
pub mod collision;
pub mod color;
pub mod data;
pub mod drawing;
pub mod error;
pub mod file;
pub mod game_loop;
pub mod input;
pub mod logging;
pub mod math;
pub mod misc;
pub mod models;
pub mod shaders;
pub mod text;
pub mod texture;
pub mod vr;
pub mod window;
use raylib_sys::TraceLogLevel;
use crate::ffi;
use std::ffi::CString;
use std::marker::PhantomData;
#[macro_export]
macro_rules! rstr {
($e:tt) => ({
#[allow(unused_unsafe)]
unsafe {
std::ffi::CStr::from_bytes_with_nul_unchecked(concat!($e, "\0").as_bytes())
}
});
($e:tt, $($arg:tt)*) => ({
#[allow(unused_unsafe)]
unsafe {
std::ffi::CString::new(format!($e, $($arg)*)).unwrap()
}
})
}
#[derive(Clone, Debug)]
pub struct RaylibThread(PhantomData<*const ()>);
#[derive(Debug)]
pub struct RaylibHandle(());
impl Drop for RaylibHandle {
fn drop(&mut self) {
unsafe {
if ffi::IsWindowReady() {
ffi::CloseWindow();
}
}
}
}
#[derive(Debug, Default)]
pub struct RaylibBuilder {
fullscreen_mode: bool,
window_resizable: bool,
window_undecorated: bool,
window_hidden: bool,
window_minimized: bool,
window_maximized: bool,
window_unfocused: bool,
window_topmost: bool,
window_always_run: bool,
window_transparent: bool,
window_highdpi: bool,
window_mouse_passthrough: bool,
borderless_windowed_mode: bool,
msaa_4x_hint: bool,
interlaced_hint: bool,
vsync_hint: bool,
log_level: TraceLogLevel,
width: i32,
height: i32,
title: String,
}
pub fn init() -> RaylibBuilder {
RaylibBuilder {
width: 640,
height: 480,
title: "raylib-rs".to_string(),
..Default::default()
}
}
impl RaylibBuilder {
pub fn fullscreen(&mut self) -> &mut Self {
self.fullscreen_mode = true;
self
}
pub fn borderless_windowed(&mut self) -> &mut Self {
self.borderless_windowed_mode = true;
self
}
pub fn log_level(&mut self, level: TraceLogLevel) -> &mut Self {
self.log_level = level;
self
}
pub fn resizable(&mut self) -> &mut Self {
self.window_resizable = true;
self
}
pub fn undecorated(&mut self) -> &mut Self {
self.window_undecorated = true;
self
}
pub fn hidden(&mut self) -> &mut Self {
self.window_hidden = true;
self
}
pub fn minimized(&mut self) -> &mut Self {
self.window_minimized = true;
self
}
pub fn maximized(&mut self) -> &mut Self {
self.window_maximized = true;
self
}
pub fn unfocused(&mut self) -> &mut Self {
self.window_unfocused = true;
self
}
pub fn topmost(&mut self) -> &mut Self {
self.window_topmost = true;
self
}
pub fn always_run(&mut self) -> &mut Self {
self.window_always_run = true;
self
}
pub fn transparent(&mut self) -> &mut Self {
self.window_transparent = true;
self
}
pub fn highdpi(&mut self) -> &mut Self {
self.window_highdpi = true;
self
}
pub fn mouse_passthrough(&mut self) -> &mut Self {
self.window_mouse_passthrough = true;
self
}
pub fn msaa_4x(&mut self) -> &mut Self {
self.msaa_4x_hint = true;
self
}
pub fn interlaced(&mut self) -> &mut Self {
self.interlaced_hint = true;
self
}
pub fn vsync(&mut self) -> &mut Self {
self.vsync_hint = true;
self
}
pub fn width(&mut self, w: i32) -> &mut Self {
self.width = w;
self
}
pub fn height(&mut self, h: i32) -> &mut Self {
self.height = h;
self
}
pub fn size(&mut self, w: i32, h: i32) -> &mut Self {
self.width = w;
self.height = h;
self
}
pub fn title(&mut self, text: &str) -> &mut Self {
self.title = text.to_string();
self
}
pub fn build(&self) -> (RaylibHandle, RaylibThread) {
use crate::consts::ConfigFlags::*;
let mut flags = 0u32;
if self.fullscreen_mode {
flags |= FLAG_FULLSCREEN_MODE as u32;
}
if self.window_resizable {
flags |= FLAG_WINDOW_RESIZABLE as u32;
}
if self.window_undecorated {
flags |= FLAG_WINDOW_UNDECORATED as u32;
}
if self.window_hidden {
flags |= FLAG_WINDOW_HIDDEN as u32;
}
if self.window_minimized {
flags |= FLAG_WINDOW_MINIMIZED as u32;
}
if self.window_maximized {
flags |= FLAG_WINDOW_MAXIMIZED as u32;
}
if self.window_unfocused {
flags |= FLAG_WINDOW_UNFOCUSED as u32;
}
if self.window_topmost {
flags |= FLAG_WINDOW_TOPMOST as u32;
}
if self.window_always_run {
flags |= FLAG_WINDOW_ALWAYS_RUN as u32;
}
if self.window_transparent {
flags |= FLAG_WINDOW_TRANSPARENT as u32;
}
if self.window_highdpi {
flags |= FLAG_WINDOW_HIGHDPI as u32;
}
if self.window_mouse_passthrough {
flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH as u32;
}
if self.borderless_windowed_mode {
flags |= FLAG_BORDERLESS_WINDOWED_MODE as u32;
}
if self.msaa_4x_hint {
flags |= FLAG_MSAA_4X_HINT as u32;
}
if self.interlaced_hint {
flags |= FLAG_INTERLACED_HINT as u32;
}
if self.vsync_hint {
flags |= FLAG_VSYNC_HINT as u32;
}
unsafe {
ffi::SetConfigFlags(flags);
}
unsafe {
ffi::SetTraceLogLevel(self.log_level as i32);
}
let rl = init_window(self.width, self.height, &self.title);
(rl, RaylibThread(PhantomData))
}
}
fn init_window(width: i32, height: i32, title: &str) -> RaylibHandle {
if unsafe { ffi::IsWindowReady() } {
panic!("Attempted to initialize raylib-rs more than once!");
} else {
unsafe {
let c_title = CString::new(title).unwrap();
ffi::InitWindow(width, height, c_title.as_ptr());
}
if !unsafe { ffi::IsWindowReady() } {
panic!("Attempting to create window failed!");
}
RaylibHandle(())
}
}