diff --git a/Cargo.toml b/Cargo.toml index b169036..53081a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,13 @@ edition = "2024" quick-xml = "0.31.0" serde = { version = "1.0.203", features = ["derive"] } serde_json = { version = "1.0.120" } +paste = "1.0.15" +anyhow = { version = "1.0.86", features = ["backtrace"] } + vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" } utilities = { git = "https://gavania.de/hodasemi/utilities.git" } -paste = "1.0.15" assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" } -anyhow = { version = "1.0.86", features = ["backtrace"] } +ecs = { git = "https://gavania.de/hodasemi/engine.git" } # optional audio = { git = "https://gavania.de/hodasemi/audio.git", optional = true } diff --git a/src/gui_handler/gui/clickable.rs b/src/gui_handler/gui/clickable.rs index 32b15c6..c8c3ced 100644 --- a/src/gui_handler/gui/clickable.rs +++ b/src/gui_handler/gui/clickable.rs @@ -4,13 +4,14 @@ use anyhow::Result; use super::executable::Executable; use super::framable::Framable; +use crate::prelude::*; #[cfg(feature = "audio")] use super::audible::Audible; use std::sync::{ - atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, Arc, RwLock, + atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, }; /// `Clickable` gives the ability to execute a closure when clicked @@ -54,12 +55,8 @@ impl Clickable { /// # Arguments /// /// * `clickable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_clickable(self.ui_layer.load(SeqCst), self.clone())?; - - Ok(()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_clickable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory @@ -67,11 +64,9 @@ impl Clickable { /// # Arguments /// /// * `clickable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_clickable(self.ui_layer.load(SeqCst), self)?; - self.set_clicked(false)?; + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_clickable(self.ui_layer.load(SeqCst), self)?; + self.set_clicked(gui_handler, false)?; Ok(()) } @@ -104,7 +99,7 @@ impl Clickable { *self.audible.write().unwrap() = audible; } - pub fn set_clicked(&self, clicked: bool) -> Result { + pub fn set_clicked(&self, gui_handler: &mut GuiHandler<'_>, clicked: bool) -> Result { if self.clicked() != clicked { self.clicked.store(clicked, SeqCst); @@ -122,7 +117,7 @@ impl Clickable { } } - self.executable.execute(())?; + self.executable.execute(gui_handler, ())?; } Ok(true) diff --git a/src/gui_handler/gui/colorable.rs b/src/gui_handler/gui/colorable.rs index ad7db1f..d52b7e9 100644 --- a/src/gui_handler/gui/colorable.rs +++ b/src/gui_handler/gui/colorable.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use anyhow::Result; + use utilities::{impl_reprc, prelude::*}; use vulkan_rs::prelude::*; @@ -33,17 +34,18 @@ pub struct Colorable { impl Colorable { /// Factory method for `Colorable`, returns `Arc`. pub fn new( + gui_handler: &mut GuiHandler<'_>, framable: Arc, color: Color, fill_type: DisplayableFillType, ) -> Result> { - let set = framable.gui_handler().color_descriptor(color)?; + let set = gui_handler.color_descriptor(color)?; let buffer = Buffer::builder() .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) .set_size(6) - .build(framable.gui_handler().device().clone())?; + .build(gui_handler.device().clone())?; let colorable = Arc::new(Colorable { framable, @@ -67,7 +69,7 @@ impl Colorable { colorable.framable.add_callback( weak_colorable, - Box::new(move || colorable_clone.update_frame()), + Box::new(move |gui_handler| colorable_clone.update_frame(gui_handler)), ); Ok(colorable) @@ -78,10 +80,8 @@ impl Colorable { /// # Arguments /// /// * `colorable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_colorable(self.ui_layer.load(SeqCst), self.clone()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_colorable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. @@ -89,10 +89,8 @@ impl Colorable { /// # Arguments /// /// * `colorable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_colorable(self.ui_layer.load(SeqCst), self) + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_colorable(self.ui_layer.load(SeqCst), self) } pub fn clear_callback(self: &Arc) { @@ -109,8 +107,8 @@ impl Colorable { /// # Arguments /// /// * `color` defines the color - pub fn set_color(&self, color: Color) -> Result<()> { - let set = self.framable.gui_handler().color_descriptor(color)?; + pub fn set_color(&self, color: Color, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + let set = gui_handler.color_descriptor(color)?; *self.color.write().unwrap() = color; *self.descriptor_set.write().unwrap() = set; @@ -149,7 +147,7 @@ impl Colorable { } /// Update frame method if the original frame is invalidated - pub fn update_frame(&self) -> Result<()> { + pub fn update_frame(&self, gui_handler: &GuiHandler<'_>) -> Result<()> { let mut frame = self.buffer.map_complete()?; let mut x_start = self.framable.left() as f32; @@ -177,12 +175,12 @@ impl Colorable { let top = y_start + height * *self.top_factor.read().unwrap(); let bottom = y_start + height * *self.bottom_factor.read().unwrap(); - frame[0].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); - frame[1].position = (self.framable.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); - frame[2].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); - frame[3].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); - frame[4].position = (self.framable.ortho() * vec4(left, top, 0.0, 1.0)).xy(); - frame[5].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); + frame[0].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); + frame[1].position = (gui_handler.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); + frame[2].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy(); + frame[3].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy(); + frame[4].position = (gui_handler.ortho() * vec4(left, top, 0.0, 1.0)).xy(); + frame[5].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); Ok(()) } diff --git a/src/gui_handler/gui/displayable.rs b/src/gui_handler/gui/displayable.rs index 62d8656..4204e09 100644 --- a/src/gui_handler/gui/displayable.rs +++ b/src/gui_handler/gui/displayable.rs @@ -71,18 +71,17 @@ impl Displayable { /// * `framable` is a `Arc` instance /// * `name` is the name for a png pub fn new( + gui_handler: &mut GuiHandler<'_>, framable: Arc, displayable_type: impl Into, fill_type: DisplayableFillType, ) -> Result> { - let descriptor_set = framable.gui_handler().image_descriptor_set()?; + let descriptor_set = gui_handler.image_descriptor_set()?; let displayable_type = displayable_type.into(); if let DisplayableType::Path(path) = &displayable_type { - let texture = framable - .gui_handler() - .displayable_image_from_path(path.clone())?; + let texture = gui_handler.displayable_image_from_path(path.clone())?; descriptor_set.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?; } @@ -90,7 +89,7 @@ impl Displayable { .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) .set_size(6) - .build(framable.gui_handler().device().clone())?; + .build(gui_handler.device().clone())?; let displayable = Arc::new(Displayable { framable, @@ -118,7 +117,7 @@ impl Displayable { displayable.framable.add_callback( weak_displayable, - Box::new(move || displayable_clone.update_frame()), + Box::new(move |gui_handler| displayable_clone.update_frame(gui_handler)), ); Ok(displayable) @@ -129,10 +128,8 @@ impl Displayable { /// # Arguments /// /// * `displayable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_displayable(self.ui_layer.load(SeqCst), self.clone()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_displayable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory @@ -140,10 +137,8 @@ impl Displayable { /// # Arguments /// /// * `displayable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_displayable(self.ui_layer.load(SeqCst), self) + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_displayable(self.ui_layer.load(SeqCst), self) } pub fn inner_type(&self) -> DisplayableType { @@ -164,25 +159,21 @@ impl Displayable { /// # Arguments /// /// * `name` is the name of the texture in `gui/` without `.png` suffix - pub fn set_image(&self, displayable_type: impl Into) -> Result<()> { + pub fn set_image( + &self, + gui_handler: &mut GuiHandler<'_>, + displayable_type: impl Into, + ) -> Result<()> { let displayable_type = displayable_type.into(); let texture = match displayable_type.clone() { - DisplayableType::Path(path) => Some( - self.framable - .gui_handler() - .displayable_image_from_path(path)?, - ), + DisplayableType::Path(path) => Some(gui_handler.displayable_image_from_path(path)?), DisplayableType::Descriptor(descriptor) => { let width = (self.framable.right() - self.framable.left()) as u32; let height = (self.framable.bottom() - self.framable.top()) as u32; if width > 0 && height > 0 { - Some( - self.framable - .gui_handler() - .displayable_image_from_descriptor(width, height, descriptor)?, - ) + Some(gui_handler.displayable_image_from_descriptor(width, height, descriptor)?) } else { None } @@ -242,7 +233,7 @@ impl Displayable { } /// Update frame method if the original frame is invalidated - pub fn update_frame(&self) -> Result<()> { + pub fn update_frame(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { let mut frame = self.buffer.map_complete()?; let mut x_start = self.framable.left() as f32; @@ -267,14 +258,11 @@ impl Displayable { if let DisplayableType::Descriptor(descriptor) = &*self.displayable_type.read().unwrap() { if width > 0.0 && height > 0.0 { - let texture = self - .framable - .gui_handler() - .displayable_image_from_descriptor( - width as u32, - height as u32, - descriptor.clone(), - )?; + let texture = gui_handler.displayable_image_from_descriptor( + width as u32, + height as u32, + descriptor.clone(), + )?; self.descriptor_set .update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?; @@ -286,12 +274,12 @@ impl Displayable { let top = y_start + height * *self.top_factor.read().unwrap(); let bottom = y_start + height * *self.bottom_factor.read().unwrap(); - frame[0].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); - frame[1].position = (self.framable.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); - frame[2].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); - frame[3].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); - frame[4].position = (self.framable.ortho() * vec4(left, top, 0.0, 1.0)).xy(); - frame[5].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); + frame[0].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); + frame[1].position = (gui_handler.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); + frame[2].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy(); + frame[3].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy(); + frame[4].position = (gui_handler.ortho() * vec4(left, top, 0.0, 1.0)).xy(); + frame[5].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); frame[0].texture_coordinates = vec2( *self.left_uv_factor.read().unwrap(), diff --git a/src/gui_handler/gui/executable.rs b/src/gui_handler/gui/executable.rs index 8da393d..dc169bf 100644 --- a/src/gui_handler/gui/executable.rs +++ b/src/gui_handler/gui/executable.rs @@ -8,15 +8,13 @@ use crate::prelude::*; /// `Executable` holds a closure which can be executed pub struct Executable { - gui_handler: Arc, callback: RwLock Result<()> + Send + Sync>>>, } impl Executable { /// Factory method for `Executable`, returns `Arc` - pub fn new(gui_handler: &Arc) -> Arc { + pub fn new() -> Arc { Arc::new(Executable { - gui_handler: gui_handler.clone(), callback: RwLock::new(None), }) } @@ -39,11 +37,11 @@ impl Executable { } /// Execute the callback closure if possible - pub fn execute(&self, input: I) -> Result<()> { + pub fn execute(&self, gui_handler: &mut GuiHandler<'_>, input: I) -> Result<()> { if let Some(callback) = self.callback.read().unwrap().as_ref() { let callback = callback.clone(); - self.gui_handler.add_callback(move || (callback)(input)); + gui_handler.add_callback(move || (callback)(input)); } Ok(()) diff --git a/src/gui_handler/gui/framable.rs b/src/gui_handler/gui/framable.rs index 6a5e02f..d52609f 100644 --- a/src/gui_handler/gui/framable.rs +++ b/src/gui_handler/gui/framable.rs @@ -6,13 +6,11 @@ use anyhow::Result; use std::{ ffi::c_void, sync::{ - atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering::SeqCst}, Arc, RwLock, Weak, + atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering::SeqCst}, }, }; -use vulkan_rs::prelude::cgmath::Matrix4; - /// Describes the vertical alignment for a `Framable` #[derive(Copy, Clone, PartialEq)] pub enum VerticalAlign { @@ -77,8 +75,6 @@ impl Drop for Handle { /// `Framable` keeps track of the position and size of an item /// and calls functions on resize to keep everything aligned correctly pub struct Framable { - gui_handler: Arc, - left: AtomicI32, right: AtomicI32, top: AtomicI32, @@ -87,7 +83,12 @@ pub struct Framable { vertical_alignment: RwLock, horizontal_alignment: RwLock, - resize_callbacks: RwLock Result<()> + Send + Sync>)>>, + resize_callbacks: RwLock< + Vec<( + Handle, + Box) -> Result<()> + Send + Sync>, + )>, + >, x_off: AtomicI32, y_off: AtomicI32, @@ -111,12 +112,10 @@ pub struct Framable { impl Framable { /// Factory method for `Framable`, returns `Arc` - pub fn new(gui_handler: Arc, resize_allowed: bool) -> Result> { + pub fn new(window_width: u32, window_height: u32, resize_allowed: bool) -> Result> { Ok(Arc::new(Framable { - window_width: AtomicU32::new(gui_handler.width()), - window_height: AtomicU32::new(gui_handler.height()), - - gui_handler, + window_width: AtomicU32::new(window_width), + window_height: AtomicU32::new(window_height), left: AtomicI32::new(0), right: AtomicI32::new(0), @@ -150,22 +149,21 @@ impl Framable { /// # Arguments /// /// * `framable` - is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { // check if window size is the same as last time - if self.gui_handler.width() != self.window_width.load(SeqCst) - || self.gui_handler.height() != self.window_height.load(SeqCst) + if gui_handler.width() != self.window_width.load(SeqCst) + || gui_handler.height() != self.window_height.load(SeqCst) { // update window size - self.window_width.store(self.gui_handler.width(), SeqCst); - self.window_height.store(self.gui_handler.height(), SeqCst); + self.window_width.store(gui_handler.width(), SeqCst); + self.window_height.store(gui_handler.height(), SeqCst); // force resize - self.resize()?; + self.resize(gui_handler)?; } if self.resize_allowed() { - self.gui_handler - .add_framable(self.ui_layer.load(SeqCst), self.clone())?; + gui_handler.add_framable(self.ui_layer.load(SeqCst), self.clone())?; } Ok(()) @@ -176,10 +174,9 @@ impl Framable { /// # Arguments /// /// * `framable` - is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { if self.resize_allowed() { - self.gui_handler - .delete_framable(self.ui_layer.load(SeqCst), self)?; + gui_handler.delete_framable(self.ui_layer.load(SeqCst), self)?; } Ok(()) @@ -193,36 +190,49 @@ impl Framable { self.ui_layer.load(SeqCst) } - pub(crate) fn set_reference_size(&self, width: u32, height: u32) -> Result<()> { + pub(crate) fn set_reference_size( + &self, + gui_handler: &mut GuiHandler<'_>, + width: u32, + height: u32, + ) -> Result<()> { *self.reference_size.write().unwrap() = Some((width, height)); self.reference_scale_position.store(true, SeqCst); self.reference_scale_size.store(true, SeqCst); if self.is_framed() { - self.resize()?; + self.resize(gui_handler)?; } Ok(()) } - pub(crate) fn allow_position_scale(&self, allowed: bool) -> Result<()> { + pub(crate) fn allow_position_scale( + &self, + gui_handler: &mut GuiHandler<'_>, + allowed: bool, + ) -> Result<()> { if allowed != self.reference_scale_position.load(SeqCst) { self.reference_scale_position.store(allowed, SeqCst); if self.is_framed() { - self.resize()?; + self.resize(gui_handler)?; } } Ok(()) } - pub(crate) fn allow_size_scale(&self, allowed: bool) -> Result<()> { + pub(crate) fn allow_size_scale( + &self, + gui_handler: &mut GuiHandler<'_>, + allowed: bool, + ) -> Result<()> { if allowed != self.reference_scale_size.load(SeqCst) { self.reference_scale_size.store(allowed, SeqCst); if self.is_framed() { - self.resize()?; + self.resize(gui_handler)?; } } @@ -237,6 +247,7 @@ impl Framable { /// width and a certain alignment pub fn set_frame( &self, + gui_handler: &GuiHandler<'_>, x_off: i32, y_off: i32, w: u32, @@ -252,7 +263,7 @@ impl Framable { *self.vertical_alignment.write().unwrap() = vertical_align; *self.horizontal_alignment.write().unwrap() = horizontal_align; - self.calculate_frame(); + self.calculate_frame(gui_handler); self.framed.store(true, SeqCst); } @@ -296,16 +307,11 @@ impl Framable { self.framed.load(SeqCst) } - /// Returns the ortho 4x4 matrix, which describes the window - pub fn ortho(&self) -> Matrix4 { - self.gui_handler.ortho() - } - /// Adds a callback closure which is executed on resize pub fn add_callback( &self, handle: impl Into, - callback: Box Result<()> + Send + Sync>, + callback: Box) -> Result<()> + Send + Sync>, ) { let handle = handle.into(); @@ -348,9 +354,9 @@ impl Framable { *self.horizontal_alignment.read().unwrap() } - fn calculate_frame(&self) { - let width = self.gui_handler.width(); - let height = self.gui_handler.height(); + fn calculate_frame(&self, gui_handler: &GuiHandler<'_>) { + let width = gui_handler.width(); + let height = gui_handler.height(); let y_align = match *self.vertical_alignment.read().unwrap() { VerticalAlign::Top => 0, @@ -420,17 +426,27 @@ impl Framable { self.bottom.store(bottom, SeqCst); } - pub fn change_position(&self, x_offset: i32, y_offset: i32) -> Result<()> { + pub fn change_position( + &self, + gui_handler: &mut GuiHandler<'_>, + x_offset: i32, + y_offset: i32, + ) -> Result<()> { assert!(self.is_framed(), "framable needs to be framed first!"); self.x_off.store(x_offset, SeqCst); self.y_off.store(y_offset, SeqCst); - self.resize()?; + self.resize(gui_handler)?; Ok(()) } - pub fn change_position_unscaled(&self, x: i32, y: i32) -> Result<()> { + pub fn change_position_unscaled( + &self, + gui_handler: &mut GuiHandler<'_>, + x: i32, + y: i32, + ) -> Result<()> { assert!(self.is_framed(), "framable needs to be framed first!"); let left = self.left.load(SeqCst); @@ -447,23 +463,19 @@ impl Framable { self.bottom.store(y + height, SeqCst); for (_, callback) in self.resize_callbacks.read().unwrap().iter() { - callback()?; + callback(gui_handler)?; } Ok(()) } - pub fn resize(&self) -> Result<()> { - self.calculate_frame(); + pub fn resize(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + self.calculate_frame(gui_handler); for (_, callback) in self.resize_callbacks.read().unwrap().iter() { - callback()?; + callback(gui_handler)?; } Ok(()) } - - pub(crate) fn gui_handler(&self) -> &Arc { - &self.gui_handler - } } diff --git a/src/gui_handler/gui/hoverable.rs b/src/gui_handler/gui/hoverable.rs index 8a0395a..40274b9 100644 --- a/src/gui_handler/gui/hoverable.rs +++ b/src/gui_handler/gui/hoverable.rs @@ -5,8 +5,8 @@ use crate::prelude::*; use anyhow::Result; use std::sync::{ - atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, Arc, + atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, }; #[cfg(feature = "audio")] @@ -56,10 +56,8 @@ impl Hoverable { /// # Arguments /// /// * `hoverable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_hoverable(self.ui_layer.load(SeqCst), self.clone())?; + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_hoverable(self.ui_layer.load(SeqCst), self.clone())?; Ok(()) } @@ -69,11 +67,9 @@ impl Hoverable { /// # Arguments /// /// * `hoverable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_hoverable(self.ui_layer.load(SeqCst), self)?; - self.set_hovered(false)?; + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_hoverable(self.ui_layer.load(SeqCst), self)?; + self.set_hovered(gui_handler, false)?; Ok(()) } @@ -107,12 +103,13 @@ impl Hoverable { /// # Arguments /// /// * `hovered` is the new hovered state - pub fn set_hovered(&self, hovered: bool) -> Result<()> { + pub fn set_hovered(&self, gui_handler: &mut GuiHandler<'_>, hovered: bool) -> Result<()> { if self.hovered() != hovered { self.hovered.store(hovered, SeqCst); - self.hover_changed_executable.execute(hovered)?; - self.on_hover_executable.execute(hovered)?; + self.hover_changed_executable + .execute(gui_handler, hovered)?; + self.on_hover_executable.execute(gui_handler, hovered)?; #[cfg(feature = "audio")] { diff --git a/src/gui_handler/gui/iconizable.rs b/src/gui_handler/gui/iconizable.rs index acf695c..b464e25 100644 --- a/src/gui_handler/gui/iconizable.rs +++ b/src/gui_handler/gui/iconizable.rs @@ -9,8 +9,8 @@ use vulkan_rs::prelude::*; use super::texturedvertex::TexturedVertex; use std::sync::{ - atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, Arc, RwLock, + atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, }; #[derive(Clone, Debug)] @@ -85,16 +85,17 @@ impl Iconizable { /// * `framable` is a `Arc` instance /// * `icon` is a reference to an `Arc` pub fn new( + gui_handler: &mut GuiHandler<'_>, framable: Arc, icon_builder: impl Into, positioning: impl Into>, ) -> Result> { - let icon = framable.gui_handler().request_icon(icon_builder)?; + let icon = gui_handler.request_icon(icon_builder)?; - let device = framable.gui_handler().device(); + let device = gui_handler.device(); let desc_pool = DescriptorPool::builder() - .set_layout(framable.gui_handler().icon_descriptor_layout().clone()) + .set_layout(gui_handler.icon_descriptor_layout().clone()) .build(device.clone())?; let descriptor_set = DescriptorPool::prepare_set(&desc_pool).allocate()?; @@ -125,7 +126,7 @@ impl Iconizable { iconizable.framable.add_callback( weak_iconizable, - Box::new(move || iconizable_clone.update_frame()), + Box::new(move |gui_handler| iconizable_clone.update_frame(gui_handler)), ); Ok(iconizable) @@ -136,10 +137,8 @@ impl Iconizable { /// # Arguments /// /// * `iconizable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_iconizable(self.ui_layer.load(SeqCst), self.clone()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_iconizable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory @@ -147,10 +146,8 @@ impl Iconizable { /// # Arguments /// /// * `iconizable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_iconizable(self.ui_layer.load(SeqCst), self) + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_iconizable(self.ui_layer.load(SeqCst), self) } pub fn set_ui_layer(&self, ui_layer: i32) { @@ -175,7 +172,7 @@ impl Iconizable { } /// Updates the frame - pub fn update_frame(&self) -> Result<()> { + pub fn update_frame(&self, gui_handler: &GuiHandler<'_>) -> Result<()> { assert!(self.framable.is_framed(), "framable is not framed yet"); // frame parameter @@ -239,7 +236,7 @@ impl Iconizable { let right = left + resulting_width; let bottom = top + resulting_height; - let ortho = self.framable.ortho(); + let ortho = gui_handler.ortho(); let mut frame = self.buffer.map_complete()?; @@ -270,8 +267,12 @@ impl Iconizable { /// # Arguments /// /// * `icon` the new icon - pub fn set_icon(&self, icon_builder: impl Into) -> Result<()> { - let icon = self.framable.gui_handler().request_icon(icon_builder)?; + pub fn set_icon( + &self, + gui_handler: &mut GuiHandler<'_>, + icon_builder: impl Into, + ) -> Result<()> { + let icon = gui_handler.request_icon(icon_builder)?; self.descriptor_set .update(&[DescriptorWrite::combined_samplers(0, &[&icon])])?; diff --git a/src/gui_handler/gui/selectable.rs b/src/gui_handler/gui/selectable.rs index b1aab5f..1522637 100644 --- a/src/gui_handler/gui/selectable.rs +++ b/src/gui_handler/gui/selectable.rs @@ -5,22 +5,20 @@ use crate::prelude::*; use anyhow::Result; use std::sync::{ - atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, Arc, RwLock, Weak, + atomic::{AtomicBool, AtomicI32, Ordering::SeqCst}, }; /// `Selectable` gives the ability to navigate per button or controller to /// optionally adjacent neighbour Selectables and to execute a closure /// when the current Selectable is pressed pub struct Selectable<'a> { - - selected: AtomicBool, - east_neighbour: RwLock>>, - west_neighbour: RwLock>>, - north_neighbour: RwLock>>, - south_neighbour: RwLock>>, + east_neighbour: RwLock>>>, + west_neighbour: RwLock>>>, + north_neighbour: RwLock>>>, + south_neighbour: RwLock>>>, #[cfg(feature = "audio")] select_audible: RwLock>>, @@ -38,10 +36,11 @@ pub struct Selectable<'a> { selected_changed_executable: Arc>, // exposed externally for event - on_select_executable: Arc>, + on_select_executable: Arc>, // used for custom buttons - custom_callback: RwLock Result + Send + Sync>>>, + custom_callback: + RwLock Result + Send + Sync>>>, } impl<'a> Selectable<'a> { @@ -51,15 +50,12 @@ impl<'a> Selectable<'a> { /// /// * `executable` is a `Arc` instance pub fn new( - gui_handler: &'a GuiHandler<'a>, - executable: Arc>, - selected_changed_executable: Arc>, - on_select_executable: Arc>, + executable: Arc>, + selected_changed_executable: Arc>, + on_select_executable: Arc>, isolate: bool, ) -> Arc { Arc::new(Selectable { - - selected: AtomicBool::new(false), east_neighbour: RwLock::new(None), @@ -89,11 +85,8 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selectable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.gui_handler - .add_selectable(self.ui_layer.load(SeqCst), self.clone())?; - - Ok(()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_selectable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. @@ -101,10 +94,9 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selectable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.gui_handler - .delete_selectable(self.ui_layer.load(SeqCst), self)?; - self.set_selected(false)?; + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_selectable(self.ui_layer.load(SeqCst), self)?; + self.set_selected(gui_handler, false)?; Ok(()) } @@ -118,8 +110,8 @@ impl<'a> Selectable<'a> { /// # Argument /// /// * `selectable` is a `Arc` instance - pub fn select(self: &Arc) -> Result<()> { - self.gui_handler.set_selectable(Some(self.clone())) + pub fn select(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.set_selectable(Some(self.clone())) } pub fn set_custom_callback(&self, custom_callback: F) @@ -145,12 +137,13 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selected` is the new selected state - pub fn set_selected(&self, selected: bool) -> Result<()> { + pub fn set_selected(&self, gui_handler: &mut GuiHandler<'_>, selected: bool) -> Result<()> { if self.selected() != selected { self.selected.store(selected, SeqCst); - self.selected_changed_executable.execute(selected)?; - self.on_select_executable.execute(selected)?; + self.selected_changed_executable + .execute(gui_handler, selected)?; + self.on_select_executable.execute(gui_handler, selected)?; #[cfg(feature = "audio")] { @@ -171,7 +164,7 @@ impl<'a> Selectable<'a> { } /// Executes the `Executable`'s callback - pub(crate) fn click_event(&self) -> Result<()> { + pub(crate) fn click_event(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { #[cfg(feature = "audio")] { if let Some(audible) = self.click_audible.read().unwrap().as_ref() { @@ -179,7 +172,7 @@ impl<'a> Selectable<'a> { } } - self.executable.execute(())?; + self.executable.execute(gui_handler, ())?; Ok(()) } @@ -202,7 +195,7 @@ impl<'a> Selectable<'a> { } /// Returns the current east neighbour, if possible - pub fn east_neighbour(&self) -> Option> { + pub fn east_neighbour(&self) -> Option>> { if let Some(weak_neighbour) = self.east_neighbour.read().unwrap().as_ref() { if let Some(neighbour) = weak_neighbour.upgrade() { return Some(neighbour); @@ -217,7 +210,7 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selectable` the new east neighbour - pub fn set_east_neighbour(&self, selectable: Option<&Arc>) { + pub fn set_east_neighbour(&self, selectable: Option<&Arc>>) { if self.isolate { return; } @@ -231,7 +224,7 @@ impl<'a> Selectable<'a> { } /// Returns the current west neighbour, if possible - pub fn west_neighbour(&self) -> Option> { + pub fn west_neighbour(&self) -> Option>> { if let Some(weak_neighbour) = self.west_neighbour.read().unwrap().as_ref() { if let Some(neighbour) = weak_neighbour.upgrade() { return Some(neighbour); @@ -246,7 +239,7 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selectable` the new west neighbour - pub fn set_west_neighbour(&self, selectable: Option<&Arc>) { + pub fn set_west_neighbour(&self, selectable: Option<&Arc>>) { if self.isolate { return; } @@ -260,7 +253,7 @@ impl<'a> Selectable<'a> { } /// Returns the current north neighbour, if possible - pub fn north_neighbour(&self) -> Option> { + pub fn north_neighbour(&self) -> Option>> { if let Some(weak_neighbour) = self.north_neighbour.read().unwrap().as_ref() { if let Some(neighbour) = weak_neighbour.upgrade() { return Some(neighbour); @@ -275,7 +268,7 @@ impl<'a> Selectable<'a> { /// # Argumnents /// /// * `selectable` the new north neighbour - pub fn set_north_neighbour(&self, selectable: Option<&Arc>) { + pub fn set_north_neighbour(&self, selectable: Option<&Arc>>) { if self.isolate { return; } @@ -289,7 +282,7 @@ impl<'a> Selectable<'a> { } /// Returns the current south neighbour, if possible - pub fn south_neighbour(&self) -> Option> { + pub fn south_neighbour(&self) -> Option>> { if let Some(weak_neighbour) = self.south_neighbour.read().unwrap().as_ref() { if let Some(neighbour) = weak_neighbour.upgrade() { return Some(neighbour); @@ -304,7 +297,7 @@ impl<'a> Selectable<'a> { /// # Arguments /// /// * `selectable` the new south neighbour - pub fn set_south_neighbour(&self, selectable: Option<&Arc>) { + pub fn set_south_neighbour(&self, selectable: Option<&Arc>>) { if self.isolate { return; } @@ -317,7 +310,7 @@ impl<'a> Selectable<'a> { } } - pub fn connect_vertically(upper: &Arc, lower: &Arc) { + pub fn connect_vertically<'c>(upper: &Arc>, lower: &Arc>) { if upper.isolate || lower.isolate { return; } @@ -326,7 +319,7 @@ impl<'a> Selectable<'a> { *lower.north_neighbour.write().unwrap() = Some(Arc::downgrade(upper)); } - pub fn connect_horizontally(left: &Arc, right: &Arc) { + pub fn connect_horizontally<'c>(left: &Arc>, right: &Arc>) { if left.isolate || right.isolate { return; } diff --git a/src/gui_handler/gui/textable.rs b/src/gui_handler/gui/textable.rs index 44f6b88..ead8e94 100644 --- a/src/gui_handler/gui/textable.rs +++ b/src/gui_handler/gui/textable.rs @@ -11,8 +11,8 @@ use super::texturedvertex::TexturedVertex; use std::{ convert::TryFrom, sync::{ - atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, Arc, RwLock, + atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, }, }; @@ -47,7 +47,7 @@ impl TryFrom for TextAlignment { return Err(anyhow::Error::msg(format!( "Failed parsing TextAlignment from: {}", text - ))) + ))); } }) } @@ -80,19 +80,20 @@ impl Textable { /// * `height_ratio` the ratio of the height in respect to the framable height /// * `text_alignment` where the text is aligned to pub fn new( + gui_handler: &mut GuiHandler<'_>, framable: Arc, text: String, height_ratio: f32, text_alignment: TextAlignment, text_color: Color, ) -> Result> { - let set = framable.gui_handler().color_descriptor(text_color)?; + let set = gui_handler.color_descriptor(text_color)?; let buffer = if text.is_empty() { None } else { Some(Self::create_text_buffer( - framable.gui_handler().device(), + gui_handler.device(), text.len() as u32 * 6, )?) }; @@ -120,7 +121,7 @@ impl Textable { textable.framable.add_callback( weak_textable, - Box::new(move || textable_clone.update_text()), + Box::new(move |gui_handler| textable_clone.update_text(gui_handler)), ); Ok(textable) @@ -142,10 +143,8 @@ impl Textable { /// # Arguments /// /// * `textable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .add_textable(self.ui_layer.load(SeqCst), self.clone()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_textable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. @@ -153,10 +152,8 @@ impl Textable { /// # Arguments /// /// * `textable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.framable - .gui_handler() - .delete_textable(self.ui_layer.load(SeqCst), self) + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_textable(self.ui_layer.load(SeqCst), self) } pub fn set_ui_layer(&self, ui_layer: i32) { @@ -173,8 +170,12 @@ impl Textable { /// # Arguments /// /// * `text_color` defines the color of the text - pub fn set_text_color(&self, text_color: Color) -> Result<()> { - let set = self.framable.gui_handler().color_descriptor(text_color)?; + pub fn set_text_color( + &self, + gui_handler: &mut GuiHandler<'_>, + text_color: Color, + ) -> Result<()> { + let set = gui_handler.color_descriptor(text_color)?; *self.descriptor_set.write().unwrap() = set; @@ -186,9 +187,13 @@ impl Textable { /// # Arguments /// /// * `text_alignment` where the text is aligned to - pub fn set_text_alignment(&self, text_alignment: TextAlignment) -> Result<()> { + pub fn set_text_alignment( + &self, + gui_handler: &mut GuiHandler<'_>, + text_alignment: TextAlignment, + ) -> Result<()> { *self.text_alignment.write().unwrap() = text_alignment; - self.update_text()?; + self.update_text(gui_handler)?; Ok(()) } @@ -214,14 +219,14 @@ impl Textable { /// /// * `text` the text to be displayed /// * `height_ratio` the ratio of the height in respect to the framable height - pub fn set_text(&self, text: impl ToString) -> Result<()> { + pub fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: impl ToString) -> Result<()> { let text = text.to_string(); if text.is_empty() { self.vertex_count.store(0, SeqCst); *self.text.write().unwrap() = String::new(); - self.framable.gui_handler().enqueue_text_update({ + gui_handler.enqueue_text_update({ let weak_buffer = Arc::downgrade(&self.buffer); Box::new(move || { @@ -234,7 +239,7 @@ impl Textable { } else { self.vertex_count.store(text.len() as u32 * 6, SeqCst); *self.text.write().unwrap() = text; - self.update_text()?; + self.update_text(gui_handler)?; } Ok(()) @@ -245,9 +250,9 @@ impl Textable { /// # Arguments /// /// * `height_ratio` the ratio of the height in respect to the framable height - pub fn set_size(&self, height_ratio: f32) -> Result<()> { + pub fn set_size(&self, gui_handler: &mut GuiHandler<'_>, height_ratio: f32) -> Result<()> { *self.height_ratio.write().unwrap() = height_ratio; - self.update_text()?; + self.update_text(gui_handler)?; Ok(()) } @@ -279,12 +284,12 @@ impl Textable { } /// Updates the texts buffer - pub fn update_text(&self) -> Result<()> { + pub fn update_text(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { self.calculate_text_size(); let (x, y) = self.calc_pos_from_alignment(); - self.create_buffer(x, y)?; + self.create_buffer(gui_handler, x, y)?; Ok(()) } @@ -320,13 +325,18 @@ impl Textable { } } - fn create_buffer(&self, win_x: f32, win_y: f32) -> Result<()> { + fn create_buffer( + &self, + gui_handler: &mut GuiHandler<'_>, + win_x: f32, + win_y: f32, + ) -> Result<()> { let weak_buffer = Arc::downgrade(&self.buffer); let text = self.text.read().unwrap().clone(); let character_size = self.character_size.load(SeqCst); - let ortho = self.framable.ortho(); + let ortho = gui_handler.ortho(); - let device = self.framable.gui_handler().device().clone(); + let device = gui_handler.device().clone(); let async_buffer_creation = Box::new(move || { if let Some(buffer) = weak_buffer.upgrade() { @@ -484,14 +494,12 @@ impl Textable { Ok(()) }); - self.framable - .gui_handler() - .enqueue_text_update(async_buffer_creation); + gui_handler.enqueue_text_update(async_buffer_creation); Ok(()) } - fn text_changed_through_write(&self) -> Result<()> { + fn text_changed_through_write(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { self.vertex_count .store(self.text.read().unwrap().len() as u32 * 6, SeqCst); self.character_size.store( @@ -500,28 +508,28 @@ impl Textable { SeqCst, ); - self.update_text()?; + self.update_text(gui_handler)?; Ok(()) } } impl ModifyText for Textable { - fn set_text(&self, text: String) -> Result<()> { + fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()> { *self.text.write().unwrap() = text; - self.text_changed_through_write() + self.text_changed_through_write(gui_handler) } - fn add_letter(&self, letter: char) -> Result { + fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result { self.text.write().unwrap().push(letter); - self.text_changed_through_write()?; + self.text_changed_through_write(gui_handler)?; Ok(self.text.read().unwrap().clone()) } - fn remove_last(&self) -> Result> { + fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result> { self.text.write().unwrap().pop(); - self.text_changed_through_write()?; + self.text_changed_through_write(gui_handler)?; let text = self.text.read().unwrap().clone(); diff --git a/src/gui_handler/gui/writeable.rs b/src/gui_handler/gui/writeable.rs index cc37332..3a6e244 100644 --- a/src/gui_handler/gui/writeable.rs +++ b/src/gui_handler/gui/writeable.rs @@ -4,20 +4,18 @@ use crate::prelude::*; use anyhow::Result; use std::sync::{ - atomic::{AtomicI32, Ordering::SeqCst}, Arc, RwLock, + atomic::{AtomicI32, Ordering::SeqCst}, }; pub trait ModifyText: Send + Sync { - fn set_text(&self, text: String) -> Result<()>; - fn add_letter(&self, letter: char) -> Result; - fn remove_last(&self) -> Result>; + fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()>; + fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result; + fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result>; } /// `Writeable` gives the ability to modify the text inside an `Textable` pub struct Writeable { - gui_handler: Arc, - modifyable: Arc, text_change_executable: Arc>>, @@ -29,12 +27,10 @@ pub struct Writeable { impl Writeable { /// Factory method for `Writeable`, returns `Arc`. pub fn new( - gui_handler: Arc, modifyable: Arc, text_change_executable: Arc>>, ) -> Result> { Ok(Arc::new(Writeable { - gui_handler, modifyable, text_change_executable, @@ -44,8 +40,8 @@ impl Writeable { })) } - pub fn set_active(self: &Arc) -> Result<()> { - if self.gui_handler.set_active_writeable(self.clone())? { + pub fn set_active(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + if gui_handler.set_active_writeable(self.clone())? { if let Some(exec) = &*self.activation_changed_executable.read().unwrap() { exec(true)?; } @@ -74,9 +70,8 @@ impl Writeable { /// # Arguments /// /// * `writeable` is a `&Arc` instance that is going to be added - pub fn add(self: &Arc) -> Result<()> { - self.gui_handler - .add_writeable(self.ui_layer.load(SeqCst), self.clone()) + pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.add_writeable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. @@ -84,9 +79,8 @@ impl Writeable { /// # Arguments /// /// * `writeable` is a `&Arc` instance that is going to be deleted - pub fn delete(self: &Arc) -> Result<()> { - self.gui_handler - .delete_writeable(self.ui_layer.load(SeqCst), self) + pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { + gui_handler.delete_writeable(self.ui_layer.load(SeqCst), self) } pub fn set_ui_layer(&self, ui_layer: i32) { @@ -98,11 +92,11 @@ impl Writeable { /// # Arguments /// /// * `text` that replaces the current text - pub fn set_text(&self, text: String) -> Result<()> { - self.modifyable.set_text(text.clone())?; + pub fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()> { + self.modifyable.set_text(gui_handler, text.clone())?; self.text_change_executable - .execute(if text.is_empty() { None } else { Some(text) })?; + .execute(gui_handler, if text.is_empty() { None } else { Some(text) })?; Ok(()) } @@ -112,17 +106,19 @@ impl Writeable { /// # Arguments /// /// * `letter` the letter thats going to be added - pub fn add_letter(&self, letter: char) -> Result<()> { - self.text_change_executable - .execute(Some(self.modifyable.add_letter(letter)?))?; + pub fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<()> { + self.text_change_executable.execute( + gui_handler, + Some(self.modifyable.add_letter(gui_handler, letter)?), + )?; Ok(()) } /// Removes the last letter - pub fn remove_last(&self) -> Result<()> { + pub fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { self.text_change_executable - .execute(self.modifyable.remove_last()?)?; + .execute(gui_handler, self.modifyable.remove_last(gui_handler)?)?; Ok(()) } diff --git a/src/gui_handler/gui_handler.rs b/src/gui_handler/gui_handler.rs index 02e8af0..516f12e 100644 --- a/src/gui_handler/gui_handler.rs +++ b/src/gui_handler/gui_handler.rs @@ -1,6 +1,7 @@ use crate::prelude::*; use anyhow::{Result, anyhow}; use assetpath::AssetPath; + use serde::{Deserialize, Serialize}; use utilities::{impl_reprc, prelude::*}; use vulkan_rs::{prelude::*, render_target::sub_pass::InputAttachmentInfo}; @@ -14,10 +15,7 @@ use super::{ use cgmath::{ortho, vec2}; -use std::sync::{ - Arc, Mutex, RwLock, - atomic::{AtomicBool, AtomicU32, Ordering::SeqCst}, -}; +use std::sync::{Arc, Mutex}; use std::{collections::HashMap, ptr}; use std::{mem, sync::Weak}; @@ -90,7 +88,7 @@ struct TextableColor { } struct CommandBufferState { - text_buffers: RwLock>>>, + text_buffers: Vec>>, } struct TextToScreen { @@ -103,7 +101,7 @@ impl TextToScreen { fn new( device: &Arc, pipeline: TargetMode, - render_target: &TargetMode>, + render_target: &TargetMode, ) -> Result { let descriptor = pipeline .chain(render_target) @@ -114,7 +112,7 @@ impl TextToScreen { .prepare_set() .allocate()?; - Self::update_descriptor(&descriptor, &*render_target.read().unwrap())?; + Self::update_descriptor(&descriptor, render_target)?; Ok(descriptor) })?; @@ -171,11 +169,11 @@ impl TextToScreen { .change_image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)]) } - fn update_on_resize(&self, render_target: &TargetMode>) -> Result<()> { + fn update_on_resize(&self, render_target: &TargetMode) -> Result<()> { self.descriptor .chain(render_target) .execute(|(descriptor, render_target)| { - Self::update_descriptor(descriptor, &*render_target.read().unwrap()) + Self::update_descriptor(descriptor, render_target) })?; Ok(()) @@ -186,15 +184,15 @@ pub struct GuiHandler<'a> { device: Arc, queue: Arc>, - width: AtomicU32, - height: AtomicU32, + width: u32, + height: u32, resource_base_path: Option, - top_ui: RwLock>>, - tooltip_ui: RwLock>>, + top_ui: Option>, + tooltip_ui: Option>, - render_targets: TargetMode>, + render_targets: TargetMode, command_buffers: TargetMode>, text_objects: TargetMode, @@ -209,20 +207,20 @@ pub struct GuiHandler<'a> { text_color_layout: Arc, - internal_icons: RwLock>>, - internal_textures: RwLock>>, - internal_colors: RwLock>, + internal_icons: HashMap>, + internal_textures: HashMap>, + internal_colors: HashMap, element_creator: Mutex, - ortho: RwLock>, + ortho: cgmath::Matrix4, icon_descriptor_layout: Arc, - needs_update: AtomicBool, - text_change_queue: RwLock Result<()> + Send + Sync>>>, + needs_update: bool, + text_change_queue: Vec Result<()> + Send + Sync>>, - on_selected: RwLock Result<()> + Send + Sync>>>, + on_selected: Option Result<()> + Send + Sync>>, #[cfg(feature = "audio")] click_sound: Option, @@ -231,28 +229,28 @@ pub struct GuiHandler<'a> { hover_sound: Option, // ----- gui handling ----- - layers: Mutex>, + layers: Vec<(i32, Elements)>, - mouse_x: AtomicU32, - mouse_y: AtomicU32, + mouse_x: u32, + mouse_y: u32, - last_direction: Mutex, + last_direction: GuiDirection, - current_writeable: RwLock>>, - current_hoverable: RwLock>>, - current_clickable: RwLock>>, - current_selectable: RwLock>>>, + current_writeable: Option>, + current_hoverable: Option>, + current_clickable: Option>, + current_selectable: Option>>, text_sample_count: VkSampleCountFlags, - callback_list: Mutex Result<()> + Send + Sync>>>, + callback_list: Vec Result<()> + Send + Sync>>, } impl<'a> GuiHandler<'a> { pub fn new( gui_handler_create_info: GuiHandlerCreateInfo<'_>, context: &impl ContextInterface, - ) -> Result> { + ) -> Result { let device = context.device(); let queue = context.queue(); @@ -297,12 +295,12 @@ impl<'a> GuiHandler<'a> { ) .build(device.clone())?; - Ok(Arc::new(GuiHandler { + Ok(GuiHandler { device: device.clone(), queue: queue.clone(), - width: AtomicU32::new(context.width()), - height: AtomicU32::new(context.height()), + width: context.width(), + height: context.height(), #[cfg(feature = "audio")] click_sound: gui_handler_create_info.click_sound.map(|mut click_sound| { @@ -332,8 +330,8 @@ impl<'a> GuiHandler<'a> { resource_base_path: gui_handler_create_info.resource_directory, - top_ui: RwLock::new(None), - tooltip_ui: RwLock::new(None), + top_ui: None, + tooltip_ui: None, render_targets, command_buffers, @@ -350,44 +348,44 @@ impl<'a> GuiHandler<'a> { text_color_layout: color_layout, - internal_icons: RwLock::new(HashMap::new()), - internal_textures: RwLock::new(HashMap::new()), - internal_colors: RwLock::new(HashMap::new()), + internal_icons: HashMap::new(), + internal_textures: HashMap::new(), + internal_colors: HashMap::new(), element_creator: Mutex::new(ElementCreator::new(device.clone(), queue.clone())?), icon_descriptor_layout, - needs_update: AtomicBool::new(true), - text_change_queue: RwLock::new(Vec::new()), + needs_update: true, + text_change_queue: Vec::new(), - on_selected: RwLock::new(None), + on_selected: None, - layers: Mutex::default(), + layers: Vec::new(), - ortho: RwLock::new(ortho( + ortho: ortho( 0.0, context.width() as f32, 0.0, context.height() as f32, -1.0, 1.0, - )), + ), - mouse_x: AtomicU32::new(0), - mouse_y: AtomicU32::new(0), + mouse_x: 0, + mouse_y: 0, - last_direction: Mutex::new(GuiDirection::None), + last_direction: GuiDirection::None, - current_clickable: RwLock::new(None), - current_hoverable: RwLock::new(None), - current_selectable: RwLock::new(None), - current_writeable: RwLock::new(None), + current_clickable: None, + current_hoverable: None, + current_selectable: None, + current_writeable: None, text_sample_count, - callback_list: Mutex::default(), - })) + callback_list: Vec::new(), + }) } pub fn device(&self) -> &Arc { @@ -399,11 +397,11 @@ impl<'a> GuiHandler<'a> { } pub fn width(&self) -> u32 { - self.width.load(SeqCst) + self.width } pub fn height(&self) -> u32 { - self.height.load(SeqCst) + self.height } pub(crate) fn icon_descriptor_layout(&self) -> &Arc { @@ -411,7 +409,7 @@ impl<'a> GuiHandler<'a> { } pub(crate) fn request_icon( - &self, + &mut self, icon_builder: impl Into, ) -> Result> { let icon_builder = icon_builder.into(); @@ -420,40 +418,14 @@ impl<'a> GuiHandler<'a> { IconBuilderType::Image(image) => { if let Some(path) = image.file_name() { self.internal_icons - .write() - .unwrap() .insert(path.clone(), Arc::downgrade(&image)); } Ok(image) } - IconBuilderType::Path(mut path) => { - let mut internal_icons = self.internal_icons.write().unwrap(); - - match internal_icons.get_mut(&path) { - Some(weak_image) => match weak_image.upgrade() { - Some(image) => Ok(image), - None => { - if !path.has_prefix() { - path.set_prefix( - &self - .resource_base_path - .as_ref() - .ok_or(anyhow!("resource base path not set!"))? - .full_path(), - ); - } - - let image = Image::from_file(path)? - .max_mip_map_levels() - .attach_pretty_sampler(self.device())? - .build(self.device(), self.queue())?; - - *weak_image = Arc::downgrade(&image); - - Ok(image) - } - }, + IconBuilderType::Path(mut path) => match self.internal_icons.get_mut(&path) { + Some(weak_image) => match weak_image.upgrade() { + Some(image) => Ok(image), None => { if !path.has_prefix() { path.set_prefix( @@ -465,17 +437,37 @@ impl<'a> GuiHandler<'a> { ); } - let image = Image::from_file(path.clone())? + let image = Image::from_file(path)? .max_mip_map_levels() .attach_pretty_sampler(self.device())? .build(self.device(), self.queue())?; - internal_icons.insert(path, Arc::downgrade(&image)); + *weak_image = Arc::downgrade(&image); Ok(image) } + }, + None => { + if !path.has_prefix() { + path.set_prefix( + &self + .resource_base_path + .as_ref() + .ok_or(anyhow!("resource base path not set!"))? + .full_path(), + ); + } + + let image = Image::from_file(path.clone())? + .max_mip_map_levels() + .attach_pretty_sampler(self.device())? + .build(self.device(), self.queue())?; + + self.internal_icons.insert(path, Arc::downgrade(&image)); + + Ok(image) } - } + }, } } @@ -488,7 +480,7 @@ impl<'a> GuiHandler<'a> { } pub(crate) fn displayable_image_from_descriptor( - &self, + &mut self, width: u32, height: u32, descriptor: ElementDescriptor, @@ -518,28 +510,23 @@ impl<'a> GuiHandler<'a> { ); } - if self.internal_textures.read().unwrap().contains_key(&path) { - Ok(self.internal_textures.read().unwrap()[&path].clone()) + if self.internal_textures.contains_key(&path) { + Ok(self.internal_textures[&path].clone()) } else { let texture = Image::from_file(path.clone())? .format(VK_FORMAT_R8G8B8A8_UNORM) .attach_sampler(Sampler::nearest_sampler().build(&self.device)?) .build(&self.device, &self.queue)?; - self.internal_textures - .write() - .unwrap() - .insert(path.clone(), texture.clone()); + self.internal_textures.insert(path.clone(), texture.clone()); Ok(texture.clone()) } } - pub(crate) fn color_descriptor(&self, color: Color) -> Result> { - if self.internal_colors.read().unwrap().contains_key(&color) { - Ok(self.internal_colors.read().unwrap()[&color] - ._descriptor_set - .clone()) + pub(crate) fn color_descriptor(&mut self, color: Color) -> Result> { + if self.internal_colors.contains_key(&color) { + Ok(self.internal_colors[&color]._descriptor_set.clone()) } else { let desc_pool = DescriptorPool::builder() .set_layout(self.text_color_layout.clone()) @@ -572,19 +559,14 @@ impl<'a> GuiHandler<'a> { _buffer: buffer, }; - self.internal_colors - .write() - .unwrap() - .insert(color, textable_color); + self.internal_colors.insert(color, textable_color); - Ok(self.internal_colors.read().unwrap()[&color] - ._descriptor_set - .clone()) + Ok(self.internal_colors[&color]._descriptor_set.clone()) } } pub(crate) fn ortho(&self) -> cgmath::Matrix4 { - *self.ortho.read().unwrap() + self.ortho } pub(crate) fn resource_base_path(&self) -> Option<&AssetPath> { @@ -601,29 +583,25 @@ impl<'a> GuiHandler<'a> { self.hover_sound.as_ref() } - pub fn set_on_selected_event(&self, f: F) -> Result<()> + pub fn set_on_selected_event(&self, f: F) where F: Fn() -> Result<()> + Send + Sync + 'static, { - *self.on_selected.write().unwrap() = Some(Box::new(f)); - - Ok(()) + self.on_selected = Some(Box::new(f)); } // --------------------------------------------------------------------- // ------------------------- event handling -------------------------- // --------------------------------------------------------------------- - pub fn set_mouse_pos(&self, x: u32, y: u32) -> Result<()> { - self.mouse_x.store(x, SeqCst); - self.mouse_y.store(y, SeqCst); + pub fn set_mouse_pos(&mut self, x: u32, y: u32) -> Result<()> { + self.mouse_x = x; + self.mouse_y = y; let mut hovered = None; { - let layers = self.layers.lock().unwrap(); - - for (_, elements) in layers.iter() { + for (_, elements) in self.layers.iter() { for hoverable in elements.iter_hoverables() { if hoverable.is_hovered(x as i32, y as i32) { hovered = Some(hoverable.clone()); @@ -633,32 +611,34 @@ impl<'a> GuiHandler<'a> { } } - let mut current_hoverable = self.current_hoverable.write().unwrap(); - match hovered { Some(hovered) => { - if let Some(current) = &*current_hoverable { + if let Some(current) = &self.current_hoverable { if Arc::ptr_eq(current, &hovered) { return Ok(()); } - current.set_hovered(false)?; + current.set_hovered(self, false)?; } - hovered.set_hovered(true)?; + hovered.set_hovered(self, true)?; - *current_hoverable = Some(hovered); + self.current_hoverable = Some(hovered); } None => { - if current_hoverable.is_some() { + if self.current_hoverable.is_some() { // unwrap is safe, just tested for `is_some` - if !current_hoverable + if !self + .current_hoverable .as_ref() .unwrap() .is_hovered(x as i32, y as i32) { - current_hoverable.as_ref().unwrap().set_hovered(false)?; - *current_hoverable = None; + self.current_hoverable + .as_ref() + .unwrap() + .set_hovered(self, false)?; + self.current_hoverable = None; } } } @@ -668,19 +648,14 @@ impl<'a> GuiHandler<'a> { } pub fn mouse_position(&self) -> (u32, u32) { - (self.mouse_x.load(SeqCst), self.mouse_y.load(SeqCst)) + (self.mouse_x, self.mouse_y) } - fn find_clickable(&self) -> Result>> { - let layers = self.layers.lock().unwrap(); - - for (_, elements) in layers.iter() { + fn find_clickable(&mut self) -> Result>> { + for (_, elements) in self.layers.iter() { for clickable in elements.iter_clickables() { - if clickable.is_pressed( - self.mouse_x.load(SeqCst) as i32, - self.mouse_y.load(SeqCst) as i32, - ) { - *self.current_clickable.write().unwrap() = Some(clickable.clone()); + if clickable.is_pressed(self.mouse_x as i32, self.mouse_y as i32) { + self.current_clickable = Some(clickable.clone()); return Ok(Some(clickable.clone())); } } @@ -689,10 +664,10 @@ impl<'a> GuiHandler<'a> { Ok(None) } - pub fn mouse_down(&self, mouse_button: MouseButton) -> Result { + pub fn mouse_down(&mut self, mouse_button: MouseButton) -> Result { if mouse_button == MouseButton::Left { if let Some(tmp_clickable) = self.find_clickable()? { - tmp_clickable.set_clicked(true)?; + tmp_clickable.set_clicked(self, true)?; return Ok(true); } } @@ -700,22 +675,26 @@ impl<'a> GuiHandler<'a> { Ok(false) } - pub fn mouse_up(&self, mouse_button: MouseButton) -> Result { + pub fn mouse_up(&mut self, mouse_button: MouseButton) -> Result { if mouse_button == MouseButton::Left { - let mut clickable = self.current_clickable.write().unwrap(); - if clickable.is_some() { - clickable.as_ref().unwrap().set_clicked(false)?; + if self.current_clickable.is_some() { + self.current_clickable + .as_ref() + .unwrap() + .set_clicked(self, false)?; - if clickable.as_ref().unwrap().is_pressed( - self.mouse_x.load(SeqCst) as i32, - self.mouse_y.load(SeqCst) as i32, - ) { - if let Some(hoverable) = self.current_hoverable.read().unwrap().as_ref() { - hoverable.set_hovered(true)?; + if self + .current_clickable + .as_ref() + .unwrap() + .is_pressed(self.mouse_x as i32, self.mouse_y as i32) + { + if let Some(hoverable) = self.current_hoverable.as_ref() { + hoverable.set_hovered(self, true)?; } } - *clickable = None; + self.current_clickable = None; return Ok(true); } @@ -724,16 +703,14 @@ impl<'a> GuiHandler<'a> { Ok(false) } - pub fn current_selectable(&self) -> Result>>> { - match self.current_selectable.read().unwrap().as_ref() { - Some(selectable) => Ok(Some(selectable.clone())), - None => Ok(None), - } + pub fn current_selectable(&self) -> Option>> { + self.current_selectable.clone() } - pub fn accept_selection(&self) -> Result { - if let Some(current_selectable) = self.current_selectable()? { - current_selectable.click_event()?; + pub fn accept_selection(&mut self) -> Result { + if let Some(current_selectable) = &self.current_selectable { + current_selectable.click_event(self)?; + return Ok(true); } @@ -741,7 +718,7 @@ impl<'a> GuiHandler<'a> { } pub fn accept_custom_selection(&self, button: ControllerButton) -> Result { - if let Some(current_selectable) = self.current_selectable()? { + if let Some(current_selectable) = &self.current_selectable { if current_selectable.custom_click_event(button)? { return Ok(true); } @@ -752,7 +729,7 @@ impl<'a> GuiHandler<'a> { pub fn decline_topgui(&self) -> Result { // workaround for unwanted borrowing behaviour inside decline function - let opt_topgui = { self.top_ui.read().unwrap().as_ref().cloned() }; + let opt_topgui = self.top_ui.as_ref().cloned(); if let Some(topgui) = opt_topgui { topgui.decline()?; @@ -764,7 +741,7 @@ impl<'a> GuiHandler<'a> { pub fn next_tab_topgui(&self, second_level: bool) -> Result { // workaround for unwanted borrowing behaviour inside decline function - let opt_topgui = { self.top_ui.read().unwrap().as_ref().cloned() }; + let opt_topgui = self.top_ui.as_ref().cloned(); if let Some(topgui) = opt_topgui { topgui.next_tab(second_level)?; @@ -776,7 +753,7 @@ impl<'a> GuiHandler<'a> { pub fn previous_tab_topgui(&self, second_level: bool) -> Result { // workaround for unwanted borrowing behaviour inside decline function - let opt_topgui = { self.top_ui.read().unwrap().as_ref().cloned() }; + let opt_topgui = self.top_ui.as_ref().cloned(); if let Some(topgui) = opt_topgui { topgui.previous_tab(second_level)?; @@ -786,12 +763,12 @@ impl<'a> GuiHandler<'a> { Ok(false) } - pub fn writeable(&self) -> Result>> { - Ok(self.current_writeable.read().unwrap().as_ref().cloned()) + pub fn writeable(&self) -> Option> { + self.current_writeable.clone() } pub fn remove_char(&self) -> Result { - match self.current_writeable.read().unwrap().as_ref() { + match &self.current_writeable { Some(current_writable) => { current_writable.remove_last()?; Ok(true) @@ -800,50 +777,48 @@ impl<'a> GuiHandler<'a> { } } - pub fn check_navigatable(&self) -> Result { - Ok(self.current_selectable.read().unwrap().is_some()) + pub fn check_navigatable(&self) -> bool { + self.current_selectable.is_some() } - pub fn update_selection(&self, direction: GuiDirection) -> Result { - let mut last_direction = self.last_direction.lock().unwrap(); - - if direction != *last_direction { - *last_direction = direction; + pub fn update_selection(&mut self, direction: GuiDirection) -> Result { + if direction != self.last_direction { + self.last_direction = direction; match self.current_selectable.write().unwrap().as_mut() { Some(current_selectable) => match direction { GuiDirection::Left => { if let Some(neighbour) = current_selectable.west_neighbour() { - current_selectable.set_selected(false)?; + current_selectable.set_selected(self, false)?; *current_selectable = neighbour; - current_selectable.set_selected(true)?; + current_selectable.set_selected(self, true)?; }; Ok(true) } GuiDirection::Right => { if let Some(neighbour) = current_selectable.east_neighbour() { - current_selectable.set_selected(false)?; + current_selectable.set_selected(self, false)?; *current_selectable = neighbour; - current_selectable.set_selected(true)?; + current_selectable.set_selected(self, true)?; }; Ok(true) } GuiDirection::Up => { if let Some(neighbour) = current_selectable.north_neighbour() { - current_selectable.set_selected(false)?; + current_selectable.set_selected(self, false)?; *current_selectable = neighbour; - current_selectable.set_selected(true)?; + current_selectable.set_selected(self, true)?; }; Ok(true) } GuiDirection::Down => { if let Some(neighbour) = current_selectable.south_neighbour() { - current_selectable.set_selected(false)?; + current_selectable.set_selected(self, false)?; *current_selectable = neighbour; - current_selectable.set_selected(true)?; + current_selectable.set_selected(self, true)?; }; Ok(true) @@ -857,25 +832,28 @@ impl<'a> GuiHandler<'a> { } } - pub(crate) fn enqueue_text_update(&self, function: Box Result<()> + Send + Sync>) { - self.text_change_queue.write().unwrap().push(function); - self.needs_update.store(true, SeqCst); + pub(crate) fn enqueue_text_update( + &mut self, + function: Box Result<()> + Send + Sync>, + ) { + self.text_change_queue.push(function); + self.needs_update = true; } - pub fn set_top_gui(&self, top_gui: Option>) { - *self.top_ui.write().unwrap() = top_gui; + pub fn set_top_gui(&mut self, top_gui: impl Into>>) { + self.top_ui = top_gui.into(); } - pub fn set_tooltip(&self, tooltip: Option>) { - *self.tooltip_ui.write().unwrap() = tooltip; + pub fn set_tooltip(&mut self, tooltip: impl Into>>) { + self.tooltip_ui = tooltip.into(); } - pub(crate) fn add_callback Result<()> + Send + Sync + 'static>(&self, f: F) { - self.callback_list.lock().unwrap().push(Box::new(f)); + pub(crate) fn add_callback Result<()> + Send + Sync + 'static>(&mut self, f: F) { + self.callback_list.push(Box::new(f)); } - pub fn process_callbacks(&self) -> Result<()> { - let callbacks = mem::take(&mut *self.callback_list.lock().unwrap()); + pub fn process_callbacks(&mut self) -> Result<()> { + let callbacks = mem::take(&mut self.callback_list); callbacks.into_iter().try_for_each(|callback| callback()) } @@ -895,8 +873,8 @@ impl<'a> GuiHandler<'a> { let viewport = [VkViewport { x: 0.0, y: 0.0, - width: self.width.load(SeqCst) as f32, - height: self.height.load(SeqCst) as f32, + width: self.width as f32, + height: self.height as f32, minDepth: 0.0, maxDepth: 1.0, }]; @@ -904,14 +882,12 @@ impl<'a> GuiHandler<'a> { let scissor = [VkRect2D { offset: VkOffset2D { x: 0, y: 0 }, extent: VkExtent2D { - width: self.width.load(SeqCst), - height: self.height.load(SeqCst), + width: self.width, + height: self.height, }, }]; - let layers = self.layers.lock().unwrap(); - - for (_, elements) in layers.iter() { + for (_, elements) in self.layers.iter() { render_target.begin(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE, index); if !elements.is_colorables_empty() { @@ -1032,10 +1008,8 @@ macro_rules! add_element { macro_rules! remove_element { ($layers: expr, $layer_id: ident, $element: ident) => { - let mut layers = $layers.lock().unwrap(); - paste! { - match layers.iter_mut().find(|(id, _)| *id == $layer_id) { + match $layers.iter_mut().find(|(id, _)| *id == $layer_id) { Some((_, layer)) => { layer.[]($element); } @@ -1046,13 +1020,11 @@ macro_rules! remove_element { } }; ($layers: expr, $layer_id: ident, $element: ident, $update: expr) => { - let mut layers = $layers.lock().unwrap(); - paste! { - match layers.iter_mut().find(|(id, _)| *id == $layer_id) { + match $layers.iter_mut().find(|(id, _)| *id == $layer_id) { Some((_, layer)) => { if layer.[]($element) { - $update.store(true, SeqCst); + $update = true; } } None => { @@ -1066,32 +1038,34 @@ macro_rules! remove_element { // object handling impl<'a> GuiHandler<'a> { // framable - pub(crate) fn add_framable(&self, layer: i32, framable: Arc) -> Result<()> { + pub(crate) fn add_framable(&mut self, layer: i32, framable: Arc) -> Result<()> { add_element!(self.layers, layer, framable); Ok(()) } - pub(crate) fn delete_framable(&self, layer: i32, framable: &Arc) -> Result<()> { + pub(crate) fn delete_framable(&mut self, layer: i32, framable: &Arc) -> Result<()> { remove_element!(self.layers, layer, framable); Ok(()) } // hoverable - pub(crate) fn add_hoverable(&self, layer: i32, hoverable: Arc) -> Result<()> { + pub(crate) fn add_hoverable(&mut self, layer: i32, hoverable: Arc) -> Result<()> { add_element!(self.layers, layer, hoverable); Ok(()) } - pub(crate) fn delete_hoverable(&self, layer: i32, hoverable: &Arc) -> Result<()> { - let mut current_hoverable = self.current_hoverable.write().unwrap(); - - if current_hoverable.is_some() { + pub(crate) fn delete_hoverable( + &mut self, + layer: i32, + hoverable: &Arc, + ) -> Result<()> { + if self.current_hoverable.is_some() { // unwrap is safe, just tested for `is_some` - if Arc::ptr_eq(hoverable, current_hoverable.as_ref().unwrap()) { - *current_hoverable = None; + if Arc::ptr_eq(hoverable, self.current_hoverable.as_ref().unwrap()) { + self.current_hoverable = None; } } @@ -1101,22 +1075,25 @@ impl<'a> GuiHandler<'a> { } // selectable - pub(crate) fn add_selectable(&self, layer: i32, selectable: Arc>) -> Result<()> { + pub(crate) fn add_selectable( + &mut self, + layer: i32, + selectable: Arc>, + ) -> Result<()> { add_element!(self.layers, layer, selectable); Ok(()) } pub(crate) fn delete_selectable( - &self, + &mut self, layer: i32, selectable: &Arc>, ) -> Result<()> { - let mut current_selectable = self.current_selectable.write().unwrap(); - if current_selectable.is_some() { + if self.current_selectable.is_some() { // unwrap is safe, just tested for `is_some` - if Arc::ptr_eq(selectable, current_selectable.as_ref().unwrap()) { - *current_selectable = None; + if Arc::ptr_eq(selectable, self.current_selectable.as_ref().unwrap()) { + self.current_selectable = None; } } @@ -1126,16 +1103,20 @@ impl<'a> GuiHandler<'a> { } // displayable - pub(crate) fn add_displayable(&self, layer: i32, displayable: Arc) -> Result<()> { + pub(crate) fn add_displayable( + &mut self, + layer: i32, + displayable: Arc, + ) -> Result<()> { add_element!(self.layers, layer, displayable); - self.needs_update.store(true, SeqCst); + self.needs_update = true; Ok(()) } pub(crate) fn delete_displayable( - &self, + &mut self, layer: i32, displayable: &Arc, ) -> Result<()> { @@ -1145,18 +1126,21 @@ impl<'a> GuiHandler<'a> { } // clickable - pub(crate) fn add_clickable(&self, layer: i32, clickable: Arc) -> Result<()> { + pub(crate) fn add_clickable(&mut self, layer: i32, clickable: Arc) -> Result<()> { add_element!(self.layers, layer, clickable); Ok(()) } - pub(crate) fn delete_clickable(&self, layer: i32, clickable: &Arc) -> Result<()> { - let mut current_clickable = self.current_clickable.write().unwrap(); - if current_clickable.is_some() { + pub(crate) fn delete_clickable( + &mut self, + layer: i32, + clickable: &Arc, + ) -> Result<()> { + if self.current_clickable.is_some() { // unwrap is safe, just tested for `is_some` - if ptr::eq(&clickable, ¤t_clickable.as_ref().unwrap()) { - *current_clickable = None; + if ptr::eq(clickable, self.current_clickable.as_ref().unwrap()) { + self.current_clickable = None; } } @@ -1166,31 +1150,29 @@ impl<'a> GuiHandler<'a> { } // textable - pub(crate) fn add_textable(&self, layer: i32, textable: Arc) -> Result<()> { + pub(crate) fn add_textable(&mut self, layer: i32, textable: Arc) -> Result<()> { add_element!(self.layers, layer, textable); - self.needs_update.store(true, SeqCst); + self.needs_update = true; Ok(()) } - pub(crate) fn delete_textable(&self, layer: i32, textable: &Arc) -> Result<()> { + pub(crate) fn delete_textable(&mut self, layer: i32, textable: &Arc) -> Result<()> { remove_element!(self.layers, layer, textable, self.needs_update); Ok(()) } // writable - pub(crate) fn add_writeable(&self, layer: i32, writeable: Arc) -> Result<()> { + pub(crate) fn add_writeable(&mut self, layer: i32, writeable: Arc) -> Result<()> { add_element!(self.layers, layer, writeable); Ok(()) } - pub(crate) fn set_active_writeable(&self, writeable: Arc) -> Result { - let mut current_writeable = self.current_writeable.write().unwrap(); - - if let Some(current) = current_writeable.as_ref() { + pub(crate) fn set_active_writeable(&mut self, writeable: Arc) -> Result { + if let Some(current) = self.current_writeable.as_ref() { // change nothing if both are the same if Arc::ptr_eq(current, &writeable) { return Ok(false); @@ -1199,19 +1181,21 @@ impl<'a> GuiHandler<'a> { current.inactivation_event()?; } - *current_writeable = Some(writeable); + self.current_writeable = Some(writeable); Ok(true) } - pub(crate) fn delete_writeable(&self, layer: i32, writeable: &Arc) -> Result<()> { + pub(crate) fn delete_writeable( + &mut self, + layer: i32, + writeable: &Arc, + ) -> Result<()> { { - let mut current_writeable = self.current_writeable.write().unwrap(); - - if let Some(w) = &*current_writeable { + if let Some(w) = &self.current_writeable { if Arc::ptr_eq(w, writeable) { w.inactivation_event()?; - *current_writeable = None; + self.current_writeable = None; } } } @@ -1222,49 +1206,55 @@ impl<'a> GuiHandler<'a> { } // iconizable - pub(crate) fn add_iconizable(&self, layer: i32, iconizable: Arc) -> Result<()> { + pub(crate) fn add_iconizable(&mut self, layer: i32, iconizable: Arc) -> Result<()> { add_element!(self.layers, layer, iconizable); - self.needs_update.store(true, SeqCst); + self.needs_update = true; Ok(()) } - pub(crate) fn delete_iconizable(&self, layer: i32, iconizable: &Arc) -> Result<()> { + pub(crate) fn delete_iconizable( + &mut self, + layer: i32, + iconizable: &Arc, + ) -> Result<()> { remove_element!(self.layers, layer, iconizable, self.needs_update); Ok(()) } - pub(crate) fn set_selectable(&self, selectable: Option>>) -> Result<()> { - let mut current_selectable = self.current_selectable.write().unwrap(); - - if let Some(selectable) = current_selectable.as_ref() { - selectable.set_selected(false)?; + pub(crate) fn set_selectable(&mut self, selectable: Option>>) -> Result<()> { + if let Some(selectable) = &self.current_selectable { + selectable.set_selected(self, false)?; } - if let Some(selectable) = selectable.as_ref() { - selectable.set_selected(true)?; + if let Some(selectable) = &selectable { + selectable.set_selected(self, true)?; - if let Some(on_selected) = self.on_selected.read().unwrap().as_ref() { + if let Some(on_selected) = &self.on_selected { on_selected()?; } } - *current_selectable = selectable; + self.current_selectable = selectable; Ok(()) } - pub(crate) fn add_colorable(&self, layer: i32, colorable: Arc) -> Result<()> { + pub(crate) fn add_colorable(&mut self, layer: i32, colorable: Arc) -> Result<()> { add_element!(self.layers, layer, colorable); - self.needs_update.store(true, SeqCst); + self.needs_update = true; Ok(()) } - pub(crate) fn delete_colorable(&self, layer: i32, colorable: &Arc) -> Result<()> { + pub(crate) fn delete_colorable( + &mut self, + layer: i32, + colorable: &Arc, + ) -> Result<()> { remove_element!(self.layers, layer, colorable, self.needs_update); Ok(()) @@ -1278,30 +1268,18 @@ impl<'a> GuiHandler<'a> { target_images: &TargetMode>>, queue: &Arc>, sample_count: VkSampleCountFlags, - ) -> Result>> { + ) -> Result> { Ok(match target_images { - TargetMode::Mono(images) => TargetMode::Mono(RwLock::new(Self::create_render_target( + TargetMode::Mono(images) => TargetMode::Mono(Self::create_render_target( device, images, None, queue, sample_count, - )?)), + )?), TargetMode::Stereo(left_images, right_images) => TargetMode::Stereo( - RwLock::new(Self::create_render_target( - device, - left_images, - None, - queue, - sample_count, - )?), - RwLock::new(Self::create_render_target( - device, - right_images, - None, - queue, - sample_count, - )?), + Self::create_render_target(device, left_images, None, queue, sample_count)?, + Self::create_render_target(device, right_images, None, queue, sample_count)?, ), }) } @@ -1363,7 +1341,7 @@ impl<'a> GuiHandler<'a> { for _ in 0..image_count { command_buffers.push(CommandBufferState { - text_buffers: RwLock::new(Vec::new()), + text_buffers: Vec::new(), }); } @@ -1398,7 +1376,7 @@ impl<'a> GuiHandler<'a> { fn init_text_objects( device: &Arc, - render_targets: &TargetMode>, + render_targets: &TargetMode, sample_count: VkSampleCountFlags, ) -> Result<(TargetMode, Arc)> { // --- layout creation --- @@ -1439,7 +1417,7 @@ impl<'a> GuiHandler<'a> { pipeline: GuiHandler::init_gui_pipeline::( device, - render_target.read().unwrap().render_pass(), + render_target.render_pass(), &pipeline_layout, vertex_shader.clone(), fragment_shader.clone(), @@ -1454,7 +1432,7 @@ impl<'a> GuiHandler<'a> { fn init_rectangle_objects( device: &Arc, - render_targets: &TargetMode>, + render_targets: &TargetMode, ) -> Result> { let descriptor_layout = DescriptorSetLayout::builder() .add_layout_binding( @@ -1481,7 +1459,7 @@ impl<'a> GuiHandler<'a> { pipeline: GuiHandler::init_gui_pipeline::( device, - render_target.read().unwrap().render_pass(), + render_target.render_pass(), &pipeline_layout, vertex_shader.clone(), fragment_shader.clone(), @@ -1494,7 +1472,7 @@ impl<'a> GuiHandler<'a> { fn init_text_screen_objects( device: &Arc, - render_targets: &TargetMode>, + render_targets: &TargetMode, ) -> Result> { let descriptor_layout = DescriptorSetLayout::builder() .add_layout_binding( @@ -1523,7 +1501,7 @@ impl<'a> GuiHandler<'a> { pipeline: GuiHandler::init_gui_pipeline::( device, - render_target.read().unwrap().render_pass(), + render_target.render_pass(), &pipeline_layout, vertex_shader.clone(), fragment_shader.clone(), @@ -1536,7 +1514,7 @@ impl<'a> GuiHandler<'a> { fn init_single_color_objects( device: &Arc, - render_targets: &TargetMode>, + render_targets: &TargetMode, ) -> Result> { let color_layout = DescriptorSetLayout::builder() .add_layout_binding( @@ -1567,7 +1545,7 @@ impl<'a> GuiHandler<'a> { pipeline: GuiHandler::init_gui_pipeline::( device, - render_target.read().unwrap().render_pass(), + render_target.render_pass(), &pipeline_layout, vertex_shader.clone(), fragment_shader.clone(), @@ -1604,18 +1582,16 @@ impl<'a> GuiHandler<'a> { buffer_recorder: &mut CommandBufferRecorder<'_>, indices: &TargetMode, ) -> Result<()> { - if self.needs_update.load(SeqCst) { - let mut text_changes = self.text_change_queue.write().unwrap(); - - if !text_changes.is_empty() { - for text_change in text_changes.iter() { + if self.needs_update { + if !self.text_change_queue.is_empty() { + for text_change in self.text_change_queue.iter() { (text_change)()?; } - text_changes.clear(); + self.text_change_queue.clear(); } - self.needs_update.store(false, SeqCst); + self.needs_update = false; } self.command_buffers @@ -1646,7 +1622,7 @@ impl<'a> GuiHandler<'a> { self.render( buffer_recorder, &command_buffers[****index], - &*render_target.read().unwrap(), + render_target, single_color_object, rectangle_objects, text_objects, @@ -1661,43 +1637,47 @@ impl<'a> GuiHandler<'a> { } pub fn resize( - &self, + &mut self, width: u32, height: u32, images: &TargetMode>>, ) -> Result<()> { images .chain(&self.render_targets) - .execute(|(images, render_target)| { - let mut rt_lock = render_target.write().unwrap(); - - *rt_lock = Self::create_render_target( + .execute(|(images, old_render_target)| { + let new_render_target = Self::create_render_target( &self.device, &images, - Some(&*rt_lock), + Some(old_render_target), &self.queue, self.text_sample_count, )?; + **old_render_target = new_render_target; + Ok(()) })?; self.text_to_screen.update_on_resize(&self.render_targets)?; - self.needs_update.store(true, SeqCst); - *self.ortho.write().unwrap() = ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0); + self.needs_update = true; + self.ortho = ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0); - self.width.store(width, SeqCst); - self.height.store(height, SeqCst); + self.width = width; + self.height = height; - let layers = self.layers.lock().unwrap(); - - for (_, elements) in layers.iter() { + for (_, elements) in self.layers.iter() { for framable in elements.iter_framables() { - framable.resize()?; + framable.resize(self)?; } } Ok(()) } } + +impl<'a> From<&'a ecs::World> for &'a GuiHandler<'_> { + fn from(world: &'a ecs::World) -> Self { + world.resources.get::>() + } +}