basic window management
This commit is contained in:
parent
9b1a591e22
commit
a13194be71
10
Cargo.toml
10
Cargo.toml
@ -21,7 +21,17 @@ exclude = [
|
||||
[dependencies]
|
||||
rgb = "^0.8.34"
|
||||
cgmath = "^0.18.0"
|
||||
cstr = "^0.2.11"
|
||||
num-traits = "^0.2.14"
|
||||
printf = "^0.1.0"
|
||||
log = "^0.4.14"
|
||||
num-derive = "^0.3.3"
|
||||
vsprintf = "^2.0.0"
|
||||
lazy_static = "^1.4.0"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "^0.63.0"
|
||||
cmake = "^0.1.49"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "^0.10.0"
|
45
build.rs
45
build.rs
@ -1,4 +1,17 @@
|
||||
use std::path::PathBuf;
|
||||
use std::{path::PathBuf, collections::HashSet};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct IgnoreMacros(HashSet<String>);
|
||||
|
||||
impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
|
||||
fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
|
||||
if self.0.contains(name) {
|
||||
bindgen::callbacks::MacroParsingBehavior::Ignore
|
||||
} else {
|
||||
bindgen::callbacks::MacroParsingBehavior::Default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compiles raylib
|
||||
fn compile_raylib(raylib_path: &str) {
|
||||
@ -23,9 +36,18 @@ fn compile_raylib(raylib_path: &str) {
|
||||
let destination = cmake_config.build();
|
||||
|
||||
// Tell cargo where the libraries might be
|
||||
println!("cargo:rustc-link-search=native={}", destination.join("lib").display());
|
||||
println!("cargo:rustc-link-search=native={}", destination.join("lib32").display());
|
||||
println!("cargo:rustc-link-search=native={}", destination.join("lib64").display());
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
destination.join("lib").display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
destination.join("lib32").display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
destination.join("lib64").display()
|
||||
);
|
||||
}
|
||||
|
||||
/// Links libraries
|
||||
@ -62,10 +84,25 @@ fn link_libs() {
|
||||
|
||||
/// Generates `bindings.rs` file
|
||||
fn generate_bindings(header_file: &str) {
|
||||
// Tell bindgen to ignore these macros
|
||||
let ignored_macros = IgnoreMacros(
|
||||
vec![
|
||||
"FP_INFINITE".into(),
|
||||
"FP_NAN".into(),
|
||||
"FP_NORMAL".into(),
|
||||
"FP_SUBNORMAL".into(),
|
||||
"FP_ZERO".into(),
|
||||
"IPPORT_RESERVED".into(),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
// Generate the data
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header(header_file)
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
.parse_callbacks(Box::new(ignored_macros))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
|
@ -1,10 +1,14 @@
|
||||
use renderkit::raylib::window::Window;
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
// Set up logging
|
||||
env_logger::init();
|
||||
|
||||
// Create a window
|
||||
renderkit::raylib::ffi::InitWindow(
|
||||
800,
|
||||
450,
|
||||
"raylib-ffi example - basic window\0".as_ptr() as *const i8,
|
||||
let window = Window::new(
|
||||
cgmath::Vector2::new(800, 450),
|
||||
"raylib-ffi example - basic window",
|
||||
);
|
||||
|
||||
// Render the window
|
||||
@ -20,7 +24,7 @@ pub fn main() {
|
||||
// Render text and a background
|
||||
renderkit::raylib::ffi::ClearBackground(renderkit::raylib::palette::RAYWHITE.into());
|
||||
renderkit::raylib::ffi::DrawText(
|
||||
"Congrats! You created your first window!\0".as_ptr() as *const i8,
|
||||
cstr::cstr!("Congrats! You created your first window!").as_ptr(),
|
||||
190,
|
||||
200,
|
||||
20,
|
||||
@ -30,8 +34,5 @@ pub fn main() {
|
||||
// End the draw call
|
||||
renderkit::raylib::ffi::EndDrawing();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
renderkit::raylib::ffi::CloseWindow();
|
||||
}
|
||||
}
|
||||
|
87
src/raylib/logging.rs
Normal file
87
src/raylib/logging.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use vsprintf::vsprintf;
|
||||
|
||||
/// Direct mapping of raylib's log levels
|
||||
/// See: https://github.com/raysan5/raylib/blob/d875891a3c2621ab40733ca3569eca9e054a6506/parser/raylib_api.json#L985-L1026
|
||||
#[derive(FromPrimitive)]
|
||||
enum RaylibLogLevel {
|
||||
All = 0,
|
||||
Trace = 1,
|
||||
Debug = 2,
|
||||
Info = 3,
|
||||
Warning = 4,
|
||||
Error = 5,
|
||||
Fatal = 6,
|
||||
None = 7,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rl_log_callback(
|
||||
level: i32,
|
||||
message: *const i8,
|
||||
args: *mut super::ffi::__va_list_tag,
|
||||
) {
|
||||
// Format the message
|
||||
let formatted_message = vsprintf(message, args);
|
||||
|
||||
// If all is well, we can continue logging
|
||||
if let Ok(formatted_message) = formatted_message {
|
||||
// Convert the string prefix to a target if possible
|
||||
let mut target = "raylib";
|
||||
let final_message;
|
||||
if formatted_message.starts_with("RLGL: ") {
|
||||
target = "raylib::rlgl";
|
||||
final_message =
|
||||
std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("RLGL: "));
|
||||
}
|
||||
// else if formatted_message.starts_with("DISPLAY: ") {
|
||||
// target = "raylib::display";
|
||||
// final_message = std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("DISPLAY: "));
|
||||
// }
|
||||
// else if formatted_message.starts_with("GL: ") {
|
||||
// target = "raylib::gl";
|
||||
// final_message = std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("GL: "));
|
||||
// }
|
||||
else if formatted_message.starts_with("GLAD: ") {
|
||||
target = "raylib::glad";
|
||||
final_message =
|
||||
std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("GLAD: "));
|
||||
} else if formatted_message.starts_with("TEXTURE: ") {
|
||||
target = "raylib::texture";
|
||||
final_message =
|
||||
std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("TEXTURE: "));
|
||||
} else if formatted_message.starts_with("SHADER: ") {
|
||||
target = "raylib::shader";
|
||||
final_message =
|
||||
std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("SHADER: "));
|
||||
} else if formatted_message.starts_with("FONT: ") {
|
||||
target = "raylib::font";
|
||||
final_message =
|
||||
std::borrow::Cow::Borrowed(formatted_message.trim_start_matches("FONT: "));
|
||||
} else {
|
||||
final_message = std::borrow::Cow::Borrowed(&formatted_message);
|
||||
}
|
||||
|
||||
// Handle the log level and fall back on info!
|
||||
match RaylibLogLevel::from_u32(level as u32) {
|
||||
Some(level) => match level {
|
||||
RaylibLogLevel::Trace => log::trace!(target: target, "{}", final_message),
|
||||
RaylibLogLevel::Debug => log::debug!(target: target, "{}", final_message),
|
||||
RaylibLogLevel::Warning => log::warn!(target: target, "{}", final_message),
|
||||
RaylibLogLevel::Error => log::error!(target: target, "{}", final_message),
|
||||
RaylibLogLevel::Fatal => log::error!(target: target, "{}", final_message),
|
||||
_ => log::info!(target: target, "{}", final_message),
|
||||
},
|
||||
None => {
|
||||
log::info!(target:"raylib", "{}", final_message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configures raylib to use our custom logging code
|
||||
pub unsafe fn rl_use_rust_logging() {
|
||||
log::debug!("Configuring raylib to use the `log` crate");
|
||||
super::ffi::SetTraceLogCallback(Some(rl_log_callback));
|
||||
}
|
@ -2,4 +2,7 @@
|
||||
|
||||
pub mod xlat;
|
||||
pub mod ffi;
|
||||
pub mod palette;
|
||||
pub mod palette;
|
||||
pub mod window;
|
||||
|
||||
pub(crate) mod logging;
|
58
src/raylib/window.rs
Normal file
58
src/raylib/window.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use cgmath::Vector2;
|
||||
|
||||
use super::ffi as raylib;
|
||||
use super::logging::rl_use_rust_logging;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref WINDOW_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
|
||||
}
|
||||
|
||||
/// A window handle
|
||||
#[derive(Debug)]
|
||||
pub struct Window {}
|
||||
|
||||
impl Window {
|
||||
/// Construct a new `Window`
|
||||
pub fn new(size: Vector2<i32>, title: &str) -> Self {
|
||||
// Make sure we only have one window
|
||||
if WINDOW_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst) > 0 {
|
||||
panic!("Only one window is allowed at a time");
|
||||
}
|
||||
|
||||
// Perform FFI work
|
||||
unsafe {
|
||||
// Hook our rusty logging system into raylib
|
||||
rl_use_rust_logging();
|
||||
|
||||
// Set some reasonable defaults
|
||||
raylib::SetWindowState(
|
||||
raylib::ConfigFlags_FLAG_VSYNC_HINT
|
||||
| raylib::ConfigFlags_FLAG_WINDOW_RESIZABLE
|
||||
| raylib::ConfigFlags_FLAG_MSAA_4X_HINT,
|
||||
);
|
||||
|
||||
// Create a window
|
||||
raylib::InitWindow(
|
||||
size.x as i32,
|
||||
size.y as i32,
|
||||
format!("{}\0", title).as_ptr() as *const i8,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
// Perform FFI work
|
||||
unsafe {
|
||||
// Clean up
|
||||
crate::raylib::ffi::CloseWindow();
|
||||
}
|
||||
|
||||
// Decrement the window count
|
||||
WINDOW_COUNT.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user