This commit is contained in:
LunarAkai 2025-08-12 16:36:47 +02:00
commit e2d5748733
41 changed files with 296 additions and 273 deletions

View file

@ -1,6 +1,6 @@
use proc_macro2::TokenStream as TokenStream2;
use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics};
use proc_macro::{self, TokenStream}; use proc_macro::{self, TokenStream};
use proc_macro2::TokenStream as TokenStream2;
use syn::{DeriveInput, GenericParam, Generics, parse_macro_input, parse_quote};
mod node; mod node;
mod system; mod system;
@ -12,8 +12,6 @@ pub fn system(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
system::system(input) system::system(input)
} }
#[proc_macro_derive(Node)] #[proc_macro_derive(Node)]
pub fn node(input: proc_macro::TokenStream) -> TokenStream { pub fn node(input: proc_macro::TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
@ -29,4 +27,4 @@ fn add_trait_bounds(mut generics: Generics) -> Generics {
} }
} }
generics generics
} }

View file

@ -21,4 +21,4 @@ pub fn node(input: DeriveInput) -> TokenStream2 {
}; };
expanded expanded
} }

View file

@ -4,7 +4,6 @@ use syn::DeriveInput;
use crate::add_trait_bounds; use crate::add_trait_bounds;
pub fn system(input: DeriveInput) -> TokenStream { pub fn system(input: DeriveInput) -> TokenStream {
let name = input.ident; let name = input.ident;

View file

@ -8,13 +8,10 @@ pub struct Component<T: ComponentType> {
component_type: T, component_type: T,
} }
pub trait ComponentType{} pub trait ComponentType {}
impl<T: ComponentType> Component<T> { impl<T: ComponentType> Component<T> {
pub fn new(id: usize, component_type: T) -> Self { pub fn new(id: usize, component_type: T) -> Self {
Self { Self { id, component_type }
id,
component_type
}
} }
} }

View file

@ -1,4 +1,7 @@
use crate::{entity, generational_index::{GenerationalIndex, GenerationalIndexAllocator}}; use crate::{
entity,
generational_index::{GenerationalIndex, GenerationalIndexAllocator},
};
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)] #[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
pub struct Entity(GenerationalIndex); pub struct Entity(GenerationalIndex);
@ -13,7 +16,6 @@ impl Entity {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EntityAllocator(GenerationalIndexAllocator); pub struct EntityAllocator(GenerationalIndexAllocator);
@ -33,4 +35,4 @@ impl EntityAllocator {
pub fn is_live(&self, entity: Entity) -> bool { pub fn is_live(&self, entity: Entity) -> bool {
self.0.is_live(entity.0) self.0.is_live(entity.0)
} }
} }

View file

@ -8,7 +8,7 @@ impl GenerationalIndex {
pub fn index(&self) -> usize { pub fn index(&self) -> usize {
self.index self.index
} }
pub fn generation(&self) -> u64 { pub fn generation(&self) -> u64 {
self.generation self.generation
} }
@ -32,7 +32,7 @@ impl GenerationalIndexAllocator {
} }
pub fn allocate(&mut self) -> GenerationalIndex { pub fn allocate(&mut self) -> GenerationalIndex {
match self.free.pop() { match self.free.pop() {
Some(index) =>{ Some(index) => {
self.entries[index].generation += 1; self.entries[index].generation += 1;
self.entries[index].is_live = true; self.entries[index].is_live = true;
@ -40,15 +40,15 @@ impl GenerationalIndexAllocator {
index, index,
generation: self.entries[index].generation, generation: self.entries[index].generation,
} }
}, }
None => { None => {
self.entries.push(AllocatorEntry { self.entries.push(AllocatorEntry {
is_live: true, is_live: true,
generation: 0, generation: 0,
}); });
GenerationalIndex { GenerationalIndex {
index: self.entries.len() -1, index: self.entries.len() - 1,
generation: 0, generation: 0,
} }
} }
@ -67,7 +67,9 @@ impl GenerationalIndexAllocator {
} }
pub fn is_live(&self, index: GenerationalIndex) -> bool { pub fn is_live(&self, index: GenerationalIndex) -> bool {
index.index() < self.entries.len() && self.entries[index.index()].generation == index.generation && self.entries[index.index()].is_live index.index() < self.entries.len()
&& self.entries[index.index()].generation == index.generation
&& self.entries[index.index()].is_live
} }
pub fn max_allocated_index(&self) -> usize { pub fn max_allocated_index(&self) -> usize {
@ -82,7 +84,7 @@ struct ArrayEntry<T> {
pub struct GenerationalIndexArray<T>(Vec<Option<ArrayEntry<T>>>); pub struct GenerationalIndexArray<T>(Vec<Option<ArrayEntry<T>>>);
impl <T> GenerationalIndexArray<T> { impl<T> GenerationalIndexArray<T> {
pub fn new() -> GenerationalIndexArray<T> { pub fn new() -> GenerationalIndexArray<T> {
GenerationalIndexArray(Vec::new()) GenerationalIndexArray(Vec::new())
} }
@ -90,9 +92,9 @@ impl <T> GenerationalIndexArray<T> {
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.0.clear(); self.0.clear();
} }
pub fn insert(&mut self, index: GenerationalIndex, value: T) { pub fn insert(&mut self, index: GenerationalIndex, value: T) {
while self.0.len() <= index.index() { while self.0.len() <= index.index() {
self.0.push(None); self.0.push(None);
} }
@ -105,9 +107,9 @@ impl <T> GenerationalIndexArray<T> {
panic!("write an index from previous gen"); panic!("write an index from previous gen");
} }
self.0[index.index()] = Some(ArrayEntry { self.0[index.index()] = Some(ArrayEntry {
value, value,
generation: index.generation(), generation: index.generation(),
}); });
} }
@ -123,12 +125,14 @@ impl <T> GenerationalIndexArray<T> {
} }
match &self.0[index.index()] { match &self.0[index.index()] {
Some(entry) => if entry.generation == index.generation() { Some(entry) => {
Some(&entry.value) if entry.generation == index.generation() {
} else { Some(&entry.value)
None } else {
}, None
None => None }
}
None => None,
} }
} }
pub fn get_mut(&mut self, index: GenerationalIndex) -> Option<&mut T> { pub fn get_mut(&mut self, index: GenerationalIndex) -> Option<&mut T> {
@ -137,12 +141,14 @@ impl <T> GenerationalIndexArray<T> {
} }
match &mut self.0[index.index()] { match &mut self.0[index.index()] {
Some(entry) => if entry.generation == index.generation() { Some(entry) => {
Some(&mut entry.value) if entry.generation == index.generation() {
} else { Some(&mut entry.value)
None } else {
}, None
None => None }
}
None => None,
} }
} }
} }

