diff --git a/crates/comet_app/src/app.rs b/crates/comet_app/src/app.rs index 888fc2a..14998f5 100755 --- a/crates/comet_app/src/app.rs +++ b/crates/comet_app/src/app.rs @@ -33,6 +33,7 @@ pub struct App { game_state: Option>, audio: Box, scene: Scene, + fullscreen: bool, should_quit: bool, } @@ -50,6 +51,7 @@ impl App { game_state: None, audio: Box::new(KiraAudio::new()), scene: Scene::new(), + fullscreen: false, should_quit: false, } } @@ -370,7 +372,6 @@ impl App { } } - #[allow(unused_variables)] match event { Event::WindowEvent { ref event, diff --git a/crates/comet_ecs/component_derive/src/lib.rs b/crates/comet_ecs/component_derive/src/lib.rs index 79355e9..cd4c2d3 100755 --- a/crates/comet_ecs/component_derive/src/lib.rs +++ b/crates/comet_ecs/component_derive/src/lib.rs @@ -2,12 +2,16 @@ extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, Data, DeriveInput, Fields}; +use syn::{parse_macro_input, DeriveInput, Data, Fields}; +// This is the procedural macro for `derive(MyTrait)` #[proc_macro_derive(Component)] -pub fn component_derive(input: TokenStream) -> TokenStream { +pub fn my_trait_derive(input: TokenStream) -> TokenStream { + // Parse the input tokens into a syntax tree (AST) let input = parse_macro_input!(input as DeriveInput); + // Get the name of the struct + let name = &input.ident; let name = &input.ident; let fields = if let Data::Struct(data) = &input.data { @@ -29,21 +33,19 @@ pub fn component_derive(input: TokenStream) -> TokenStream { let default_fields = if let Data::Struct(data) = &input.data { match &data.fields { - Fields::Named(fields) => fields - .named - .iter() - .map(|field| { + Fields::Named(fields) => { + // Generate code to assign each field a default value + fields.named.iter().map(|field| { let field_name = &field.ident; quote! { #field_name: Default::default() } - }) - .collect::>(), - Fields::Unnamed(fields) => fields - .unnamed - .iter() - .map(|_field| { + }).collect::>() + }, + Fields::Unnamed(fields) => { + // Generate default values for tuple structs + fields.unnamed.iter().map(|_field| { quote! { Default::default() } - }) - .collect::>(), + }).collect::>() + }, Fields::Unit => Vec::new(), } } else { @@ -57,6 +59,13 @@ pub fn component_derive(input: TokenStream) -> TokenStream { } }); + for field in &fields { + if !is_copy_field(&field) { + panic!("All fields in the struct must implement Copy"); + } + } + + // Generate the implementation of MyTrait for the given struct let expanded = quote! { impl Component for #name { fn new() -> Self { @@ -74,6 +83,7 @@ pub fn component_derive(input: TokenStream) -> TokenStream { impl Default for #name { fn default() -> Self { + // Construct the struct with default values Self { #(#default_fields),* } @@ -105,5 +115,16 @@ pub fn component_derive(input: TokenStream) -> TokenStream { } }; + // Convert the generated code into a TokenStream and return it TokenStream::from(expanded) } + + +fn is_copy_field(field: &syn::Field) -> bool { + // Logic to check if the field type implements Copy (this is simplified) + // You might need more sophisticated logic to check the actual type of the field. + let field_type = &field.ty; + // Implement a check for Copy trait for the field type if needed + // Return true if it implements Copy; false otherwise + true // Assuming it does, just for simplicity +} \ No newline at end of file diff --git a/crates/comet_ecs/src/archetypes.rs b/crates/comet_ecs/src/archetypes.rs index c6ccd11..62c023f 100755 --- a/crates/comet_ecs/src/archetypes.rs +++ b/crates/comet_ecs/src/archetypes.rs @@ -1,47 +1,59 @@ -use comet_structs::ComponentSet; use std::collections::{HashMap, HashSet}; +use comet_structs::ComponentSet; #[derive(Debug, Clone)] pub struct Archetypes { - archetypes: HashMap>, + archetypes: HashMap> } impl Archetypes { - pub fn new() -> Self { - Self { - archetypes: HashMap::new(), - } - } + pub fn new() -> Self { + Self { + archetypes: HashMap::new() + } + } - pub fn component_sets(&self) -> Vec { - self.archetypes.keys().cloned().collect() - } + pub fn component_sets(&self) -> Vec { + self.archetypes.keys().cloned().collect() + } - pub fn create_archetype(&mut self, components: ComponentSet) { - self.archetypes.insert(components, HashSet::new()); - } + pub fn create_archetype(&mut self, components: ComponentSet) { + self.archetypes.insert(components, HashSet::new()); + } - pub fn get_archetype(&self, components: &ComponentSet) -> Option<&HashSet> { - self.archetypes.get(components) - } + pub fn get_archetype(&self, components: &ComponentSet) -> Option<&HashSet> { + self.archetypes.get(components) + } - pub fn add_entity_to_archetype(&mut self, components: &ComponentSet, entity: u32) { - if let Some(archetype) = self.archetypes.get_mut(components) { - archetype.insert(entity); - } - } + pub fn get_archetype_mut(&mut self, components: &ComponentSet) -> Option<&mut HashSet> { + self.archetypes.get_mut(components) + } - pub fn remove_entity_from_archetype(&mut self, components: &ComponentSet, entity: u32) { - if let Some(archetype) = self.archetypes.get_mut(components) { - archetype.retain(|&id| id != entity); - } - } + pub fn add_entity_to_archetype(&mut self, components: &ComponentSet, entity: u32) { + if let Some(archetype) = self.archetypes.get_mut(components) { + archetype.insert(entity); + } + } - pub fn remove_archetype(&mut self, components: &ComponentSet) { - self.archetypes.remove(components); - } + pub fn remove_entity_from_archetype(&mut self, components: &ComponentSet, entity: u32) { + if let Some(archetype) = self.archetypes.get_mut(components) { + archetype.retain(|&id| id != entity); + } + } - pub fn contains_archetype(&self, components: &ComponentSet) -> bool { - self.archetypes.contains_key(components) - } -} + pub fn remove_archetype(&mut self, components: &ComponentSet) { + self.archetypes.remove(components); + } + + pub fn contains_archetype(&self, components: &ComponentSet) -> bool { + self.archetypes.contains_key(components) + } + + pub fn archetype_contains_entity(&self, entity_id: u32, components: &ComponentSet) -> bool { + if self.contains_archetype(components) { + let archetype = self.get_archetype(components).unwrap(); + return archetype.contains(&entity_id); + } + false + } +} \ No newline at end of file diff --git a/crates/comet_input/src/input_handler.rs b/crates/comet_input/src/input_handler.rs index eafc8f6..a3113bc 100644 --- a/crates/comet_input/src/input_handler.rs +++ b/crates/comet_input/src/input_handler.rs @@ -1,81 +1,73 @@ -use crate::keyboard::Key; -use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; +use winit::event::{ElementState, WindowEvent, KeyEvent, Event}; +use std::collections::HashSet; +use winit::event::WindowEvent::KeyboardInput; use winit::keyboard::PhysicalKey; +use crate::keyboard::Key; #[derive(Debug)] pub struct InputHandler { - keys_pressed: Vec, - keys_held: Vec, - keys_released: Vec, + keys_pressed: Vec, + keys_held: Vec, + keys_released: Vec } impl InputHandler { - pub fn new() -> Self { - Self { - keys_pressed: Vec::new(), - keys_held: Vec::new(), - keys_released: Vec::new(), - } - } + pub fn new() -> Self { + Self { + keys_pressed: Vec::new(), + keys_held: Vec::new(), + keys_released: Vec::new() + } + } - pub fn update(&mut self, event: &Event) { - match event { - Event::WindowEvent { - event: - WindowEvent::KeyboardInput { - event: - KeyEvent { - state, - physical_key: PhysicalKey::Code(keycode), - .. - }, - .. - }, - .. - } => match state { - ElementState::Pressed => { - if self - .keys_pressed - .contains(&PhysicalKey::Code(keycode.clone())) - { - self.keys_held.push(PhysicalKey::Code(keycode.clone())); - } else { - self.keys_pressed.push(PhysicalKey::Code(keycode.clone())); - } - self.keys_pressed.push(PhysicalKey::Code(keycode.clone())); - } - ElementState::Released => { - self.keys_released = vec![]; - if let Some(index) = self - .keys_pressed - .iter() - .position(|&x| x == PhysicalKey::Code(keycode.clone())) - { - self.keys_pressed.remove(index); - } - if let Some(index) = self - .keys_held - .iter() - .position(|&x| x == PhysicalKey::Code(keycode.clone())) - { - self.keys_held.remove(index); - } - self.keys_released.push(PhysicalKey::Code(keycode.clone())); - } - }, - _ => {} - } - } + pub fn update(&mut self, event: &Event) { + match event { + Event::WindowEvent { + event: WindowEvent::KeyboardInput { + event: KeyEvent { + state, + physical_key: PhysicalKey::Code(keycode), + .. + }, + .. + }, + .. + } => + { + match state { + ElementState::Pressed => { + if self.keys_pressed.contains(&PhysicalKey::Code(keycode.clone())) { + self.keys_held.push(PhysicalKey::Code(keycode.clone())); + } else { + self.keys_pressed.push(PhysicalKey::Code(keycode.clone())); + } + self.keys_pressed.push(PhysicalKey::Code(keycode.clone())); + } + ElementState::Released => { + self.keys_released = vec![]; + if let Some(index) = self.keys_pressed.iter().position(|&x| x == PhysicalKey::Code(keycode.clone())) { + self.keys_pressed.remove(index); + } + if let Some(index) = self.keys_held.iter().position(|&x| x == PhysicalKey::Code(keycode.clone())) { + self.keys_held.remove(index); + } + self.keys_released.push(PhysicalKey::Code(keycode.clone())); + } + } + } + _ => {} + } + } - pub fn key_pressed(&self, key: Key) -> bool { - self.keys_pressed.contains(&PhysicalKey::Code(key)) - } + pub fn key_pressed(&self, key: Key) -> bool { + self.keys_pressed.contains(&PhysicalKey::Code(key)) + } - pub fn key_held(&self, key: Key) -> bool { - self.keys_held.contains(&PhysicalKey::Code(key)) - } + pub fn key_held(&self, key: Key) -> bool { + self.keys_held.contains(&PhysicalKey::Code(key)) + } - pub fn key_released(&self, key: Key) -> bool { - self.keys_released.contains(&PhysicalKey::Code(key)) - } + pub fn key_released(&self, key: Key) -> bool { + self.keys_released.contains(&PhysicalKey::Code(key)) + } } diff --git a/crates/comet_math/Cargo.toml b/crates/comet_math/Cargo.toml index d0aaf64..af49077 100644 --- a/crates/comet_math/Cargo.toml +++ b/crates/comet_math/Cargo.toml @@ -7,5 +7,4 @@ edition = "2021" comet_log = { path = "../comet_log" } rand = "0.9.0-beta.1" image = { version = "0.24", default_features = false, features = ["png", "jpeg", "hdr"] } -chrono = "0.4.40" -serde = { version = "1.0", features = ["derive"] } +chrono = "0.4.40" \ No newline at end of file diff --git a/crates/comet_math/src/bezier.rs b/crates/comet_math/src/bezier.rs index 3c16dfd..89458c6 100644 --- a/crates/comet_math/src/bezier.rs +++ b/crates/comet_math/src/bezier.rs @@ -1,4 +1,4 @@ -use crate::InnerSpace; +use crate::{InnerSpace, Point}; /// Representation of a Bezier curve of degree n in any (2-4) dimensions. pub struct Bezier { diff --git a/crates/comet_math/src/matrix.rs b/crates/comet_math/src/matrix.rs index 81fb3d6..4a9c501 100644 --- a/crates/comet_math/src/matrix.rs +++ b/crates/comet_math/src/matrix.rs @@ -1,7 +1,6 @@ use crate::vector::{v2, v3, v4}; use std::ops::*; -#[allow(dead_code)] trait LinearTransformation { fn det(&self) -> f32; } @@ -13,7 +12,6 @@ trait LinearTransformation { /// Representation of a 2x2 matrix. #[repr(C)] #[derive(Debug, PartialEq)] -#[allow(non_camel_case_types)] pub struct m2 { x00: f32, x01: f32, @@ -210,7 +208,6 @@ impl Into<[[f32; 2]; 2]> for m2 { /// Representation of a 3x3 matrix. #[repr(C)] #[derive(Debug, PartialEq)] -#[allow(non_camel_case_types)] pub struct m3 { x00: f32, x01: f32, @@ -500,7 +497,6 @@ impl Into<[[f32; 3]; 3]> for m3 { /// Representation of a 4x4 matrix. #[repr(C)] #[derive(Debug, PartialEq)] -#[allow(non_camel_case_types)] pub struct m4 { x00: f32, x01: f32, diff --git a/crates/comet_math/src/noise.rs b/crates/comet_math/src/noise.rs index 62f155d..f6ddbea 100644 --- a/crates/comet_math/src/noise.rs +++ b/crates/comet_math/src/noise.rs @@ -323,12 +323,9 @@ impl ValueNoise { let mut f = 0.0; let mut amplitude = 0.5; - for _ in 0..4 { - f += amplitude * self.noise(uv); - uv = (uv.0 * 2.0, uv.1 * 2.0); - amplitude *= 0.5; - } - + f += amplitude * self.noise(uv); + uv = (uv.0 * 2.0, uv.1 * 2.0); + amplitude *= 0.5; f = ((f / max_amplitude) + 1.0) * 0.5; noise.push(f); diff --git a/crates/comet_math/src/point.rs b/crates/comet_math/src/point.rs index edc5cc4..51ef279 100644 --- a/crates/comet_math/src/point.rs +++ b/crates/comet_math/src/point.rs @@ -7,7 +7,6 @@ pub trait Point { } /// Representation of a 2D point. -#[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy, PartialEq)] pub struct p2 { x: f32, @@ -37,7 +36,6 @@ impl p2 { } /// Representation of a 3D point. -#[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy, PartialEq)] pub struct p3 { x: f32, @@ -83,7 +81,7 @@ impl Point for p2 { Self { x, y } } - fn to_vec(&self) -> impl InnerSpace { + fn to_vec(&self) -> v2 { v2::new(self.x, self.y) } } @@ -95,11 +93,23 @@ impl Point for p3 { Self { x, y, z } } - fn to_vec(&self) -> impl InnerSpace { + fn to_vec(&self) -> v3 { v3::new(self.x, self.y, self.z) } } +impl Into for p2 { + fn into(self) -> v2 { + self.to_vec() + } +} + +impl Into for p3 { + fn into(self) -> v3 { + self.to_vec() + } +} + impl From for p2 { fn from(v: v2) -> Self { Self::from_vec(v) diff --git a/crates/comet_math/src/polynomial.rs b/crates/comet_math/src/polynomial.rs index 2a7ff89..eaf1f09 100644 --- a/crates/comet_math/src/polynomial.rs +++ b/crates/comet_math/src/polynomial.rs @@ -118,7 +118,7 @@ impl Div for Polynomial { let divisor = other.coefficients.clone(); while dividend.len() >= divisor.len() { let mut quotient = vec![0.0; dividend.len() - divisor.len() + 1]; - let i = dividend.len() - divisor.len(); + let mut i = dividend.len() - divisor.len(); quotient[i] = dividend.last().unwrap() / divisor.last().unwrap(); for (j, &d) in divisor.iter().enumerate() { dividend[i + j] -= quotient[i] * d; diff --git a/crates/comet_math/src/quaternion.rs b/crates/comet_math/src/quaternion.rs index 4f08550..1183b9c 100644 --- a/crates/comet_math/src/quaternion.rs +++ b/crates/comet_math/src/quaternion.rs @@ -11,7 +11,6 @@ pub struct Quat { impl Quat { /// The zero quaternion. - #[allow(unused)] const ZERO: Self = Self { s: 0.0, v: v3 { diff --git a/crates/comet_math/src/vector.rs b/crates/comet_math/src/vector.rs index 860a5b0..011e788 100644 --- a/crates/comet_math/src/vector.rs +++ b/crates/comet_math/src/vector.rs @@ -1,9 +1,6 @@ -use crate::{ - point::{p2, p3}, - quaternion::Quat, - Point, -}; -use serde::{Deserialize, Serialize}; +use crate::point::{p2, p3}; +use crate::quaternion::Quat; +use crate::Point; use std::ops::*; pub trait InnerSpace: @@ -34,7 +31,8 @@ pub trait InnerSpace: /// Representation of a 2D vector #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v2 { x: f32, @@ -177,7 +175,8 @@ impl Into for [f32; 2] { /// Representation of a 2D integer vector #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v2i { x: i64, @@ -424,7 +423,8 @@ impl Into<[f32; 2]> for v2i { /// Representation of a 3D vector #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v3 { pub x: f32, @@ -620,7 +620,8 @@ impl Into for [f32; 3] { /// Representation of a 3D integer vector #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v3i { pub x: i64, @@ -823,7 +824,8 @@ impl From for v3i { /// Representation of a 4D vector #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v4 { x: f32, diff --git a/crates/comet_renderer/src/camera.rs b/crates/comet_renderer/src/camera.rs index 2e70adf..730084f 100644 --- a/crates/comet_renderer/src/camera.rs +++ b/crates/comet_renderer/src/camera.rs @@ -1,4 +1,5 @@ use comet_ecs::{Camera2D, Transform2D}; +use comet_log::fatal; use comet_math::{m4, v2, v3}; pub struct CameraManager { @@ -14,6 +15,16 @@ impl CameraManager { } } + pub fn set_cameras(&mut self, cameras: Vec) { + self.cameras = cameras + } + + pub fn set_active(&mut self, active: usize) { + if active >= self.cameras.len() { + fatal!("Active camera index is out of range of the RenderCamera array!") + } + } + pub fn get_camera(&self) -> &RenderCamera { self.cameras.get(self.active_camera).unwrap() } diff --git a/crates/comet_resources/src/font.rs b/crates/comet_resources/src/font.rs index cc3a700..a7c4748 100644 --- a/crates/comet_resources/src/font.rs +++ b/crates/comet_resources/src/font.rs @@ -1,120 +1,120 @@ -use crate::texture_atlas::{TextureAtlas, TextureRegion}; -use ab_glyph::{point, Font as AbFont, FontArc, Glyph, PxScale, ScaleFont}; use image::{DynamicImage, Rgba, RgbaImage}; +use ab_glyph::{FontArc, PxScale, ScaleFont, Glyph, point, Font as AbFont}; +use comet_log::debug; +use crate::texture_atlas::{TextureAtlas, TextureRegion}; pub struct GlyphData { - pub name: String, - pub render: DynamicImage, - pub advance: f32, - pub offset_x: f32, - pub offset_y: f32, + pub name: String, + pub render: DynamicImage, + pub advance: f32, + pub offset_x: f32, + pub offset_y: f32, } pub struct Font { - name: String, - size: f32, - line_height: f32, - glyphs: TextureAtlas, + name: String, + size: f32, + line_height: f32, + glyphs: TextureAtlas, } impl Font { - pub fn new(path: &str, size: f32) -> Self { - let (glyphs, line_height) = Self::generate_atlas(path, size); - Font { - name: path.to_string(), - size, - line_height, - glyphs, - } - } + pub fn new(path: &str, size: f32) -> Self { + let (glyphs, line_height) = Self::generate_atlas(path, size); + Font { + name: path.to_string(), + size, + line_height, + glyphs + } + } - pub fn name(&self) -> &str { - &self.name - } + pub fn name(&self) -> &str { + &self.name + } - pub fn size(&self) -> f32 { - self.size - } + pub fn size(&self) -> f32 { + self.size + } - pub fn line_height(&self) -> f32 { - self.line_height - } + pub fn line_height(&self) -> f32 { + self.line_height + } - pub fn glyphs(&self) -> &TextureAtlas { - &self.glyphs - } + pub fn glyphs(&self) -> &TextureAtlas { + &self.glyphs + } - pub fn get_glyph(&self, ch: char) -> Option<&TextureRegion> { - self.glyphs.textures().get(&ch.to_string()) - } + pub fn get_glyph(&self, ch: char) -> Option<&TextureRegion> { + self.glyphs.textures().get(&ch.to_string()) + } - fn generate_atlas(path: &str, size: f32) -> (TextureAtlas, f32) { - let font_data = std::fs::read(path).expect("Failed to read font file"); - let font = FontArc::try_from_vec(font_data).expect("Failed to load font"); + fn generate_atlas(path: &str, size: f32) -> (TextureAtlas, f32) { + let font_data = std::fs::read(path).expect("Failed to read font file"); + let font = FontArc::try_from_vec(font_data).expect("Failed to load font"); - let scale = PxScale::from(size); - let scaled_font = font.as_scaled(scale); + let scale = PxScale::from(size); + let scaled_font = font.as_scaled(scale); - let mut glyphs: Vec = Vec::new(); + let mut glyphs: Vec = Vec::new(); - for code_point in 0x0020..=0x007E { - if let Some(ch) = std::char::from_u32(code_point) { - let glyph_id = font.glyph_id(ch); - if glyph_id.0 == 0 { - continue; - } + for code_point in 0x0020..=0x007E { + if let Some(ch) = std::char::from_u32(code_point) { + let glyph_id = font.glyph_id(ch); + if glyph_id.0 == 0 { + continue; + } - if ch == ' ' { - let advance = scaled_font.h_advance(glyph_id); - glyphs.push(GlyphData { - name: ch.to_string(), - render: DynamicImage::new_rgba8(0, 0), // no bitmap - advance, - offset_x: 0.0, - offset_y: 0.0, - }); - continue; - } + if ch == ' ' { + let advance = scaled_font.h_advance(glyph_id); + glyphs.push(GlyphData { + name: ch.to_string(), + render: DynamicImage::new_rgba8(0, 0), // no bitmap + advance, + offset_x: 0.0, + offset_y: 0.0, + }); + continue; + } - let glyph = Glyph { - id: glyph_id, - scale, - position: point(0.0, 0.0), - }; + let glyph = Glyph { + id: glyph_id, + scale, + position: point(0.0, 0.0), + }; - if let Some(outline) = scaled_font.outline_glyph(glyph.clone()) { - let bounds = outline.px_bounds(); - let width = bounds.width().ceil() as u32; - let height = bounds.height().ceil() as u32; + if let Some(outline) = scaled_font.outline_glyph(glyph.clone()) { + let bounds = outline.px_bounds(); + let width = bounds.width().ceil() as u32; + let height = bounds.height().ceil() as u32; - if width == 0 || height == 0 { - continue; - } + if width == 0 || height == 0 { + continue; + } - let mut image = RgbaImage::new(width, height); - for pixel in image.pixels_mut() { - *pixel = Rgba([0, 0, 0, 0]); - } + let mut image = RgbaImage::new(width, height); + for pixel in image.pixels_mut() { + *pixel = Rgba([0, 0, 0, 0]); + } - outline.draw(|x, y, v| { - let alpha = (v * 255.0) as u8; - image.put_pixel(x, y, Rgba([255, 255, 255, alpha])); - }); + outline.draw(|x, y, v| { + let alpha = (v * 255.0) as u8; + image.put_pixel(x, y, Rgba([255, 255, 255, alpha])); + }); - glyphs.push(GlyphData { - name: ch.to_string(), - render: DynamicImage::ImageRgba8(image), - advance: scaled_font.h_advance(glyph_id), - offset_x: bounds.min.x, - offset_y: bounds.min.y, - }) - } - } - } + glyphs.push( + GlyphData { + name: ch.to_string(), + render: DynamicImage::ImageRgba8(image), + advance: scaled_font.h_advance(glyph_id), + offset_x: bounds.min.x, + offset_y: bounds.min.y, + } + ) + } + } + } - ( - TextureAtlas::from_glyphs(glyphs), - scaled_font.ascent() - scaled_font.descent(), - ) - } -} + (TextureAtlas::from_glyphs(glyphs), scaled_font.ascent() - scaled_font.descent()) + } +} \ No newline at end of file diff --git a/crates/comet_resources/src/resources.rs b/crates/comet_resources/src/resources.rs index 9d9c878..efb9aad 100644 --- a/crates/comet_resources/src/resources.rs +++ b/crates/comet_resources/src/resources.rs @@ -1,181 +1,182 @@ -use std::{collections::HashMap, path::Path}; - -use crate::{ - texture, - texture_atlas::{TextureAtlas, TextureRegion}, +use std::{ + collections::HashMap, path::Path }; +use wgpu::{Device, FilterMode, Queue, TextureFormat, TextureUsages}; +use crate::{texture, Texture}; +use crate::texture_atlas::{TextureAtlas, TextureRegion}; + pub struct ResourceManager { - texture_atlas: TextureAtlas, - data_files: HashMap, + texture_atlas: TextureAtlas, + data_files: HashMap } impl ResourceManager { - pub fn new() -> Self { - Self { - texture_atlas: TextureAtlas::empty(), - data_files: HashMap::new(), - } - } + pub fn new() -> Self { + Self { + texture_atlas: TextureAtlas::empty(), + data_files: HashMap::new() + } + } - pub fn texture_atlas(&self) -> &TextureAtlas { - &self.texture_atlas - } + pub fn texture_atlas(&self) -> &TextureAtlas { + &self.texture_atlas + } - pub fn texture_locations(&self) -> &HashMap { - &self.texture_atlas.textures() - } + pub fn texture_locations(&self) -> &HashMap { + &self.texture_atlas.textures() + } - pub fn data_files(&self) -> &HashMap { - &self.data_files - } + pub fn data_files(&self) -> &HashMap { + &self.data_files + } - pub fn set_texture_atlas(&mut self, texture_atlas: TextureAtlas) { - self.texture_atlas = texture_atlas; + pub fn set_texture_atlas(&mut self, texture_atlas: TextureAtlas) { + self.texture_atlas = texture_atlas; - // This is just for testing purposes - //self.texture_locations.insert("normal_comet.png".to_string(), ([0,0], [15,15])); - //self.texture_locations.insert("green_comet.png".to_string(), ([0,15], [15,31])); - } + // This is just for testing purposes + //self.texture_locations.insert("normal_comet.png".to_string(), ([0,0], [15,15])); + //self.texture_locations.insert("green_comet.png".to_string(), ([0,15], [15,31])); + } - pub fn create_texture_atlas(&mut self, paths: Vec) { - self.texture_atlas = TextureAtlas::from_texture_paths(paths) - } + pub fn create_texture_atlas(&mut self, paths: Vec) { + self.texture_atlas = TextureAtlas::from_texture_paths(paths) + } - pub async fn load_string(&self, file_name: &str) -> anyhow::Result { - let path = Path::new(std::env::var("OUT_DIR")?.as_str()) - .join("res") - .join(file_name); - let txt = std::fs::read_to_string(path)?; + pub async fn load_string(&self, file_name: &str) -> anyhow::Result { + let path = Path::new(std::env::var("OUT_DIR")?.as_str()) + .join("res") + .join(file_name); + let txt = std::fs::read_to_string(path)?; - Ok(txt) - } + Ok(txt) + } - pub async fn load_binary(&self, file_name: &str) -> anyhow::Result> { - let path = Path::new(std::env::var("OUT_DIR").unwrap().as_str()) - .join("res") - .join(file_name); - let data = std::fs::read(path)?; + pub async fn load_binary(&self, file_name: &str) -> anyhow::Result> { + let path = Path::new(std::env::var("OUT_DIR").unwrap().as_str()) + .join("res") + .join(file_name); + let data = std::fs::read(path)?; - Ok(data) - } + Ok(data) + } - pub async fn load_texture( - &self, - file_name: &str, - is_normal_map: bool, - device: &wgpu::Device, - queue: &wgpu::Queue, - ) -> anyhow::Result { - let data = self.load_binary(file_name).await?; - texture::Texture::from_bytes(device, queue, &data, file_name, is_normal_map) - } + pub async fn load_texture( + &self, + file_name: &str, + is_normal_map: bool, + device: &wgpu::Device, + queue: &wgpu::Queue, + ) -> anyhow::Result { + let data = self.load_binary(file_name).await?; + texture::Texture::from_bytes(device, queue, &data, file_name, is_normal_map) + } - /*pub async fn load_model( - &self, - file_name: &str, - device: &wgpu::Device, - queue: &wgpu::Queue, - layout: &wgpu::BindGroupLayout, - ) -> anyhow::Result { - let obj_text = self.load_string(file_name).await?; - let obj_cursor = Cursor::new(obj_text); - let mut obj_reader = BufReader::new(obj_cursor); + /*pub async fn load_model( + &self, + file_name: &str, + device: &wgpu::Device, + queue: &wgpu::Queue, + layout: &wgpu::BindGroupLayout, + ) -> anyhow::Result { + let obj_text = self.load_string(file_name).await?; + let obj_cursor = Cursor::new(obj_text); + let mut obj_reader = BufReader::new(obj_cursor); - let (models, obj_materials) = tobj::load_obj_buf_async( - &mut obj_reader, - &tobj::LoadOptions { - triangulate: true, - single_index: true, - ..Default::default() - }, - |p| async move { - let mat_text = self.load_string(&p).await.unwrap(); - tobj::load_mtl_buf(&mut BufReader::new(Cursor::new(mat_text))) - }, - ) - .await?; + let (models, obj_materials) = tobj::load_obj_buf_async( + &mut obj_reader, + &tobj::LoadOptions { + triangulate: true, + single_index: true, + ..Default::default() + }, + |p| async move { + let mat_text = self.load_string(&p).await.unwrap(); + tobj::load_mtl_buf(&mut BufReader::new(Cursor::new(mat_text))) + }, + ) + .await?; - let mut materials = Vec::new(); - for m in obj_materials? { - let diffuse_texture = self.load_texture(&m.diffuse_texture, false, device, queue).await?; - let normal_texture = self.load_texture(&m.normal_texture, true, device, queue).await?; - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), - }, - ], - label: None, - }); + let mut materials = Vec::new(); + for m in obj_materials? { + let diffuse_texture = self.load_texture(&m.diffuse_texture, false, device, queue).await?; + let normal_texture = self.load_texture(&m.normal_texture, true, device, queue).await?; + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), + }, + ], + label: None, + }); - materials.push(model::Material { - name: m.name, - diffuse_texture, - bind_group, - }); - } + materials.push(model::Material { + name: m.name, + diffuse_texture, + bind_group, + }); + } - let meshes = models - .into_iter() - .map(|m| { - let vertices = (0..m.mesh.positions.len() / 3) - .map(|i| { - if m.mesh.normals.is_empty() { - model::ModelVertex { - position: [ - m.mesh.positions[i * 3], - m.mesh.positions[i * 3 + 1], - m.mesh.positions[i * 3 + 2], - ], - tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], - normal: [0.0, 0.0, 0.0], - } - } else { - model::ModelVertex { - position: [ - m.mesh.positions[i * 3], - m.mesh.positions[i * 3 + 1], - m.mesh.positions[i * 3 + 2], - ], - tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], - normal: [ - m.mesh.normals[i * 3], - m.mesh.normals[i * 3 + 1], - m.mesh.normals[i * 3 + 2], - ], - } - } - }) - .collect::>(); + let meshes = models + .into_iter() + .map(|m| { + let vertices = (0..m.mesh.positions.len() / 3) + .map(|i| { + if m.mesh.normals.is_empty() { + model::ModelVertex { + position: [ + m.mesh.positions[i * 3], + m.mesh.positions[i * 3 + 1], + m.mesh.positions[i * 3 + 2], + ], + tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], + normal: [0.0, 0.0, 0.0], + } + } else { + model::ModelVertex { + position: [ + m.mesh.positions[i * 3], + m.mesh.positions[i * 3 + 1], + m.mesh.positions[i * 3 + 2], + ], + tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], + normal: [ + m.mesh.normals[i * 3], + m.mesh.normals[i * 3 + 1], + m.mesh.normals[i * 3 + 2], + ], + } + } + }) + .collect::>(); - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(&format!("{:?} Vertex Buffer", file_name)), - contents: bytemuck::cast_slice(&vertices), - usage: wgpu::BufferUsages::VERTEX, - }); - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(&format!("{:?} Index Buffer", file_name)), - contents: bytemuck::cast_slice(&m.mesh.indices), - usage: wgpu::BufferUsages::INDEX, - }); + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(&format!("{:?} Vertex Buffer", file_name)), + contents: bytemuck::cast_slice(&vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(&format!("{:?} Index Buffer", file_name)), + contents: bytemuck::cast_slice(&m.mesh.indices), + usage: wgpu::BufferUsages::INDEX, + }); - model::Mesh { - name: file_name.to_string(), - vertex_buffer, - index_buffer, - num_elements: m.mesh.indices.len() as u32, - material: m.mesh.material_id.unwrap_or(0), - } - }) - .collect::>(); + model::Mesh { + name: file_name.to_string(), + vertex_buffer, + index_buffer, + num_elements: m.mesh.indices.len() as u32, + material: m.mesh.material_id.unwrap_or(0), + } + }) + .collect::>(); - Ok(model::Model { meshes, materials }) - }*/ + Ok(model::Model { meshes, materials }) + }*/ } diff --git a/crates/comet_resources/src/texture_atlas.rs b/crates/comet_resources/src/texture_atlas.rs index 0e558fc..664d023 100644 --- a/crates/comet_resources/src/texture_atlas.rs +++ b/crates/comet_resources/src/texture_atlas.rs @@ -334,7 +334,7 @@ impl TextureAtlas { for glyph_name in glyph_names { let region = font.glyphs().textures().get(&glyph_name).unwrap(); - let (u0, v0) = (region.u0(), region.v0()); + let (u0, v0, u1, v1) = (region.u0(), region.v0(), region.u1(), region.v1()); let (width, height) = region.dimensions(); let src_x = (u0 * font.glyphs().atlas().width() as f32) as u32; diff --git a/crates/comet_resources/src/vertex.rs b/crates/comet_resources/src/vertex.rs index 14ec2ba..6436a75 100644 --- a/crates/comet_resources/src/vertex.rs +++ b/crates/comet_resources/src/vertex.rs @@ -1,53 +1,55 @@ +use wgpu::Color; + #[repr(C)] #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable, PartialEq)] pub struct Vertex { - position: [f32; 3], - tex_coords: [f32; 2], - color: [f32; 4], + position: [f32; 3], + tex_coords: [f32; 2], + color: [f32; 4] } impl Vertex { - pub fn new(position: [f32; 3], tex_coords: [f32; 2], color: [f32; 4]) -> Self { - Self { - position, - tex_coords, - color, - } - } + pub fn new(position: [f32; 3], tex_coords: [f32; 2], color: [f32; 4]) -> Self { + Self { + position, + tex_coords, + color + } + } - pub fn set_position(&mut self, new_position: [f32; 3]) { - self.position = new_position - } + pub fn set_position(&mut self, new_position: [f32;3]) { + self.position = new_position + } - pub fn set_tex_coords(&mut self, new_tex_coords: [f32; 2]) { - self.tex_coords = new_tex_coords - } + pub fn set_tex_coords(&mut self, new_tex_coords: [f32; 2]) { + self.tex_coords = new_tex_coords + } - pub fn set_color(&mut self, new_color: [f32; 4]) { - self.color = new_color - } + pub fn set_color(&mut self, new_color: [f32; 4]) { + self.color = new_color + } - pub fn desc() -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &[ - wgpu::VertexAttribute { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float32x3, - }, - wgpu::VertexAttribute { - offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, - shader_location: 1, - format: wgpu::VertexFormat::Float32x2, - }, - wgpu::VertexAttribute { - offset: std::mem::size_of::<[f32; 5]>() as wgpu::BufferAddress, - shader_location: 2, - format: wgpu::VertexFormat::Float32x4, - }, - ], - } - } -} + pub fn desc() -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &[ + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, + shader_location: 1, + format: wgpu::VertexFormat::Float32x2, + }, + wgpu::VertexAttribute { + offset: std::mem::size_of::<[f32; 5]>() as wgpu::BufferAddress, + shader_location: 2, + format: wgpu::VertexFormat::Float32x4, + } + ] + } + } +} \ No newline at end of file diff --git a/crates/comet_structs/src/component_storage.rs b/crates/comet_structs/src/component_storage.rs index 3216bda..86ce173 100644 --- a/crates/comet_structs/src/component_storage.rs +++ b/crates/comet_structs/src/component_storage.rs @@ -1,58 +1,65 @@ -use crate::{FlatMap, SparseSet}; +use std::any::{Any, TypeId}; use comet_log::*; -use std::any::TypeId; +use crate::{FlatMap, SparseSet}; pub type ComponentStorage = FlatMap; impl ComponentStorage { - pub fn register_component(&mut self, capacity: usize) { - if !self.contains(&TypeId::of::()) { - self.insert(TypeId::of::(), SparseSet::new::(capacity, 1000)); - } else { - error!("Component {:?} already exists", TypeId::of::()); - } - } - pub fn deregister_component(&mut self) { - if self.contains(&TypeId::of::()) { - self.remove(&TypeId::of::()); - } else { - error!("Component {:?} does not exist", TypeId::of::()); - } - } + pub fn register_component(&mut self, capacity: usize) { + if !self.contains(&TypeId::of::()) { + self.insert(TypeId::of::(), SparseSet::new::(capacity, 1000)); + } + else { + error!("Component {:?} already exists", TypeId::of::()); + } + } - pub fn set_component(&mut self, index: usize, element: T) { - if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { - sparse_set.insert(index, element); - } else { - error!("Component {:?} is not registered", TypeId::of::()); - } - } + pub fn deregister_component(&mut self) { + if self.contains(&TypeId::of::()) { + self.remove(&TypeId::of::()); + } + else { + error!("Component {:?} does not exist", TypeId::of::()); + } + } - pub fn remove_component(&mut self, index: usize) -> Option { - if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { - sparse_set.remove(index) - } else { - error!("Component {:?} is not registered", TypeId::of::()); - None - } - } + pub fn set_component(&mut self, index: usize, element: T) { + if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { + sparse_set.insert(index, element); + } + else { + error!("Component {:?} is not registered", TypeId::of::()); + } + } - pub fn get_component(&self, index: usize) -> Option<&T> { - if let Some(sparse_set) = self.get(&TypeId::of::()) { - sparse_set.get(index) - } else { - error!("Component {:?} is not registered", TypeId::of::()); - None - } - } + pub fn remove_component(&mut self, index: usize) -> Option { + if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { + sparse_set.remove(index) + } + else { + error!("Component {:?} is not registered", TypeId::of::()); + None + } + } - pub fn get_component_mut(&mut self, index: usize) -> Option<&mut T> { - if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { - sparse_set.get_mut(index) - } else { - error!("Component {:?} is not registered", TypeId::of::()); - None - } - } -} + pub fn get_component(&self, index: usize) -> Option<&T> { + if let Some(sparse_set) = self.get(&TypeId::of::()) { + sparse_set.get(index) + } + else { + error!("Component {:?} is not registered", TypeId::of::()); + None + } + } + + pub fn get_component_mut(&mut self, index: usize) -> Option<&mut T> { + if let Some(sparse_set) = self.get_mut(&TypeId::of::()) { + sparse_set.get_mut(index) + } + else { + error!("Component {:?} is not registered", TypeId::of::()); + None + } + } +} \ No newline at end of file diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 6d65300..26078cd 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -1,19 +1,17 @@ use comet::prelude::*; // This function will only be called once before the event loop starts. -#[allow(unused_variables)] fn setup(app: &mut App, renderer: &mut Renderer2D) {} // This function will be called on every tick after the event loop starts. -#[allow(unused_variables)] fn update(app: &mut App, renderer: &mut Renderer2D, dt: f32) {} fn main() { - // This creates a window with the title "Hello world". - // Note: You can call your functions differently if you want to though it is advised to use - // `setup` and `update` as the names. - // You can also replace `Renderer2D` with any other struct that implements the `Renderer` trait. - App::new() - .with_title("Hello world") - .run::(setup, update); -} + // This creates a window with the title "Hello world". + // Note: You can call your functions differently if you want to though it is advised to use + // `setup` and `update` as the names. + // You can also replace `Renderer2D` with any other struct that implements the `Renderer` trait. + App::new() + .with_title("Hello world") + .run::(setup, update); +} \ No newline at end of file diff --git a/examples/prefabs.rs b/examples/prefabs.rs index d4e6513..d4a88b7 100644 --- a/examples/prefabs.rs +++ b/examples/prefabs.rs @@ -43,7 +43,6 @@ fn setup(app: &mut App, renderer: &mut Renderer2D) { } } -#[allow(unused_variables)] fn update(app: &mut App, renderer: &mut Renderer2D, dt: f32) {} fn main() { diff --git a/examples/simple_text.rs b/examples/simple_text.rs index ebea0ec..b0f0056 100644 --- a/examples/simple_text.rs +++ b/examples/simple_text.rs @@ -26,7 +26,6 @@ fn setup(app: &mut App, renderer: &mut Renderer2D) { ); } -#[allow(unused_variables)] fn update(app: &mut App, renderer: &mut Renderer2D, dt: f32) { // Getting the windows size let size = renderer.size(); diff --git a/examples/textured_entity.rs b/examples/textured_entity.rs index 16a6e3f..9757081 100644 --- a/examples/textured_entity.rs +++ b/examples/textured_entity.rs @@ -18,7 +18,6 @@ fn setup(app: &mut App, renderer: &mut Renderer2D) { app.add_component(e0, render); } -#[allow(unused_variables)] fn update(app: &mut App, renderer: &mut Renderer2D, dt: f32) { renderer.render_scene_2d(app.scene_mut()) }