diff options
| author | Micha White <botahamec@outlook.com> | 2024-08-15 20:14:15 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2024-08-15 20:14:15 -0400 |
| commit | f8a80039c74332e2101a177ef3fde31ef2077224 (patch) | |
| tree | f887c96bf9879a28b7ce914ad96161f63ee83190 /sys | |
| parent | 488c7ed94b0662222fa0d825ab81b60b0b1e5d6c (diff) | |
Lots a changes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/Cargo.toml | 8 | ||||
| -rw-r--r-- | sys/build.rs | 8 | ||||
| -rw-r--r-- | sys/src/lib.rs | 98 | ||||
| -rw-r--r-- | sys/src/renderer.rs | 49 | ||||
| -rw-r--r-- | sys/src/window.rs | 116 |
5 files changed, 279 insertions, 0 deletions
diff --git a/sys/Cargo.toml b/sys/Cargo.toml new file mode 100644 index 0000000..bb1a70d --- /dev/null +++ b/sys/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "alligator_sys" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/sys/build.rs b/sys/build.rs new file mode 100644 index 0000000..c33a20f --- /dev/null +++ b/sys/build.rs @@ -0,0 +1,8 @@ +fn main() { + let out_dir = std::env::var("OUT_DIR").unwrap(); + eprintln!("{out_dir}"); + println!("cargo:rustc-link-lib=d3d11"); + println!("cargo:rustc-link-search=native=./"); + println!("cargo:rustc-link-lib-static=alligator_backend"); + println!("cargo:rerun-if-changed=alligator_backend.lib"); +} diff --git a/sys/src/lib.rs b/sys/src/lib.rs new file mode 100644 index 0000000..f3fae9c --- /dev/null +++ b/sys/src/lib.rs @@ -0,0 +1,98 @@ +use std::ffi::{c_uchar, c_uint, c_void}; +use std::os::raw::c_char; + +mod renderer; +mod window; + +pub use renderer::Renderer; +pub use window::{Window, WindowConfig, WindowEvent}; + +type CRenderer = *mut (); +type CWindow = *mut (); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(C)] +pub struct RendererConfig { + pub width: c_uint, + pub height: c_uint, + pub instance_capacity: c_uint, + pub fullscreen: bool, + pub vsync: bool, +} + +#[repr(C)] +pub struct Vertex { + x: f32, + y: f32, + z: f32, + curve_a: f32, + curve_b: f32, + color1_r: f32, + color1_g: f32, + color1_b: f32, + color1_a: f32, + normal_x: f32, + normal_y: f32, + normal_z: f32, +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct CWindowConfig { + default_width: c_uint, + default_height: c_uint, + default_x: c_uint, + default_y: c_uint, + title: *const c_char, + visible: bool, + borderless_fullscreen: bool, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(C)] +pub enum CWindowEvent { + AboutToWait, + Other, + CloseRequest, + ScaleFactorChange, + Resume, + RedrawRequest, +} + +#[link(name = "alligator_backend", kind = "static")] +extern "C" { + fn new_renderer(config: RendererConfig, window: CWindow) -> CRenderer; + fn resize_renderer(renderer: CRenderer, width: c_uint, height: c_uint); + fn set_vsync(renderer: CRenderer, vsync: bool); + fn create_vertex_buffer(renderer: CRenderer, count: c_uint, instances: *const Vertex); + fn set_camera( + renderer: CRenderer, + x: f32, + y: f32, + zoom: f32, + rotation: f32, + width: f32, + height: f32, + ); + fn render_frame(renderer: CRenderer); + fn destroy_renderer(renderer: CRenderer); + + fn create_window(config: CWindowConfig) -> CWindow; + fn set_visible(window: CWindow, visible: bool); + fn resize_window(window: CWindow, width: c_uint, height: c_uint); + fn set_fullscreen(window: CWindow, fullscreen: bool); + fn set_title(window: CWindow, title: *const c_char); + fn wait_for_event(window: CWindow); + fn pop_event(window: CWindow) -> bool; + fn wait_for_resume(window: CWindow); + fn set_event_handler(window: CWindow, closure: *mut c_void); + fn run_event_handler(window: CWindow, event: CWindowEvent); + fn request_redraw(window: CWindow); + fn destroy_window(window: CWindow); +} + +#[no_mangle] +unsafe extern "C" fn alligator_run_closure(closure: *mut c_void, event: CWindowEvent) { + let closure: &mut &mut dyn FnMut(CWindowEvent) = unsafe { &mut *closure.cast() }; + closure(event) +} diff --git a/sys/src/renderer.rs b/sys/src/renderer.rs new file mode 100644 index 0000000..05d111b --- /dev/null +++ b/sys/src/renderer.rs @@ -0,0 +1,49 @@ +use crate::{RendererConfig, Vertex, Window}; + +pub struct Renderer { + ptr: *mut (), +} + +impl Drop for Renderer { + fn drop(&mut self) { + unsafe { crate::destroy_renderer(self.ptr) } + } +} + +impl Renderer { + pub fn new(window: &Window, config: RendererConfig) -> Self { + let ptr = unsafe { crate::new_renderer(config, window.ptr) }; + Self { ptr } + } + + pub fn resize(&mut self, width: u32, height: u32) { + unsafe { crate::resize_renderer(self.ptr, width, height) } + } + + pub fn set_vsync(&mut self, vsync: bool) { + unsafe { crate::set_vsync(self.ptr, vsync) } + } + + pub fn create_vertex_buffer(&mut self, vertices: &[Vertex]) { + assert!(vertices.len() < (u32::MAX as usize), "Too many triangles!"); + let ptr = vertices.as_ptr(); + let len = vertices.len(); + unsafe { crate::create_vertex_buffer(self.ptr, len as u32, ptr) } + } + + pub fn set_camera( + &mut self, + x: f32, + y: f32, + zoom: f32, + rotation: f32, + width: f32, + height: f32, + ) { + unsafe { crate::set_camera(self.ptr, x, y, zoom, rotation, width, height) } + } + + pub fn render_frame(&mut self) { + unsafe { crate::render_frame(self.ptr) } + } +} diff --git a/sys/src/window.rs b/sys/src/window.rs new file mode 100644 index 0000000..19de5e7 --- /dev/null +++ b/sys/src/window.rs @@ -0,0 +1,116 @@ +use std::ffi::{c_void, CString}; +use std::ops::ControlFlow; + +use crate::{CWindowConfig, CWindowEvent}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct WindowConfig { + pub title: String, + pub default_width: u32, + pub default_height: u32, + pub default_x: u32, + pub default_y: u32, + pub visible: bool, + pub borderless_fullscreen: bool, +} + +pub struct Window { + pub(crate) ptr: *mut (), +} + +pub enum WindowEvent { + Other = 1, + CloseRequest, + ScaleFactorChange, + Resume, + RedrawRequest, +} + +impl Drop for Window { + fn drop(&mut self) { + unsafe { crate::destroy_window(self.ptr) } + } +} + +impl Window { + pub fn new(config: WindowConfig) -> Self { + let title = CString::new(config.title.as_bytes()).unwrap(); + let config = CWindowConfig { + default_width: config.default_width, + default_height: config.default_height, + default_x: config.default_x, + default_y: config.default_y, + visible: config.visible, + borderless_fullscreen: config.borderless_fullscreen, + title: title.as_ptr(), + }; + + let window = unsafe { crate::create_window(config) }; + + Self { ptr: window } + } + + pub fn set_visible(&mut self, visible: bool) { + unsafe { crate::set_visible(self.ptr, visible) } + } + + pub fn set_title(&mut self, title: &str) { + let string = CString::new(title.to_string().as_bytes()).unwrap(); + let bytes = string.as_ptr(); + unsafe { crate::set_title(self.ptr, bytes) } + } + + pub fn resize(&mut self, width: u32, height: u32) { + unsafe { crate::resize_window(self.ptr, width, height) } + } + + pub fn set_fullscreen(&mut self, fullscreen: bool) { + unsafe { crate::set_fullscreen(self.ptr, fullscreen) } + } + + fn translate_event(event: CWindowEvent) -> Option<WindowEvent> { + let event = match event { + CWindowEvent::AboutToWait => return None, + CWindowEvent::Other => WindowEvent::Other, + CWindowEvent::CloseRequest => WindowEvent::CloseRequest, + CWindowEvent::ScaleFactorChange => WindowEvent::ScaleFactorChange, + CWindowEvent::Resume => WindowEvent::Resume, + CWindowEvent::RedrawRequest => WindowEvent::RedrawRequest, + }; + Some(event) + } + + pub fn wait_for_event(&self) { + unsafe { crate::wait_for_event(self.ptr) } + } + + pub fn pop_event(&self) -> bool { + unsafe { crate::pop_event(self.ptr) } + } + + pub fn wait_for_resume(&mut self) { + unsafe { crate::wait_for_resume(self.ptr) } + } + + pub fn run(&mut self, mut handler: impl FnMut(&mut Window, Option<WindowEvent>)) -> ! { + let window_ptr = self.ptr; + + unsafe { + let closure = |c_event: CWindowEvent| { + handler(self, Self::translate_event(c_event)); + }; + let closure_data: Box<Box<dyn FnMut(CWindowEvent)>> = Box::new(Box::new(closure)); + crate::set_event_handler(window_ptr, Box::into_raw(closure_data) as *mut _); + } + + loop { + if !self.pop_event() { + unsafe { crate::run_event_handler(window_ptr, CWindowEvent::AboutToWait) }; + } + } + } + + pub fn request_redraw(&mut self) { + unsafe { crate::request_redraw(self.ptr) } + } +} |