View file

@ -1,14 +1,19 @@
use std::{collections::HashMap, path::{Component, Components}}; use std::{
collections::HashMap,
path::{Component, Components},
};
use anymap::AnyMap; use anymap::AnyMap;
use crate::{entity::{Entity, EntityAllocator}, generational_index::{GenerationalIndex, GenerationalIndexAllocator, GenerationalIndexArray}}; use crate::{
entity::{Entity, EntityAllocator},
generational_index::{GenerationalIndex, GenerationalIndexAllocator, GenerationalIndexArray},
};
pub mod component;
pub mod entity;
pub mod generational_index; pub mod generational_index;
pub mod world; pub mod world;
pub mod entity;
pub mod component;
// based on: https://kyren.github.io/2018/09/14/rustconf-talk.html // based on: https://kyren.github.io/2018/09/14/rustconf-talk.html
@ -17,25 +22,25 @@ pub mod component;
Game Game
🠟 🠟
Systems Systems
(RenderSystem, PhysicsSystem, EnemyAISystem, EnemyCollisionSystem,...) (RenderSystem, PhysicsSystem, EnemyAISystem, EnemyCollisionSystem,...)
🠟 🠟
Entity Entity
🠟 🠟
Components Components
-------------------------------------- --------------------------------------
*/ */
#[derive(Debug)] #[derive(Debug)]
pub struct ECS { pub struct ECS {
entities: EntityAllocator, entities: EntityAllocator,
components: AnyMap components: AnyMap,
} }
impl ECS { impl ECS {
pub fn new() -> ECS { pub fn new() -> ECS {
ECS { ECS {
entities: EntityAllocator::new(), entities: EntityAllocator::new(),
components: AnyMap::new(), components: AnyMap::new(),
} }
} }
@ -47,9 +52,5 @@ impl ECS {
self.entities.is_live(entity) self.entities.is_live(entity)
} }
pub fn register_component() { pub fn register_component() {}
}
} }

View file

@ -2,21 +2,21 @@ use std::fmt::Error;
use anymap::AnyMap; use anymap::AnyMap;
use crate::{Entity, ECS}; use crate::{ECS, Entity};
/// stores Entitys, Components and resources /// stores Entitys, Components and resources
/// provides methods to search for specific Entitys /// provides methods to search for specific Entitys
#[derive(Debug)] #[derive(Debug)]
pub struct World { pub struct World {
ecs: ECS, ecs: ECS,
resources: AnyMap resources: AnyMap,
} }
impl World { impl World {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
ecs: ECS::new(), ecs: ECS::new(),
resources: AnyMap::new(), resources: AnyMap::new(),
} }
} }
} }

View file

