summaryrefslogtreecommitdiff
path: root/engine/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-10-06 23:09:57 +0200
committerHampusM <hampus@hampusmat.com>2023-10-06 23:09:57 +0200
commitd1be0566969974bd70f2d77915b6936095c894c6 (patch)
tree255745999c57c6a12042cd535fa272bc2994ee86 /engine/src
parent5c0374e61be0ba39c89af8d3e801437255253ffb (diff)
feat: add engine library base
Diffstat (limited to 'engine/src')
-rw-r--r--engine/src/lib.rs74
-rw-r--r--engine/src/renderer/mod.rs57
-rw-r--r--engine/src/vector.rs6
3 files changed, 137 insertions, 0 deletions
diff --git a/engine/src/lib.rs b/engine/src/lib.rs
new file mode 100644
index 0000000..618bc75
--- /dev/null
+++ b/engine/src/lib.rs
@@ -0,0 +1,74 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+use glfw::Window;
+pub use glfw::WindowSize;
+
+mod renderer;
+
+pub mod vector;
+
+pub struct Engine
+{
+ window: Window,
+}
+
+impl Engine
+{
+ /// Creates and initializes a new engine.
+ ///
+ /// # Errors
+ /// Will return `Err` if window creation or window configuration fails.
+ pub fn new(window_size: &WindowSize, window_title: &str) -> Result<Self, Error>
+ {
+ let window = Window::create(window_size, window_title)
+ .map_err(Error::CreateWindowFailed)?;
+
+ window
+ .make_context_current()
+ .map_err(Error::ConfigureWindowFailed)?;
+
+ crate::renderer::initialize(&window).map_err(Error::InitializeRendererFailed)?;
+
+ Ok(Self { window })
+ }
+
+ /// Starts the engine.
+ ///
+ /// # Errors
+ /// Will return `Err` if updating the window fails.
+ pub fn start(&self, mut func: impl FnMut()) -> Result<(), Error>
+ {
+ while !self.window.should_close() {
+ func();
+
+ crate::renderer::render();
+
+ self.window
+ .swap_buffers()
+ .map_err(Error::UpdateWindowFailed)?;
+
+ self.window
+ .poll_events()
+ .map_err(Error::UpdateWindowFailed)?;
+ }
+
+ Ok(())
+ }
+}
+
+/// Engine Error
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ #[error("Failed to create window")]
+ CreateWindowFailed(#[source] glfw::Error),
+
+ #[error("Failed to configure window")]
+ ConfigureWindowFailed(#[source] glfw::Error),
+
+ #[error("Failed to initialize renderer")]
+ InitializeRendererFailed(#[source] renderer::Error),
+
+ #[error("Failed to update window")]
+ UpdateWindowFailed(#[source] glfw::Error),
+}
diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs
new file mode 100644
index 0000000..c34441c
--- /dev/null
+++ b/engine/src/renderer/mod.rs
@@ -0,0 +1,57 @@
+use std::ffi::{c_void, CString};
+use std::process::abort;
+
+use crate::vector::Vec2;
+
+pub fn initialize(window: &glfw::Window) -> Result<(), Error>
+{
+ gl::load_with(|symbol| {
+ let proc_name = unsafe { CString::from_vec_unchecked(symbol.into()) };
+
+ match window.get_proc_address(proc_name.as_c_str()) {
+ Ok(addr) => addr as *const c_void,
+ Err(err) => {
+ println!(
+ "FATAL ERROR: Failed to get adress of OpenGL function {}. {}",
+ symbol, err
+ );
+
+ abort();
+ }
+ }
+ });
+
+ let window_size = window.size().map_err(Error::GetWindowSizeFailed)?;
+
+ set_viewport(&Vec2 { x: 0, y: 0 }, &window_size);
+
+ Ok(())
+}
+
+pub fn render()
+{
+ unsafe {
+ gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
+ }
+}
+
+/// Renderer error.
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ #[error("Failed to get window size")]
+ GetWindowSizeFailed(#[source] glfw::Error),
+}
+
+fn set_viewport(position: &Vec2<u32>, size: &crate::WindowSize)
+{
+ unsafe {
+ #[allow(clippy::cast_possible_wrap)]
+ gl::Viewport(
+ position.x as i32,
+ position.y as i32,
+ size.width as i32,
+ size.height as i32,
+ );
+ }
+}
diff --git a/engine/src/vector.rs b/engine/src/vector.rs
new file mode 100644
index 0000000..92192bf
--- /dev/null
+++ b/engine/src/vector.rs
@@ -0,0 +1,6 @@
+#[derive(Debug)]
+pub struct Vec2<Value>
+{
+ pub x: Value,
+ pub y: Value,
+}