diff --git a/CHANGELOG.md b/CHANGELOG.md index 063966e1..b79ad068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog All notable changes to this project will be documented in this file. +## v0.9.4 - 26/02/2023 + +- Added `WindowBackend::set_title` and `WindowBackend::title` to change or get the title at any time. +- Improved stencil clearing when setting a mask on the draw api at the end of the pass. +- Fix panic using Draw API to draw text with `max_width` and `size` as 0. +- Fix `debug_assert` in `Device::inner_read_pixels`. +- Added support for `include` directives using `shaderc`. +- Added optional feature `serde` to serialize/deserialize some core types. + ## v0.9.3 - 12/02/2023 - Added `WindowBackend::screen_size` to get the screen's resolution size. diff --git a/Cargo.lock b/Cargo.lock index 5675b19c..5ab3b63d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1062,6 +1062,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" dependencies = [ "bytemuck", + "serde", ] [[package]] @@ -1230,6 +1231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ "ahash", + "serde", ] [[package]] @@ -1720,7 +1722,7 @@ dependencies = [ [[package]] name = "notan" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "egui_demo_lib", @@ -1744,7 +1746,7 @@ dependencies = [ [[package]] name = "notan_app" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "downcast-rs", @@ -1763,20 +1765,21 @@ dependencies = [ "notan_utils", "parking_lot", "platter2", + "serde", "wasm-bindgen-futures", "web-sys", ] [[package]] name = "notan_audio" -version = "0.9.3" +version = "0.9.4" dependencies = [ "parking_lot", ] [[package]] name = "notan_backend" -version = "0.9.3" +version = "0.9.4" dependencies = [ "notan_web", "notan_winit", @@ -1784,14 +1787,15 @@ dependencies = [ [[package]] name = "notan_core" -version = "0.9.3" +version = "0.9.4" dependencies = [ + "serde", "web-sys", ] [[package]] name = "notan_draw" -version = "0.9.3" +version = "0.9.4" dependencies = [ "log", "lyon", @@ -1807,7 +1811,7 @@ dependencies = [ [[package]] name = "notan_egui" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "egui", @@ -1819,7 +1823,7 @@ dependencies = [ [[package]] name = "notan_extra" -version = "0.9.3" +version = "0.9.4" dependencies = [ "notan_app", "spin_sleep", @@ -1827,7 +1831,7 @@ dependencies = [ [[package]] name = "notan_glow" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "glow", @@ -1842,7 +1846,7 @@ dependencies = [ [[package]] name = "notan_glyph" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "glyph_brush", @@ -1854,7 +1858,7 @@ dependencies = [ [[package]] name = "notan_graphics" -version = "0.9.3" +version = "0.9.4" dependencies = [ "bytemuck", "glsl-layout", @@ -1867,17 +1871,18 @@ dependencies = [ [[package]] name = "notan_input" -version = "0.9.3" +version = "0.9.4" dependencies = [ "hashbrown 0.13.2", "log", "notan_core", "notan_math", + "serde", ] [[package]] name = "notan_log" -version = "0.9.3" +version = "0.9.4" dependencies = [ "console_log", "fern", @@ -1890,7 +1895,7 @@ dependencies = [ [[package]] name = "notan_macro" -version = "0.9.3" +version = "0.9.4" dependencies = [ "cfg_aliases", "glsl-to-spirv", @@ -1904,14 +1909,15 @@ dependencies = [ [[package]] name = "notan_math" -version = "0.9.3" +version = "0.9.4" dependencies = [ "glam", + "serde", ] [[package]] name = "notan_oddio" -version = "0.9.3" +version = "0.9.4" dependencies = [ "cpal", "hashbrown 0.13.2", @@ -1923,7 +1929,7 @@ dependencies = [ [[package]] name = "notan_random" -version = "0.9.3" +version = "0.9.4" dependencies = [ "getrandom", "rand", @@ -1932,7 +1938,7 @@ dependencies = [ [[package]] name = "notan_text" -version = "0.9.3" +version = "0.9.4" dependencies = [ "hashbrown 0.13.2", "lazy_static", @@ -1946,7 +1952,7 @@ dependencies = [ [[package]] name = "notan_utils" -version = "0.9.3" +version = "0.9.4" dependencies = [ "instant", "js-sys", @@ -1958,7 +1964,7 @@ dependencies = [ [[package]] name = "notan_web" -version = "0.9.3" +version = "0.9.4" dependencies = [ "console_error_panic_hook", "futures-util", @@ -1977,7 +1983,7 @@ dependencies = [ [[package]] name = "notan_winit" -version = "0.9.3" +version = "0.9.4" dependencies = [ "arboard", "glutin", diff --git a/Cargo.toml b/Cargo.toml index e8e82bcf..7690b6bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" categories = ["graphics", "rendering", "wasm", "gui", "multimedia"] @@ -19,22 +19,22 @@ features = ["default", "glyph", "egui", "text", "extra", "audio", "links", "drop lto = true [dependencies] -notan_core = { path = "crates/notan_core", version = "0.9.3" } -notan_input = { path = "crates/notan_input", version = "0.9.3" } -notan_app = { path = "crates/notan_app", version = "0.9.3" } -notan_macro = { path = "crates/notan_macro", version = "0.9.3" } -notan_math = { path = "crates/notan_math", version = "0.9.3" } -notan_graphics = { path = "crates/notan_graphics", version = "0.9.3" } -notan_utils = { path = "crates/notan_utils", version = "0.9.3" } -notan_log = { path = "crates/notan_log", version = "0.9.3", optional = true } -notan_glyph = { path = "crates/notan_glyph", version = "0.9.3", optional = true } -notan_draw = { path = "crates/notan_draw", version = "0.9.3", optional = true } -notan_backend = { path = "crates/notan_backend", version = "0.9.3", optional = true } -notan_egui = { path = "crates/notan_egui", version = "0.9.3", optional = true } -notan_text = { path = "crates/notan_text", version = "0.9.3", optional = true } -notan_audio = { path = "crates/notan_audio", version = "0.9.3", optional = true } -notan_extra = { path = "crates/notan_extra", version = "0.9.3", optional = true } -notan_random = { path = "crates/notan_random", version = "0.9.3", optional = true } +notan_core = { path = "crates/notan_core", version = "0.9.4" } +notan_input = { path = "crates/notan_input", version = "0.9.4" } +notan_app = { path = "crates/notan_app", version = "0.9.4" } +notan_macro = { path = "crates/notan_macro", version = "0.9.4" } +notan_math = { path = "crates/notan_math", version = "0.9.4" } +notan_graphics = { path = "crates/notan_graphics", version = "0.9.4" } +notan_utils = { path = "crates/notan_utils", version = "0.9.4" } +notan_log = { path = "crates/notan_log", version = "0.9.4", optional = true } +notan_glyph = { path = "crates/notan_glyph", version = "0.9.4", optional = true } +notan_draw = { path = "crates/notan_draw", version = "0.9.4", optional = true } +notan_backend = { path = "crates/notan_backend", version = "0.9.4", optional = true } +notan_egui = { path = "crates/notan_egui", version = "0.9.4", optional = true } +notan_text = { path = "crates/notan_text", version = "0.9.4", optional = true } +notan_audio = { path = "crates/notan_audio", version = "0.9.4", optional = true } +notan_extra = { path = "crates/notan_extra", version = "0.9.4", optional = true } +notan_random = { path = "crates/notan_random", version = "0.9.4", optional = true } [workspace] members = ["crates/*"] @@ -57,6 +57,7 @@ texture_to_file = ["notan_graphics/texture_to_file"] random = ["notan_random"] glsl-to-spirv = ["notan_macro/glsl-to-spirv"] shaderc = ["notan_macro/shaderc"] +serde = ["notan_app/serde", "notan_math/serde", "notan_core/serde", "notan_input/serde"] [dev-dependencies] egui_demo_lib = "0.20.0" diff --git a/crates/notan_app/Cargo.toml b/crates/notan_app/Cargo.toml index 723d7c25..c90dfcdc 100644 --- a/crates/notan_app/Cargo.toml +++ b/crates/notan_app/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_app" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -14,18 +14,19 @@ description = "Provides the core API for Notan" [dependencies] log = "0.4.17" hashbrown = "0.13.2" -notan_core = { path = "../notan_core", version = "0.9.3" } -notan_input = { path = "../notan_input", version = "0.9.3" } -notan_math = { path = "../notan_math", version = "0.9.3" } -notan_macro = { path = "../notan_macro", version = "0.9.3" } -notan_graphics = { path = "../notan_graphics", version = "0.9.3" } -notan_utils = { path = "../notan_utils", version = "0.9.3" } -notan_audio = { path = "../notan_audio", version = "0.9.3", optional = true } +notan_core = { path = "../notan_core", version = "0.9.4" } +notan_input = { path = "../notan_input", version = "0.9.4" } +notan_math = { path = "../notan_math", version = "0.9.4" } +notan_macro = { path = "../notan_macro", version = "0.9.4" } +notan_graphics = { path = "../notan_graphics", version = "0.9.4" } +notan_utils = { path = "../notan_utils", version = "0.9.4" } +notan_audio = { path = "../notan_audio", version = "0.9.4", optional = true } downcast-rs = "1.2.0" indexmap = "1.9.2" futures = "0.3.25" parking_lot = "0.12.1" bytemuck = "1.13.0" +serde = { version = "1", optional = true, features = ["serde_derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] platter2 = "0.1.6" diff --git a/crates/notan_app/src/backend.rs b/crates/notan_app/src/backend.rs index 27aee29a..6be92034 100644 --- a/crates/notan_app/src/backend.rs +++ b/crates/notan_app/src/backend.rs @@ -188,6 +188,12 @@ pub trait WindowBackend { /// Returns the window's size fn size(&self) -> (i32, i32); + /// Set the window's title + fn set_title(&mut self, title: &str); + + /// Returns current windows title + fn title(&self) -> &str; + /// Returns if the window is visible fn visible(&self) -> bool; diff --git a/crates/notan_app/src/config.rs b/crates/notan_app/src/config.rs index af9a5fa1..c3323d03 100644 --- a/crates/notan_app/src/config.rs +++ b/crates/notan_app/src/config.rs @@ -5,6 +5,7 @@ use crate::builder::{AppBuilder, BuildConfig}; /// Builder configuration for the window options #[derive(Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct WindowConfig { /// Window's title /// `Web: no-op` diff --git a/crates/notan_app/src/empty.rs b/crates/notan_app/src/empty.rs index 8d09c9fb..be9fe5b0 100644 --- a/crates/notan_app/src/empty.rs +++ b/crates/notan_app/src/empty.rs @@ -16,6 +16,7 @@ use notan_audio::AudioBackend; #[derive(Default)] pub struct EmptyWindowBackend { + title: String, size: (i32, i32), position: (i32, i32), is_fullscreen: bool, @@ -112,6 +113,14 @@ impl WindowBackend for EmptyWindowBackend { fn visible(&self) -> bool { self.visible } + + fn set_title(&mut self, title: &str) { + self.title = title.to_string(); + } + + fn title(&self) -> &str { + &self.title + } } #[derive(Default)] diff --git a/crates/notan_audio/Cargo.toml b/crates/notan_audio/Cargo.toml index 2b510bdc..e9ca134c 100644 --- a/crates/notan_audio/Cargo.toml +++ b/crates/notan_audio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_audio" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" diff --git a/crates/notan_backend/Cargo.toml b/crates/notan_backend/Cargo.toml index 13a7954c..e3846ac1 100644 --- a/crates/notan_backend/Cargo.toml +++ b/crates/notan_backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_backend" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -12,10 +12,10 @@ description = "Provides a default backend for Notan" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [target.'cfg(target_arch = "wasm32")'.dependencies] -notan_web = { path = "../notan_web", version = "0.9.3" } +notan_web = { path = "../notan_web", version = "0.9.4" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -notan_winit = { path = "../notan_winit", version = "0.9.3" } +notan_winit = { path = "../notan_winit", version = "0.9.4" } [features] audio = ["notan_web/audio", "notan_winit/audio"] diff --git a/crates/notan_core/Cargo.toml b/crates/notan_core/Cargo.toml index 5591998f..f5253a91 100644 --- a/crates/notan_core/Cargo.toml +++ b/crates/notan_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_core" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -10,6 +10,7 @@ license = "MIT OR Apache-2.0" description = "Basic types and structs used in Notan" [dependencies] +serde = { version = "1", optional = true, features = ["serde_derive"] } [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = { version = "0.3.60", optional = true } diff --git a/crates/notan_core/src/events.rs b/crates/notan_core/src/events.rs index 8a1a7219..154d8c81 100644 --- a/crates/notan_core/src/events.rs +++ b/crates/notan_core/src/events.rs @@ -6,8 +6,9 @@ use std::path::PathBuf; use crate::keyboard::KeyCode; use crate::mouse::MouseButton; -#[derive(Debug, PartialEq, Clone)] /// Application events usually received from the user +#[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Event { /// When the app is about to close Exit, @@ -88,17 +89,19 @@ pub enum Event { #[cfg(feature = "drop_files")] #[derive(Default, Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DroppedFile { pub path: Option, pub name: String, pub mime: String, #[cfg(target_arch = "wasm32")] + #[cfg_attr(feature = "serde", serde(skip))] pub file: Option, } -#[derive(Debug, Clone, Default)] /// Event iterator queue +#[derive(Debug, Clone, Default)] pub struct EventIterator(VecDeque); impl EventIterator { diff --git a/crates/notan_core/src/keyboard.rs b/crates/notan_core/src/keyboard.rs index 0c5cff53..d5f970b3 100644 --- a/crates/notan_core/src/keyboard.rs +++ b/crates/notan_core/src/keyboard.rs @@ -1,7 +1,8 @@ -#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] -#[repr(u32)] /// KeyCode represents the symbolic name of the keyboard keys pressed /// This enum code comes from `winit` just adding the Unknown key for non-compatible keys between platforms +#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] +#[repr(u32)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum KeyCode { /// The '1' key over the letters. Key1, diff --git a/crates/notan_core/src/mouse.rs b/crates/notan_core/src/mouse.rs index 47cee416..c6fc82a0 100644 --- a/crates/notan_core/src/mouse.rs +++ b/crates/notan_core/src/mouse.rs @@ -1,5 +1,6 @@ -#[derive(Clone, Copy, Hash, Debug, Eq, PartialEq, Ord, PartialOrd)] /// Represents a button of a mouse +#[derive(Clone, Copy, Hash, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MouseButton { Left, Right, diff --git a/crates/notan_draw/Cargo.toml b/crates/notan_draw/Cargo.toml index dfc2eb50..9d3e2a04 100644 --- a/crates/notan_draw/Cargo.toml +++ b/crates/notan_draw/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_draw" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -13,12 +13,12 @@ description = "Provides a simple 2D API for Notan" [dependencies] log = "0.4.17" -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_graphics = { path = "../notan_graphics", version = "0.9.3" } -notan_macro = { path = "../notan_macro", version = "0.9.3" } -notan_math = { path = "../notan_math", version = "0.9.3" } -notan_glyph = { path = "../notan_glyph", version = "0.9.3" } -notan_text = { path = "../notan_text", version = "0.9.3" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_graphics = { path = "../notan_graphics", version = "0.9.4" } +notan_macro = { path = "../notan_macro", version = "0.9.4" } +notan_math = { path = "../notan_math", version = "0.9.4" } +notan_glyph = { path = "../notan_glyph", version = "0.9.4" } +notan_text = { path = "../notan_text", version = "0.9.4" } lyon = "1.0.1" serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.91" diff --git a/crates/notan_draw/src/draw.rs b/crates/notan_draw/src/draw.rs index a49ec35e..117033bb 100644 --- a/crates/notan_draw/src/draw.rs +++ b/crates/notan_draw/src/draw.rs @@ -29,6 +29,7 @@ pub struct Draw { pub(crate) masking: bool, pub(crate) needs_to_clean_stencil: bool, pub(crate) glyphs_calculator: Calculator, + mask_batches: Option>, } impl Clone for Draw { @@ -53,6 +54,7 @@ impl Clone for Draw { needs_to_clean_stencil: self.needs_to_clean_stencil, text_batch_indices: self.text_batch_indices.clone(), glyphs_calculator: Calculator::new(), + mask_batches: self.mask_batches.clone(), } } } @@ -82,6 +84,7 @@ impl Draw { needs_to_clean_stencil: false, text_batch_indices: None, glyphs_calculator: Calculator::new(), + mask_batches: None, } } @@ -90,46 +93,56 @@ impl Draw { pub fn matrix(&self) -> &Mat3 { self.transform.matrix() } - // - // pub fn round_pixels(&mut self, _round: bool) { - // //TODO round pixels to draw "2d pixel games" - // todo!("round pixels"); - // } + + fn process_mask_batches(&mut self) { + if let Some(mask_batches) = self.mask_batches.take() { + //Move the current batch to the queue + if let Some(b) = self.current_batch.take() { + self.batches.push(b); + } + + self.batches.extend(mask_batches.iter().map(|batch| { + let mut b = batch.clone(); + b.is_mask = true; + b + })); + } + } pub fn mask(&mut self, mask: Option<&Self>) { debug_assert!(!(self.masking && mask.is_some()), "Already using mask."); match mask { - Some(m) => { - self.masking = true; - self.needs_to_clean_stencil = true; - - //Move the current batch to the queue - if let Some(b) = self.current_batch.take() { - self.batches.push(b); + Some(m) if !self.masking => { + let mut mask_batches = m.batches.clone(); + if let Some(b) = m.current_batch.as_ref() { + mask_batches.push(b.clone()); } - //Reserve the space for the mask batches - // let new_capacity = self.batches.len() + m.batches.len() + 1; - // self.batches.reserve(new_capacity); - self.batches.extend(m.batches.iter().map(|batch| { - let mut b = batch.clone(); - b.is_mask = true; - b - })); - - if let Some(mut b) = m.current_batch.clone() { - b.is_mask = true; - self.batches.push(b); + if !mask_batches.is_empty() { + self.masking = true; + self.mask_batches = Some(mask_batches); } } - _ => { + None if self.masking => { self.masking = false; + self.mask_batches = None; + //Move the current batch to the queue if let Some(b) = self.current_batch.take() { self.batches.push(b); } } + _ => { + #[cfg(debug_assertions)] + { + log::warn!( + "Draw setting mask as: {:?} when the value is {:?} is a no-op", + mask.is_some(), + self.masking + ); + } + } } } @@ -197,6 +210,11 @@ impl Draw { F1: Fn(&Batch, &I) -> bool, F2: Fn(&I) -> BatchType, { + if self.masking { + self.needs_to_clean_stencil = true; + self.process_mask_batches(); + } + let needs_new_batch = needs_new_batch(self, info, is_diff_type); if needs_new_batch { if let Some(old) = self.current_batch.take() { diff --git a/crates/notan_draw/src/manager.rs b/crates/notan_draw/src/manager.rs index 047cc5da..6868ed40 100644 --- a/crates/notan_draw/src/manager.rs +++ b/crates/notan_draw/src/manager.rs @@ -96,7 +96,7 @@ fn paint_batch( manager.drawing_mask = true; } else if !b.is_mask && manager.drawing_mask { manager.drawing_mask = false; - manager.renderer.begin(Some(&Default::default())); + manager.renderer.begin(None); } match &b.typ { diff --git a/crates/notan_draw/src/texts/text.rs b/crates/notan_draw/src/texts/text.rs index 6e2f5cba..de022bcd 100644 --- a/crates/notan_draw/src/texts/text.rs +++ b/crates/notan_draw/src/texts/text.rs @@ -136,12 +136,19 @@ impl DrawProcess for TextSection<'_> { flip, } = self; + #[cfg(debug_assertions)] + { + if size < 1.0 { + log::warn!("Text must use a size bigger or equal than 1.0"); + } + } + let color = color.with_alpha(color.a * alpha); let count = text.chars().filter(|c| !c.is_whitespace()).count(); let g_text = Text::new(text) .with_color(color.rgba()) - .with_scale(size) + .with_scale(size.max(1.0)) .with_font_id(font); let mut section = Section::default() diff --git a/crates/notan_egui/Cargo.toml b/crates/notan_egui/Cargo.toml index 931acd0e..41f42c08 100644 --- a/crates/notan_egui/Cargo.toml +++ b/crates/notan_egui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_egui" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -15,9 +15,9 @@ description = "Provides EGUI support for Notan" log = "0.4.17" egui = { version = "0.20.1", features = ["bytemuck"] } bytemuck = "1.13.0" -notan_core = { path = "../notan_core", version = "0.9.3" } -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_macro = { path = "../notan_macro", version = "0.9.3" } +notan_core = { path = "../notan_core", version = "0.9.4" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_macro = { path = "../notan_macro", version = "0.9.4" } [features] links = [] diff --git a/crates/notan_extra/Cargo.toml b/crates/notan_extra/Cargo.toml index fcc6accc..ddfae64a 100644 --- a/crates/notan_extra/Cargo.toml +++ b/crates/notan_extra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_extra" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -12,7 +12,7 @@ description = "Provides extra features or plugins for Notan" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -notan_app = { path = "../notan_app", version = "0.9.3" } +notan_app = { path = "../notan_app", version = "0.9.4" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] spin_sleep = "1.1.1" diff --git a/crates/notan_glow/Cargo.toml b/crates/notan_glow/Cargo.toml index 772c0ce0..d823dda2 100644 --- a/crates/notan_glow/Cargo.toml +++ b/crates/notan_glow/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_glow" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -15,7 +15,7 @@ description = "Provides support for OpenGL, OpenGL ES and WebGL for Notan" log = "0.4.17" bytemuck = "1.13.0" glow = "0.11.2" -notan_graphics = { path= "../notan_graphics", version = "0.9.3" } +notan_graphics = { path= "../notan_graphics", version = "0.9.4" } hashbrown = "0.13.2" image = { version = "0.24.5", default-features = false, features = ["jpeg", "png"] } diff --git a/crates/notan_glyph/Cargo.toml b/crates/notan_glyph/Cargo.toml index 947c67d1..e11c063c 100644 --- a/crates/notan_glyph/Cargo.toml +++ b/crates/notan_glyph/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_glyph" -version = "0.9.3" +version = "0.9.4" edition = "2021" readme = "README.md" homepage = "https://github.com/Nazariglez/notan" @@ -14,6 +14,6 @@ description = "Provides glyph's support for Notan" log = "0.4.17" glyph_brush = "0.7.5" bytemuck = "1.13.0" -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_graphics = { path = "../notan_graphics", version = "0.9.3" } -notan_math = { path = "../notan_math", version = "0.9.3" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_graphics = { path = "../notan_graphics", version = "0.9.4" } +notan_math = { path = "../notan_math", version = "0.9.4" } diff --git a/crates/notan_graphics/Cargo.toml b/crates/notan_graphics/Cargo.toml index 359a1412..6b59c846 100644 --- a/crates/notan_graphics/Cargo.toml +++ b/crates/notan_graphics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_graphics" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -15,9 +15,9 @@ description = "Provides simple graphics API for Notan" bytemuck = "1.13.0" parking_lot = "0.12.1" image = { version = "0.24.5", default-features = false, features = ["jpeg", "png"] } -notan_math = { path = "../notan_math", version = "0.9.3" } -notan_macro = { path = "../notan_macro", version = "0.9.3" } -notan_utils = { path = "../notan_utils", version = "0.9.3" } +notan_math = { path = "../notan_math", version = "0.9.4" } +notan_macro = { path = "../notan_macro", version = "0.9.4" } +notan_utils = { path = "../notan_utils", version = "0.9.4" } glsl-layout = { version = "0.5.0", features = ["glam"] } [features] diff --git a/crates/notan_graphics/src/device.rs b/crates/notan_graphics/src/device.rs index 5b2458aa..7efa8d31 100644 --- a/crates/notan_graphics/src/device.rs +++ b/crates/notan_graphics/src/device.rs @@ -418,15 +418,15 @@ impl Device { ) -> Result<(), String> { // Check if the buffer size is enough to read the pixels if cfg!(debug_assertions) { - let size = (texture.width() * texture.height()) as usize; - let bpp = texture.format().bytes_per_pixel() as usize; + let size = (opts.width * opts.height) as usize; + let bpp = opts.format.bytes_per_pixel() as usize; let len = size * bpp; - debug_assert_eq!( - len, + debug_assert!( + bytes.len() >= len, + "The provided buffer len of {} is less than the required {} when reading pixels from texture {}", bytes.len(), - "To read the pixels the texture {} needs at a buffer of {} len", - texture.id(), - len + len, + texture.id() ); } diff --git a/crates/notan_input/Cargo.toml b/crates/notan_input/Cargo.toml index 7050d60a..96d2f85e 100644 --- a/crates/notan_input/Cargo.toml +++ b/crates/notan_input/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_input" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -10,7 +10,11 @@ license = "MIT OR Apache-2.0" description = "Provides a set of API to manage user's input" [dependencies] -notan_core = { path = "../notan_core", version = "0.9.3" } -notan_math = { path = "../notan_math", version = "0.9.3" } +notan_core = { path = "../notan_core", version = "0.9.4" } +notan_math = { path = "../notan_math", version = "0.9.4" } hashbrown = "0.13.2" log = "0.4.17" +serde = { version = "1", optional = true, features = ["serde_derive"] } + +[features] +serde = ["dep:serde", "notan_core/serde", "notan_math/serde", "hashbrown/serde"] \ No newline at end of file diff --git a/crates/notan_input/src/keyboard.rs b/crates/notan_input/src/keyboard.rs index 0590ccd0..2949dce5 100644 --- a/crates/notan_input/src/keyboard.rs +++ b/crates/notan_input/src/keyboard.rs @@ -3,8 +3,9 @@ use notan_core::events::Event; pub use notan_core::keyboard::KeyCode; -#[derive(Default)] /// Represent the keyboard data +#[derive(Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Keyboard { /// pressed keys pub pressed: HashSet, diff --git a/crates/notan_input/src/mouse.rs b/crates/notan_input/src/mouse.rs index 1dd92ac4..20307c6d 100644 --- a/crates/notan_input/src/mouse.rs +++ b/crates/notan_input/src/mouse.rs @@ -5,6 +5,7 @@ pub use notan_core::mouse::MouseButton; use notan_math::{Mat3, Vec2}; #[derive(Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] /// Represent the mouse data pub struct Mouse { /// x position diff --git a/crates/notan_input/src/touch.rs b/crates/notan_input/src/touch.rs index c61e2051..8d8f9b6c 100644 --- a/crates/notan_input/src/touch.rs +++ b/crates/notan_input/src/touch.rs @@ -3,6 +3,7 @@ use notan_core::events::Event; /// Represent a pointer event #[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] struct Pointer { /// Pointer index _index: u8, @@ -14,8 +15,9 @@ struct Pointer { y: f32, } -#[derive(Default)] /// Represent the touches data +#[derive(Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Touch { /// pressed touches pub pressed: HashSet, diff --git a/crates/notan_log/Cargo.toml b/crates/notan_log/Cargo.toml index 4eb3d72d..77550e9e 100644 --- a/crates/notan_log/Cargo.toml +++ b/crates/notan_log/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_log" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -14,7 +14,7 @@ description = "Provides a multipatform log support for Notan" [dependencies] log = "0.4.17" fern = { version = "0.6.1", features = ["colored"] } -notan_app = { path = "../notan_app", version = "0.9.3" } +notan_app = { path = "../notan_app", version = "0.9.4" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] time = { version = "0.3.17", features = ["formatting", "local-offset"] } diff --git a/crates/notan_macro/Cargo.toml b/crates/notan_macro/Cargo.toml index 35c04832..9707bc70 100644 --- a/crates/notan_macro/Cargo.toml +++ b/crates/notan_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_macro" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" diff --git a/crates/notan_macro/src/lib.rs b/crates/notan_macro/src/lib.rs index 4d5f5843..3bb28b44 100644 --- a/crates/notan_macro/src/lib.rs +++ b/crates/notan_macro/src/lib.rs @@ -67,7 +67,7 @@ pub fn state_derive(input: TokenStream) -> TokenStream { pub fn vertex_shader(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as LitStr); let content = input.value(); - let spirv = shaders::spirv_from(&content, shaders::ShaderType::Vertex).unwrap(); + let spirv = shaders::spirv_from(&content, shaders::ShaderType::Vertex, None).unwrap(); shaders::source_from_spirv(spirv).unwrap() } @@ -85,7 +85,7 @@ pub fn include_vertex_shader(input: TokenStream) -> TokenStream { pub fn fragment_shader(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as LitStr); let content = input.value(); - let spirv = shaders::spirv_from(&content, shaders::ShaderType::Fragment).unwrap(); + let spirv = shaders::spirv_from(&content, shaders::ShaderType::Fragment, None).unwrap(); shaders::source_from_spirv(spirv).unwrap() } diff --git a/crates/notan_macro/src/shaders.rs b/crates/notan_macro/src/shaders.rs index 95a02034..5caf8e2e 100644 --- a/crates/notan_macro/src/shaders.rs +++ b/crates/notan_macro/src/shaders.rs @@ -4,7 +4,7 @@ use quote::quote; use spirv_cross::{glsl, spirv, ErrorCode}; use std::fs::read_to_string; use std::io::{Cursor, Read}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::{io, slice}; #[derive(Debug, Clone, Copy)] @@ -34,6 +34,11 @@ impl From for shaderc::ShaderKind { } } +fn get_root_path() -> PathBuf { + let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); + Path::new(&root).to_path_buf() +} + fn read_file(full_path: &Path) -> Result { if !full_path.is_file() { return Err(format!("File {} was not found.", full_path.display())); @@ -43,15 +48,17 @@ fn read_file(full_path: &Path) -> Result { } pub(crate) fn spirv_from_file(relative_path: &str, typ: ShaderType) -> Result, String> { - let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); - let root_path = Path::new(&root); + let root_path = get_root_path(); let full_path = root_path.join(Path::new(relative_path)); - - spirv_from(&read_file(&full_path)?, typ) + spirv_from(&read_file(&full_path)?, typ, Some(full_path)) } #[cfg(use_glsl_to_spirv)] -pub(crate) fn spirv_from(source: &str, typ: ShaderType) -> Result, String> { +pub(crate) fn spirv_from( + source: &str, + typ: ShaderType, + _file_path: Option, +) -> Result, String> { let source = source.trim(); let mut spirv_output = glsl_to_spirv::compile(source, typ.into()) .unwrap_or_else(|e| panic!("Invalid {typ:#?} shader: \n{e}")); @@ -64,13 +71,50 @@ pub(crate) fn spirv_from(source: &str, typ: ShaderType) -> Result, Strin } #[cfg(use_shaderc)] -pub(crate) fn spirv_from(source: &str, typ: ShaderType) -> Result, String> { +pub(crate) fn spirv_from( + source: &str, + typ: ShaderType, + file_path: Option, +) -> Result, String> { + use shaderc::IncludeType; + let source = source.trim(); let compiler = shaderc::Compiler::new().unwrap(); - let options = shaderc::CompileOptions::new().unwrap(); + let mut options = shaderc::CompileOptions::new().unwrap(); + + // Resolve `#include` directives + if let Some(file_path) = file_path.as_ref() { + let file_dir = file_path.parent().unwrap(); + + options.set_include_callback(|name, type_, _filename, _include_depth| { + let include_path = match type_ { + IncludeType::Relative => file_dir.join(name), + IncludeType::Standard => get_root_path().join(name), + }; + let include_path_string = include_path.to_string_lossy().into_owned(); + + if let Ok(file_content) = read_file(include_path.as_path()) { + Ok(shaderc::ResolvedInclude { + content: file_content, + resolved_name: include_path_string, + }) + } else { + Err(format!( + "Failed to include file: \"{}\" (from \"{}\")", + name, include_path_string + )) + } + }); + } + + let input_file_name = file_path + .as_ref() + .and_then(|f| f.file_name()) + .and_then(|f| f.to_str()) + .unwrap_or("shader.glsl"); let spirv_output = compiler - .compile_into_spirv(source, typ.into(), "shader.glsl", "main", Some(&options)) + .compile_into_spirv(source, typ.into(), input_file_name, "main", Some(&options)) .unwrap_or_else(|e| panic!("Invalid {typ:#?} shader: \n{e}")); let mut spirv = vec![]; diff --git a/crates/notan_math/Cargo.toml b/crates/notan_math/Cargo.toml index d0b52ff7..517ebb0e 100644 --- a/crates/notan_math/Cargo.toml +++ b/crates/notan_math/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_math" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -13,3 +13,7 @@ description = "Provides simple set of math's utils for Notan" [dependencies] glam = { version = "0.22.0", features = ["scalar-math", "bytemuck"] } +serde = { version = "1", optional = true, features = ["serde_derive"] } + +[features] +serde = ["dep:serde", "glam/serde"] diff --git a/crates/notan_math/src/rect.rs b/crates/notan_math/src/rect.rs index 92ce9cd2..211d0372 100644 --- a/crates/notan_math/src/rect.rs +++ b/crates/notan_math/src/rect.rs @@ -1,4 +1,5 @@ #[derive(Default, Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Rect { pub x: f32, pub y: f32, diff --git a/crates/notan_oddio/Cargo.toml b/crates/notan_oddio/Cargo.toml index a5898663..b1c4a3f5 100644 --- a/crates/notan_oddio/Cargo.toml +++ b/crates/notan_oddio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_oddio" -version = "0.9.3" +version = "0.9.4" edition = "2021" readme = "README.md" homepage = "https://github.com/Nazariglez/notan" @@ -11,7 +11,7 @@ description = "Provides support for Audio features using Oddio" [dependencies] log = "0.4.17" hashbrown = "0.13.2" -notan_audio = { path = "../notan_audio", version = "0.9.3" } +notan_audio = { path = "../notan_audio", version = "0.9.4" } cpal = { version = "0.14.2", features = ["wasm-bindgen"] } oddio = "0.6.2" symphonia = { version = "0.5.2", features = ["mp3"] } diff --git a/crates/notan_random/Cargo.toml b/crates/notan_random/Cargo.toml index 75cc88b1..a3a4a323 100644 --- a/crates/notan_random/Cargo.toml +++ b/crates/notan_random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_random" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" diff --git a/crates/notan_text/Cargo.toml b/crates/notan_text/Cargo.toml index 436a490b..b2d6a2d3 100644 --- a/crates/notan_text/Cargo.toml +++ b/crates/notan_text/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_text" -version = "0.9.3" +version = "0.9.4" edition = "2021" readme = "README.md" homepage = "https://github.com/Nazariglez/notan" @@ -11,10 +11,10 @@ description = "Provides a simple Text API for Notan" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_graphics = { path = "../notan_graphics", version = "0.9.3" } -notan_glyph = { path = "../notan_glyph", version = "0.9.3" } -notan_math = { path = "../notan_math", version = "0.9.3" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_graphics = { path = "../notan_graphics", version = "0.9.4" } +notan_glyph = { path = "../notan_glyph", version = "0.9.4" } +notan_math = { path = "../notan_math", version = "0.9.4" } log = "0.4.17" lazy_static = "1.4.0" parking_lot = "0.12.1" diff --git a/crates/notan_utils/Cargo.toml b/crates/notan_utils/Cargo.toml index 0e4d83d2..c7c32ce8 100644 --- a/crates/notan_utils/Cargo.toml +++ b/crates/notan_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_utils" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" diff --git a/crates/notan_web/Cargo.toml b/crates/notan_web/Cargo.toml index eed916af..b7913733 100644 --- a/crates/notan_web/Cargo.toml +++ b/crates/notan_web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_web" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -18,12 +18,12 @@ js-sys = "0.3.60" wasm-bindgen-futures = "0.4.33" console_error_panic_hook = "0.1.7" futures-util = "0.3.25" -notan_core = { path = "../notan_core", version = "0.9.3" } -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_glow = { path = "../notan_glow", version = "0.9.3" } -notan_graphics = { path = "../notan_graphics", version = "0.9.3" } -notan_audio = { path = "../notan_audio", version = "0.9.3", optional = true } -notan_oddio = { path = "../notan_oddio", version = "0.9.3", optional = true } +notan_core = { path = "../notan_core", version = "0.9.4" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_glow = { path = "../notan_glow", version = "0.9.4" } +notan_graphics = { path = "../notan_graphics", version = "0.9.4" } +notan_audio = { path = "../notan_audio", version = "0.9.4", optional = true } +notan_oddio = { path = "../notan_oddio", version = "0.9.4", optional = true } [dependencies.web-sys] version = "0.3.60" diff --git a/crates/notan_web/src/window.rs b/crates/notan_web/src/window.rs index 22e024bd..6aa587f0 100644 --- a/crates/notan_web/src/window.rs +++ b/crates/notan_web/src/window.rs @@ -66,6 +66,8 @@ pub struct WebWindowBackend { pub(crate) captured: Rc>, mouse_passthrough: bool, + + title: String, } impl WebWindowBackend { @@ -122,6 +124,8 @@ impl WebWindowBackend { let lazy = Rc::new(RefCell::new(config.lazy_loop)); let frame_requested = Rc::new(RefCell::new(false)); + let title = config.title.clone(); + let win = Self { window, document, @@ -160,6 +164,7 @@ impl WebWindowBackend { visible, mouse_passthrough, + title, }; win.init() @@ -382,6 +387,14 @@ impl WindowBackend for WebWindowBackend { fn visible(&self) -> bool { self.visible } + + fn set_title(&mut self, title: &str) { + self.title = title.to_string(); + } + + fn title(&self) -> &str { + &self.title + } } unsafe impl Send for WebWindowBackend {} diff --git a/crates/notan_winit/Cargo.toml b/crates/notan_winit/Cargo.toml index 6da462f0..b82a2b68 100644 --- a/crates/notan_winit/Cargo.toml +++ b/crates/notan_winit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notan_winit" -version = "0.9.3" +version = "0.9.4" authors = ["Nazarí González "] edition = "2021" readme = "README.md" @@ -13,12 +13,12 @@ description = "Provides a native backend using winit for Notan" [dependencies] log = "0.4.17" -notan_core = { path = "../notan_core", version = "0.9.3" } -notan_app = { path = "../notan_app", version = "0.9.3" } -notan_glow = { path = "../notan_glow", version = "0.9.3" } -notan_audio = { path = "../notan_audio", version = "0.9.3", optional = true } -notan_oddio = { path = "../notan_oddio", version = "0.9.3", optional = true } -notan_input = { path = "../notan_input", version = "0.9.3", optional = true } +notan_core = { path = "../notan_core", version = "0.9.4" } +notan_app = { path = "../notan_app", version = "0.9.4" } +notan_glow = { path = "../notan_glow", version = "0.9.4" } +notan_audio = { path = "../notan_audio", version = "0.9.4", optional = true } +notan_oddio = { path = "../notan_oddio", version = "0.9.4", optional = true } +notan_input = { path = "../notan_input", version = "0.9.4", optional = true } glutin = "0.30.3" glutin-winit = "0.2.1" winit = "0.27.5" diff --git a/crates/notan_winit/src/window.rs b/crates/notan_winit/src/window.rs index 653863ac..c46ac322 100644 --- a/crates/notan_winit/src/window.rs +++ b/crates/notan_winit/src/window.rs @@ -18,6 +18,7 @@ pub struct WinitWindowBackend { high_dpi: bool, is_always_on_top: bool, mouse_passthrough: bool, + title: String, } impl WindowBackend for WinitWindowBackend { @@ -167,6 +168,15 @@ impl WindowBackend for WinitWindowBackend { fn visible(&self) -> bool { self.visible } + + fn set_title(&mut self, title: &str) { + self.title = title.to_string(); + self.window().set_title(&self.title); + } + + fn title(&self) -> &str { + &self.title + } } fn load_icon(path: &Option) -> Option { @@ -239,16 +249,26 @@ impl WinitWindowBackend { gl_manager.set_fullscreen(config.fullscreen); } + let WindowConfig { + lazy_loop, + visible, + high_dpi, + title, + mouse_passthrough, + .. + } = config; + Ok(Self { gl_manager, scale_factor, - lazy: config.lazy_loop, + lazy: lazy_loop, cursor: CursorIcon::Default, captured: false, - visible: config.visible, - high_dpi: config.high_dpi, + visible, + high_dpi, is_always_on_top: false, - mouse_passthrough: config.mouse_passthrough, + mouse_passthrough, + title, }) }