@ -1,8 +1,13 @@
pub enum EventType { pub enum EventType {
None, None,
WindowClose, WindowResize, WindowClose,
KeyPressed, KeyReleased, WindowResize,
MouseButtonPressed, MouseButtonReleased, MouseMoved, MouseScrolled KeyPressed,
KeyReleased,
MouseButtonPressed,
MouseButtonReleased,
MouseMoved,
MouseScrolled,
} }
/// Base Class for Engine Events /// Base Class for Engine Events
@ -13,4 +18,3 @@ pub trait Event {
/// Emits the Event /// Emits the Event
fn emit(); fn emit();
} }

View file

@ -2,4 +2,4 @@ use crate::event::Event;
pub trait EventListener { pub trait EventListener {
fn on_event<T: Event>(event: T); fn on_event<T: Event>(event: T);
} }

View file

@ -1,7 +1,10 @@
use crate::{event::{Event, EventType}, events::key_events::KeyEvent}; use crate::{
event::{Event, EventType},
events::key_events::KeyEvent,
};
#[derive(Debug)] #[derive(Debug)]
struct KeyPressedEvent{} struct KeyPressedEvent {}
const KEY_PRESSED_EVENT_NAME: &str = "KeyPressedEvent"; const KEY_PRESSED_EVENT_NAME: &str = "KeyPressedEvent";
@ -13,12 +16,8 @@ impl Event for KeyPressedEvent {
fn get_event_type() -> EventType { fn get_event_type() -> EventType {
EventType::KeyPressed EventType::KeyPressed
} }
fn emit() { fn emit() {}
}
} }
impl super::KeyEvent for KeyPressedEvent { impl super::KeyEvent for KeyPressedEvent {}
}

View file

@ -3,7 +3,5 @@ use crate::event::Event;
pub mod key_pressed_event; pub mod key_pressed_event;
pub trait KeyEvent: Event { pub trait KeyEvent: Event {
fn get_key_code() { fn get_key_code() {}
}
}
}

View file

@ -1,3 +1,3 @@
pub mod key_events; pub mod key_events;
pub mod mouse_events; pub mod mouse_events;
pub mod window_events; pub mod window_events;

View file

@ -1,5 +1,3 @@
use crate::event::Event; use crate::event::Event;
pub trait MouseEvent: Event { pub trait MouseEvent: Event {}
}

View file

@ -2,6 +2,4 @@ pub mod window_close_event;
use crate::event::Event; use crate::event::Event;
pub trait WindowEvent: Event { pub trait WindowEvent: Event {}
}

View file

@ -1,9 +1,7 @@
use crate::{event::Event, events::window_events::WindowEvent}; use crate::{event::Event, events::window_events::WindowEvent};
#[derive(Debug)] #[derive(Debug)]
pub struct WindowCloseEvent { pub struct WindowCloseEvent {}
}
impl Event for WindowCloseEvent { impl Event for WindowCloseEvent {
fn get_event_name() -> &'static str { fn get_event_name() -> &'static str {
@ -14,10 +12,7 @@ impl Event for WindowCloseEvent {
todo!() todo!()
} }
fn emit(){ fn emit() {}
}
} }
impl WindowEvent for WindowCloseEvent { impl WindowEvent for WindowCloseEvent {}
}

View file

@ -1,4 +1,4 @@
//! Defines various Events for the Moonhare Game Engine //! Defines various Events for the Moonhare Game Engine
pub mod event; pub mod event;
pub mod event_listener; pub mod event_listener;
pub mod events; pub mod events;

View file

@ -1 +1 @@
pub mod world; pub mod world;

View file

@ -1,15 +1,14 @@
use crate::nodes::node::Node; use crate::nodes::node::Node;
/// World holds Nodes
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct World { pub struct World {
nodes: Vec<Box<dyn Node>> nodes: Vec<Box<dyn Node>>,
} }
impl World { impl World {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self { nodes: vec![] }
nodes: vec![]
}
} }
pub fn add_node(&mut self, node: Box<dyn Node>) { pub fn add_node(&mut self, node: Box<dyn Node>) {
@ -27,4 +26,4 @@ impl World {
node.update(); node.update();
} }
} }
} }

View file

@ -2,16 +2,21 @@
use std::{any::Any, rc::Rc}; use std::{any::Any, rc::Rc};
use moonhare_graphics::{
use moonhare_graphics::{color::Color, glium::{backend::Context, glutin::api::egl::context}}; color::Color,
glium::{backend::Context, glutin::api::egl::context},
};
use moonhare_log::*; use moonhare_log::*;
use moonhare_window::{platforms::glfw_window::GLFWWindow}; use moonhare_window::platforms::glfw_window::GLFWWindow;
use crate::{basic::world::{self, World}, systems::system::{BaseSystems, System}}; use crate::{
basic::world::{self, World},
systems::system::{BaseSystems, System},
};
pub mod systems;
pub mod basic; pub mod basic;
pub mod nodes; pub mod nodes;
pub mod systems;
/* #[derive(Debug)] /* #[derive(Debug)]
pub struct Game { pub struct Game {
pub base_systems: BaseSystems, pub base_systems: BaseSystems,
@ -21,32 +26,30 @@ pub struct Game {
pub name: String, pub name: String,
} */ } */
// when creating a game, you can add systems to it, which do _things_
// when creating a game, you can add systems to it, which do _things_
// BaseSystems -> Window, Update, Render // BaseSystems -> Window, Update, Render
// Hierachy: // Hierachy:
// [Game] -> <Systems> -> <Nodes> (-> <Nodes> -> ... ) // [Game] -> <World> -> <Nodes> (-> <Nodes> -> ... )
//------------- //-------------
// [ ] => only 1 --- < > => allow multiple // [ ] => only 1 --- < > => allow multiple
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Game { pub struct Game {
pub world: Vec<World>, pub world: Vec<World>,
pub is_running: bool pub is_running: bool,
} }
impl Default for Game { impl Default for Game {
fn default() -> Self { fn default() -> Self {
Self { Self {
world: vec![], world: vec![],
is_running: true is_running: true,
} }
} }
} }
pub struct GraphicsHandler { pub struct GraphicsHandler {
pub context: Option<Rc<Context>> pub context: Option<Rc<Context>>,
} }
impl Default for GraphicsHandler { impl Default for GraphicsHandler {
@ -81,12 +84,8 @@ impl Game {
} }
} }
} }
} }
fn default_game_name() -> String { fn default_game_name() -> String {
"Moonhare Game".to_owned() "Moonhare Game".to_owned()
} }

View file

@ -8,21 +8,14 @@ pub trait Node: DynClone {
} }
dyn_clone::clone_trait_object!(Node); dyn_clone::clone_trait_object!(Node);
impl Debug for dyn Node { impl Debug for dyn Node {
fn fmt(&self, f: &mut Formatter<'_>) -> Result { fn fmt(&self, f: &mut Formatter<'_>) -> Result {
writeln!(f, "") writeln!(f, "")
} }
} }
impl<T: Clone> Node for Box<T> { impl<T: Clone> Node for Box<T> {
fn init(&mut self) { fn init(&mut self) {}
}
fn update(&mut self) { fn update(&mut self) {}
}
} }

View file

@ -1,23 +1,26 @@
use std::rc::Rc; use std::rc::Rc;
use crate::nodes::node::Node;
use moonhare_derives::Node; use moonhare_derives::Node;
use moonhare_graphics::{color::Color, glium::backend::Context}; use moonhare_graphics::{color::Color, glium::backend::Context};
use moonhare_window::{glfw::RenderContext, platforms::glfw_window::{self, GLFWWindow}}; use moonhare_window::{
use crate::nodes::node::Node; glfw::RenderContext,
platforms::glfw_window::{self, GLFWWindow},
};
#[derive(Node, Clone)] #[derive(Node, Clone)]
pub struct Window { pub struct Window {
context: moonhare_window::WindowRenderContext, context: moonhare_window::WindowRenderContext,
glfw_window: Option<moonhare_window::platforms::glfw_window::GLFWWindow>, glfw_window: Option<moonhare_window::platforms::glfw_window::GLFWWindow>,
render_context: Option<Rc<Context>> render_context: Option<Rc<Context>>,
} }
impl Default for Window { impl Default for Window {
fn default() -> Self { fn default() -> Self {
Self { Self {
context: moonhare_window::WindowRenderContext::OPENGLGLFW, context: moonhare_window::WindowRenderContext::OPENGLGLFW,
glfw_window: None, glfw_window: None,
render_context: None render_context: None,
} }
} }
} }
@ -27,7 +30,9 @@ impl Window {
Self { Self {
context: moonhare_window::WindowRenderContext::OPENGLGLFW, context: moonhare_window::WindowRenderContext::OPENGLGLFW,
glfw_window: Some(moonhare_window::Window::create(self.context)), glfw_window: Some(moonhare_window::Window::create(self.context)),
render_context: Some(moonhare_graphics::build_context(self.glfw_window.clone().unwrap().glfw_window)) render_context: Some(moonhare_graphics::build_context(
self.glfw_window.clone().unwrap().glfw_window,
)),
} }
} }
@ -40,11 +45,15 @@ impl Window {
fn handle_window_event(glfw_window: &GLFWWindow) { fn handle_window_event(glfw_window: &GLFWWindow) {
glfw_window.glfw_window.borrow_mut().glfw.poll_events(); glfw_window.glfw_window.borrow_mut().glfw.poll_events();
for (_, event) in moonhare_window::glfw::flush_messages(&glfw_window.events.borrow()) { for (_, event) in moonhare_window::glfw::flush_messages(&glfw_window.events.borrow()) {
moonhare_window::platforms::glfw_window::GLFWWindow::handle_window_event(&glfw_window, event); moonhare_window::platforms::glfw_window::GLFWWindow::handle_window_event(
} &glfw_window,
event,
);
}
} }
fn render(context: Rc<Context>) { fn render(context: Rc<Context>) {
let target = moonhare_graphics::glium::Frame::new(context.clone(), context.get_framebuffer_dimensions()); let target =
moonhare_graphics::glium::Frame::new(context.clone(), context.get_framebuffer_dimensions());
moonhare_graphics::draw_background_color(Color::color_from_rgb(255, 255, 255), target); moonhare_graphics::draw_background_color(Color::color_from_rgb(255, 255, 255), target);
} }

View file

@ -1,4 +1,4 @@
pub mod render_system;
pub mod system; pub mod system;
pub mod window_system;
pub mod update_system; pub mod update_system;
pub mod render_system; pub mod window_system;

View file

@ -3,13 +3,9 @@ pub struct RenderSystem;
impl Default for RenderSystem { impl Default for RenderSystem {
fn default() -> Self { fn default() -> Self {
Self { Self {}
}
} }
} }
impl RenderSystem { impl RenderSystem {
pub(crate) fn update(&self) { pub(crate) fn update(&self) {}
}
}
}

View file

@ -1,6 +1,8 @@
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use crate::systems::{render_system::RenderSystem, update_system::UpdateSystem, window_system::WindowSystem}; use crate::systems::{
render_system::RenderSystem, update_system::UpdateSystem, window_system::WindowSystem,
};
/// Systems are collections of related High Level Game Logic /// Systems are collections of related High Level Game Logic
/// Systems can have Nodes as children /// Systems can have Nodes as children
@ -10,7 +12,7 @@ pub trait System {}
impl Debug for dyn System { impl Debug for dyn System {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
writeln!(f, "") writeln!(f, "")
} }
} }
// todo: make this more generic so that new systems can be added by the game application it self // todo: make this more generic so that new systems can be added by the game application it self
@ -26,10 +28,10 @@ pub struct BaseSystems {
impl BaseSystems { impl BaseSystems {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
window_system: WindowSystem::default(), window_system: WindowSystem::default(),
update_system: UpdateSystem, update_system: UpdateSystem,
render_system: RenderSystem render_system: RenderSystem,
} }
} }
pub fn game_loop(&self) { pub fn game_loop(&self) {
@ -37,6 +39,6 @@ impl BaseSystems {
self.update_system.update(); self.update_system.update();
self.render_system.update(); self.render_system.update();
} }
} }

View file

@ -3,13 +3,10 @@ pub struct UpdateSystem;
impl Default for UpdateSystem { impl Default for UpdateSystem {
fn default() -> Self { fn default() -> Self {
Self { Self {}
}
} }
} }
impl UpdateSystem { impl UpdateSystem {
pub(crate) fn update(&self) { pub(crate) fn update(&self) {}
}
}
}

View file

@ -6,15 +6,13 @@ pub struct WindowSystem {
impl Default for WindowSystem { impl Default for WindowSystem {
fn default() -> Self { fn default() -> Self {
Self { Self {
context: moonhare_window::WindowRenderContext::OPENGLGLFW, context: moonhare_window::WindowRenderContext::OPENGLGLFW,
glfw_window: None glfw_window: None,
} }
} }
} }
impl WindowSystem { impl WindowSystem {
pub(crate) fn update(&self) { pub(crate) fn update(&self) {}
}
}
}

View file

@ -1,9 +1,12 @@
use std::{cell::RefCell, ffi::{c_void, CString}, rc::Rc}; use std::{
cell::RefCell,
ffi::{CString, c_void},
rc::Rc,
};
use glium::SwapBuffersError; use glium::SwapBuffersError;
use moonhare_window::glfw::Context; use moonhare_window::glfw::Context;
// adopted from the glium repo -> examples -> manual_creation.rs // adopted from the glium repo -> examples -> manual_creation.rs
#[derive(Clone)] #[derive(Clone)]
pub struct Backend { pub struct Backend {
@ -11,34 +14,36 @@ pub struct Backend {
} }
unsafe impl glium::backend::Backend for Backend { unsafe impl glium::backend::Backend for Backend {
fn swap_buffers(&self) -> Result<(), SwapBuffersError> { fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
self.gl_window.borrow_mut().swap_buffers(); self.gl_window.borrow_mut().swap_buffers();
Ok(()) Ok(())
} }
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void { unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
let symbol = CString::new(symbol).unwrap(); let symbol = CString::new(symbol).unwrap();
self.gl_window self.gl_window
.borrow_mut() .borrow_mut()
.get_proc_address(&symbol.to_str().unwrap()) as *const _ .get_proc_address(&symbol.to_str().unwrap()) as *const _
} }
fn get_framebuffer_dimensions(&self) -> (u32, u32) { fn get_framebuffer_dimensions(&self) -> (u32, u32) {
let window = &self.gl_window.borrow(); let window = &self.gl_window.borrow();
(window.get_size().0 as u32, window.get_size().1 as u32) (window.get_size().0 as u32, window.get_size().1 as u32)
} }
fn resize(&self, new_size: (u32, u32)) { fn resize(&self, new_size: (u32, u32)) {
let _ = &self.gl_window.borrow_mut().set_size(new_size.0 as i32, new_size.1 as i32); let _ = &self
} .gl_window
.borrow_mut()
.set_size(new_size.0 as i32, new_size.1 as i32);
}
fn is_current(&self) -> bool { fn is_current(&self) -> bool {
self.gl_window.borrow().is_current() self.gl_window.borrow().is_current()
} }
unsafe fn make_current(&self) { unsafe fn make_current(&self) {
let mut gl_window = self.gl_window.borrow_mut(); let mut gl_window = self.gl_window.borrow_mut();
gl_window.make_current(); gl_window.make_current();
} }
}
}

View file

@ -2,28 +2,38 @@ pub struct Color {
pub red: f32, pub red: f32,
pub green: f32, pub green: f32,
pub blue: f32, pub blue: f32,
pub alpha: f32 pub alpha: f32,
} }
impl Color { impl Color {
/// Color Values from 0 - 255 /// Color Values from 0 - 255
/// For example: 255, 255, 255 -> White /// For example: 255, 255, 255 -> White
pub fn color_from_rgb(red: i32, green: i32, blue: i32) -> Self { pub fn color_from_rgb(red: i32, green: i32, blue: i32) -> Self {
// 255 -> 1.0 // 255 -> 1.0
// 0 -> 0.0 // 0 -> 0.0
let r: f32 = red as f32/ 255.0; let r: f32 = red as f32 / 255.0;
let g: f32 = green as f32 / 255.0; let g: f32 = green as f32 / 255.0;
let b: f32 = blue as f32/ 255.0; let b: f32 = blue as f32 / 255.0;
Self { red: r, green: g, blue: b, alpha: 1.0 } Self {
red: r,
green: g,
blue: b,
alpha: 1.0,
}
} }
pub fn color_from_rgba(red: i32, green: i32, blue: i32, alpha: f32) -> Self { pub fn color_from_rgba(red: i32, green: i32, blue: i32, alpha: f32) -> Self {
// 255 -> 1.0 // 255 -> 1.0
// 0 -> 0.0 // 0 -> 0.0
let r: f32 = red as f32 / 255.0; let r: f32 = red as f32 / 255.0;
let g: f32 = green as f32 / 255.0; let g: f32 = green as f32 / 255.0;
let b: f32 = blue as f32 / 255.0; let b: f32 = blue as f32 / 255.0;
let a: f32 = alpha; let a: f32 = alpha;
Self { red: r, green: g, blue: b, alpha: a } Self {
red: r,
green: g,
blue: b,
alpha: a,
}
} }
} }

View file

@ -1,22 +1,29 @@
//! Crate for providing an abstraction layer over different graphics APIs //! Crate for providing an abstraction layer over different graphics APIs
use std::{cell::{Cell, RefCell}, rc::Rc, sync::{Arc, Mutex, RwLock}}; use std::{
cell::{Cell, RefCell},
rc::Rc,
sync::{Arc, Mutex, RwLock},
};
use glium::{backend::{Context, Facade}, Frame, Surface}; use glium::{
Frame, Surface,
backend::{Context, Facade},
};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use moonhare_window::glfw::PWindow; use moonhare_window::glfw::PWindow;
pub mod shader;
pub mod backend; pub mod backend;
pub mod vertices;
pub mod color; pub mod color;
pub mod shader;
pub mod vertices;
pub use glium; pub use glium;
use state::InitCell; use state::InitCell;
use crate::color::Color; use crate::color::Color;
pub fn build_context(window: Rc<RefCell<PWindow>>) -> Rc<Context>{ pub fn build_context(window: Rc<RefCell<PWindow>>) -> Rc<Context> {
let gl_window: Rc<RefCell<PWindow>> = window; let gl_window: Rc<RefCell<PWindow>> = window;
// now building the context // now building the context
let context = unsafe { let context = unsafe {
// The first parameter is our backend. // The first parameter is our backend.
@ -38,4 +45,4 @@ pub fn build_context(window: Rc<RefCell<PWindow>>) -> Rc<Context>{
pub fn draw_background_color(color: Color, mut target: Frame) { pub fn draw_background_color(color: Color, mut target: Frame) {
Surface::clear_color(&mut target, color.red, color.green, color.blue, color.alpha); Surface::clear_color(&mut target, color.red, color.green, color.blue, color.alpha);
target.finish().unwrap() target.finish().unwrap()
} }

View file

@ -1,4 +1,4 @@
pub enum ShaderType { pub enum ShaderType {
Vertex, Vertex,
Fragment, Fragment,
} }

View file

@ -1 +1 @@
pub mod vertex; pub mod vertex;

View file

@ -4,4 +4,4 @@ pub use moonhare_event as event;
pub use moonhare_game as game; pub use moonhare_game as game;
pub use moonhare_graphics as graphics; pub use moonhare_graphics as graphics;
pub use moonhare_log as log; pub use moonhare_log as log;
pub use moonhare_window as window; pub use moonhare_window as window;

View file

@ -2,16 +2,19 @@
use std::{fmt::Display, io, time::SystemTime}; use std::{fmt::Display, io, time::SystemTime};
/// Configures the Log Output Settings /// Configures the Log Output Settings
pub fn configere_logger() -> Result<(), fern::InitError>{ pub fn configere_logger() -> Result<(), fern::InitError> {
let base_config = fern::Dispatch::new().level(log::LevelFilter::Info); let base_config = fern::Dispatch::new().level(log::LevelFilter::Info);
// configure colors for the whole line // configure colors for the whole line
let colors_line = fern::colors::ColoredLevelConfig::new() let colors_line = fern::colors::ColoredLevelConfig::new()
.error(fern::colors::Color::Red) .error(fern::colors::Color::Red)
.warn(fern::colors::Color::Yellow) .warn(fern::colors::Color::Yellow)
// we actually don't need to specify the color for debug and info, they are white by default // we actually don't need to specify the color for debug and info, they are white by default
.info(fern::colors::Color::TrueColor { r: 85, g: 85, b: 85 }) .info(fern::colors::Color::TrueColor {
r: 85,
g: 85,
b: 85,
})
.debug(fern::colors::Color::White) .debug(fern::colors::Color::White)
// depending on the terminals color scheme, this is the same as the background color // depending on the terminals color scheme, this is the same as the background color
.trace(fern::colors::Color::Black); .trace(fern::colors::Color::Black);
@ -29,7 +32,6 @@ pub fn configere_logger() -> Result<(), fern::InitError>{
}) })
.chain(fern::log_file("moonhare_engine.log")?); .chain(fern::log_file("moonhare_engine.log")?);
let stdout_config = fern::Dispatch::new() let stdout_config = fern::Dispatch::new()
.format(move |out, message, record| { .format(move |out, message, record| {
// special format for debug messages coming from our own crate. // special format for debug messages coming from our own crate.
@ -82,5 +84,3 @@ pub fn trace<T: Display>(arg: T) {
pub fn error<T: Display>(arg: T) { pub fn error<T: Display>(arg: T) {
log::error!("{}", arg); log::error!("{}", arg);
} }

View file

@ -1,7 +1,7 @@
//! Provides functionality to create either a vulkan or opengl window //! Provides functionality to create either a vulkan or opengl window
pub mod window_config;
pub mod platforms; pub mod platforms;
pub use glfw as glfw; pub mod window_config;
pub use glfw;
use crate::platforms::glfw_window::GLFWWindow; use crate::platforms::glfw_window::GLFWWindow;
@ -10,8 +10,7 @@ pub enum WindowRenderContext {
OPENGLGLFW, OPENGLGLFW,
} }
pub trait WindowResult { pub trait WindowResult {}
}
pub trait MoonhareWindow { pub trait MoonhareWindow {
fn init() -> GLFWWindow; fn init() -> GLFWWindow;
@ -19,9 +18,7 @@ pub trait MoonhareWindow {
fn shutdown(); fn shutdown();
} }
pub struct Window { pub struct Window {}
}
impl Window { impl Window {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -39,4 +36,4 @@ impl Window {
pub fn create() { pub fn create() {
todo!("moonhare engine only supports linux for now") todo!("moonhare engine only supports linux for now")
} }
} }

View file

@ -3,11 +3,11 @@ use std::{cell::RefCell, rc::Rc, sync::Arc};
use glfw::{Context, Glfw, GlfwReceiver, PWindow, Window, WindowEvent}; use glfw::{Context, Glfw, GlfwReceiver, PWindow, Window, WindowEvent};
use moonhare_event::{event::Event, events::window_events::window_close_event::WindowCloseEvent}; use moonhare_event::{event::Event, events::window_events::window_close_event::WindowCloseEvent};
use crate::{window_config, MoonhareWindow}; use crate::{MoonhareWindow, window_config};
#[derive(Debug)] #[derive(Debug)]
pub struct GLFWWindow { pub struct GLFWWindow {
// Todo: learn more about rust smart pointers so i actually understand whats going on here, but hey it works for now // Todo: learn more about rust smart pointers so i actually understand whats going on here, but hey it works for now
pub glfw_window: Rc<RefCell<PWindow>>, pub glfw_window: Rc<RefCell<PWindow>>,
pub events: Rc<RefCell<GlfwReceiver<(f64, WindowEvent)>>>, pub events: Rc<RefCell<GlfwReceiver<(f64, WindowEvent)>>>,
pub glfw: Glfw, pub glfw: Glfw,
@ -18,7 +18,12 @@ const APP_ID: &str = "de.lunarakai.moonhare_engine";
impl Clone for GLFWWindow { impl Clone for GLFWWindow {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { glfw_window: self.glfw_window.clone(), events: self.events.clone(), glfw: self.glfw.clone(), is_running: self.is_running.clone() } Self {
glfw_window: self.glfw_window.clone(),
events: self.events.clone(),
glfw: self.glfw.clone(),
is_running: self.is_running.clone(),
}
} }
} }
@ -26,11 +31,13 @@ impl GLFWWindow {
fn new() -> Self { fn new() -> Self {
let mut glfw = glfw::init(glfw::fail_on_errors).unwrap(); let mut glfw = glfw::init(glfw::fail_on_errors).unwrap();
let config = window_config::WindowConfig::default(); let config = window_config::WindowConfig::default();
let (mut window, events) = glfw.create_window( let (mut window, events) = glfw
config.width, .create_window(
config.height, config.width,
format!("{} GLFW {}", config.title, glfw::get_version_string()).as_str(), config.height,
glfw::WindowMode::Windowed) format!("{} GLFW {}", config.title, glfw::get_version_string()).as_str(),
glfw::WindowMode::Windowed,
)
.unwrap(); .unwrap();
window.set_key_polling(true); window.set_key_polling(true);
@ -40,36 +47,29 @@ impl GLFWWindow {
glfw_window: Rc::new(RefCell::new(window)), glfw_window: Rc::new(RefCell::new(window)),
events: Rc::new(RefCell::new(events)), events: Rc::new(RefCell::new(events)),
glfw: glfw, glfw: glfw,
is_running: true is_running: true,
} }
} }
pub fn handle_window_event(&self, event: glfw::WindowEvent) { pub fn handle_window_event(&self, event: glfw::WindowEvent) {
match event { match event {
glfw::WindowEvent::Close => { glfw::WindowEvent::Close => {
WindowCloseEvent::emit(); WindowCloseEvent::emit();
} }
_ => {}, _ => {}
} }
} }
} }
impl MoonhareWindow for GLFWWindow { impl MoonhareWindow for GLFWWindow {
fn init() -> GLFWWindow { fn init() -> GLFWWindow {
let window = GLFWWindow::new(); let window = GLFWWindow::new();
window window
} }
fn on_update() {}
fn on_update() {
}
fn shutdown() { fn shutdown() {
// todo: emit WindowCloseEvent // todo: emit WindowCloseEvent
} }
} }

View file

@ -1 +1 @@
pub mod glfw_window; pub mod glfw_window;

View file

@ -10,9 +10,9 @@ pub struct WindowConfig {
impl Default for WindowConfig { impl Default for WindowConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
title: "Moonhare Engine".to_owned(), title: "Moonhare Engine".to_owned(),
width: 1280, width: 1280,
height: 720, height: 720,
visble: default_visibility(), visble: default_visibility(),
decorations: default_decorations(), decorations: default_decorations(),
@ -25,7 +25,7 @@ impl WindowConfig {
fn set_window_name(mut self, name: String) { fn set_window_name(mut self, name: String) {
self.title = name; self.title = name;
} }
fn set_window_height(mut self, new_height: u32) { fn set_window_height(mut self, new_height: u32) {
self.height = new_height; self.height = new_height;
} }
@ -49,4 +49,4 @@ fn default_visibility() -> bool {
fn default_decorations() -> bool { fn default_decorations() -> bool {
true true
} }

14
justfile Normal file
View file

@ -0,0 +1,14 @@
run:
cargo run
test:
cargo test --verbose
doc:
cargo doc --no-deps --package moonhare_engine
fmt:
cargo fmt
push commit_message:
./push_to_git.sh "{{commit_message}}"

View file

@ -11,11 +11,11 @@ Game: (not a node, only one game may exist)
- Node - Node
- ... - ...
- Scene2 (node) - Scene2 (node)
- ... - ...
------------------ ------------------
Node Node
- Optional<Components> - Optional<Components>
- Optional<Script> - Optional<Script>
----------------------- -----------------------
*/ */

View file

@ -1,12 +1,14 @@
use std::fs::File; use std::fs::File;
use moonhare_engine::{game::{basic::world::World, nodes::window::Window, Game}, log}; use moonhare_engine::{
game::{Game, basic::world::World, nodes::window::Window},
log,
};
fn main() { fn main() {
let _ = log::configere_logger(); let _ = log::configere_logger();
log::info("test"); log::info("test");
let mut game = Game::new(); let mut game = Game::new();
let mut world = World::new(); let mut world = World::new();
@ -14,4 +16,4 @@ fn main() {
world.add_node(Box::new(window)); world.add_node(Box::new(window));
game.add_world(world.clone()); game.add_world(world.clone());
log::info(format!("{:?}", game.get_worlds())); log::info(format!("{:?}", game.get_worlds()));
} }