Compare commits

..

3 commits

Author SHA1 Message Date
c5286a3340 Update Rust crate quick-xml to 0.37.0
Some checks failed
Gavania Merge Build / build (pull_request) Failing after 2m21s
2025-03-04 09:05:37 +00:00
Michael Hübner
afc101effc Fix GuiHandler 2025-03-04 09:48:30 +01:00
Michael Hübner
0976860b9f Start removing interior mutability of GuiHandler 2025-03-04 09:11:05 +01:00
14 changed files with 659 additions and 616 deletions

View file

@ -8,11 +8,13 @@ edition = "2024"
quick-xml = "0.37.0" quick-xml = "0.37.0"
serde = { version = "1.0.203", features = ["derive"] } serde = { version = "1.0.203", features = ["derive"] }
serde_json = { version = "1.0.120" } 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" } vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
utilities = { git = "https://gavania.de/hodasemi/utilities.git" } utilities = { git = "https://gavania.de/hodasemi/utilities.git" }
paste = "1.0.15"
assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" } 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 # optional
audio = { git = "https://gavania.de/hodasemi/audio.git", optional = true } audio = { git = "https://gavania.de/hodasemi/audio.git", optional = true }

View file

@ -55,20 +55,6 @@ impl<T> TargetMode<T> {
} }
} }
pub fn chain<'a, R>(&'a self, other: &'a TargetMode<R>) -> TargetMode<(&'a T, &'a R)> {
match (self, other) {
(TargetMode::Mono(mono_self), TargetMode::Mono(mono_other)) => {
TargetMode::Mono((mono_self, mono_other))
}
(
TargetMode::Stereo(left_self, right_self),
TargetMode::Stereo(left_other, right_other),
) => TargetMode::Stereo((left_self, left_other), (right_self, right_other)),
_ => panic!("Incompatible TargetModes"),
}
}
pub fn execute<F, R>(&self, mut f: F) -> anyhow::Result<TargetMode<R>> pub fn execute<F, R>(&self, mut f: F) -> anyhow::Result<TargetMode<R>>
where where
F: FnMut(&T) -> anyhow::Result<R>, F: FnMut(&T) -> anyhow::Result<R>,
@ -90,6 +76,56 @@ impl<T> TargetMode<T> {
} }
} }
pub trait Chain<'a, R, T> {
fn chain(&'a self, other: &'a TargetMode<T>) -> TargetMode<(&'a R, &'a T)>;
fn chain_mut_1(&'a mut self, other: &'a TargetMode<T>) -> TargetMode<(&'a mut R, &'a T)>;
fn chain_mut_2(&'a self, other: &'a mut TargetMode<T>) -> TargetMode<(&'a R, &'a mut T)>;
}
impl<'a, R, T> Chain<'a, R, T> for TargetMode<R> {
fn chain(&'a self, other: &'a TargetMode<T>) -> TargetMode<(&'a R, &'a T)> {
match (self, other) {
(TargetMode::Mono(mono_self), TargetMode::Mono(mono_other)) => {
TargetMode::Mono((mono_self, mono_other))
}
(
TargetMode::Stereo(left_self, right_self),
TargetMode::Stereo(left_other, right_other),
) => TargetMode::Stereo((left_self, left_other), (right_self, right_other)),
_ => panic!("Incompatible TargetModes"),
}
}
fn chain_mut_1(&'a mut self, other: &'a TargetMode<T>) -> TargetMode<(&'a mut R, &'a T)> {
match (self, other) {
(TargetMode::Mono(mono_self), TargetMode::Mono(mono_other)) => {
TargetMode::Mono((mono_self, mono_other))
}
(
TargetMode::Stereo(left_self, right_self),
TargetMode::Stereo(left_other, right_other),
) => TargetMode::Stereo((left_self, left_other), (right_self, right_other)),
_ => panic!("Incompatible TargetModes"),
}
}
fn chain_mut_2(&'a self, other: &'a mut TargetMode<T>) -> TargetMode<(&'a R, &'a mut T)> {
match (self, other) {
(TargetMode::Mono(mono_self), TargetMode::Mono(mono_other)) => {
TargetMode::Mono((mono_self, mono_other))
}
(
TargetMode::Stereo(left_self, right_self),
TargetMode::Stereo(left_other, right_other),
) => TargetMode::Stereo((left_self, left_other), (right_self, right_other)),
_ => panic!("Incompatible TargetModes"),
}
}
}
pub trait Unfold { pub trait Unfold {
type Output; type Output;
@ -104,9 +140,33 @@ macro_rules! impl_unfold {
fn unfold(self) -> Self::Output { fn unfold(self) -> Self::Output {
match self { match self {
TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ &$rhs_var)), TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ $rhs_var)),
TargetMode::Stereo( ( ( $( [<l_ $var>], )+ ) , [<l_ $rhs_var>] ), ( ( $( [<r_ $var>], )+ ) , [<r_ $rhs_var>] ) ) TargetMode::Stereo( ( ( $( [<l_ $var>], )+ ) , [<l_ $rhs_var>] ), ( ( $( [<r_ $var>], )+ ) , [<r_ $rhs_var>] ) )
=> TargetMode::Stereo( ( $( [<l_ $var>], )+ &[<l_ $rhs_var>] ), ( $( [<r_ $var>], )+ &[<r_ $rhs_var>] ) ), => TargetMode::Stereo( ( $( [<l_ $var>], )+ [<l_ $rhs_var>] ), ( $( [<r_ $var>], )+ [<r_ $rhs_var>] ) ),
}
}
}
impl<'a, $($type,)+ $rhs_type: 'a> Unfold for TargetMode<(&'a mut ($($type,)+), &'a $rhs_type)> {
type Output = TargetMode<($(&'a mut $type,)+ &'a $rhs_type)>;
fn unfold(self) -> Self::Output {
match self {
TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ $rhs_var)),
TargetMode::Stereo( ( ( $( [<l_ $var>], )+ ) , [<l_ $rhs_var>] ), ( ( $( [<r_ $var>], )+ ) , [<r_ $rhs_var>] ) )
=> TargetMode::Stereo( ( $( [<l_ $var>], )+ [<l_ $rhs_var>] ), ( $( [<r_ $var>], )+ [<r_ $rhs_var>] ) ),
}
}
}
impl<'a, $($type,)+ $rhs_type: 'a> Unfold for TargetMode<(&'a ($($type,)+), &'a mut $rhs_type)> {
type Output = TargetMode<($(&'a $type,)+ &'a mut $rhs_type)>;
fn unfold(self) -> Self::Output {
match self {
TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ $rhs_var)),
TargetMode::Stereo( ( ( $( [<l_ $var>], )+ ) , [<l_ $rhs_var>] ), ( ( $( [<r_ $var>], )+ ) , [<r_ $rhs_var>] ) )
=> TargetMode::Stereo( ( $( [<l_ $var>], )+ [<l_ $rhs_var>] ), ( $( [<r_ $var>], )+ [<r_ $rhs_var>] ) ),
} }
} }
} }

View file

@ -4,13 +4,14 @@ use anyhow::Result;
use super::executable::Executable; use super::executable::Executable;
use super::framable::Framable; use super::framable::Framable;
use crate::prelude::*;
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
use super::audible::Audible; use super::audible::Audible;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
Arc, RwLock, Arc, RwLock,
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
}; };
/// `Clickable` gives the ability to execute a closure when clicked /// `Clickable` gives the ability to execute a closure when clicked
@ -54,12 +55,8 @@ impl Clickable {
/// # Arguments /// # Arguments
/// ///
/// * `clickable` is a `&Arc<Clickable>` instance that is going to be added /// * `clickable` is a `&Arc<Clickable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_clickable(self.ui_layer.load(SeqCst), self.clone())
.gui_handler()
.add_clickable(self.ui_layer.load(SeqCst), self.clone())?;
Ok(())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory /// Delete method, has to be explicitly called, otherwise it will remain in memory
@ -67,11 +64,9 @@ impl Clickable {
/// # Arguments /// # Arguments
/// ///
/// * `clickable` is a `&Arc<Clickable>` instance that is going to be deleted /// * `clickable` is a `&Arc<Clickable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_clickable(self.ui_layer.load(SeqCst), self)?;
.gui_handler() self.set_clicked(gui_handler, false)?;
.delete_clickable(self.ui_layer.load(SeqCst), self)?;
self.set_clicked(false)?;
Ok(()) Ok(())
} }
@ -104,7 +99,7 @@ impl Clickable {
*self.audible.write().unwrap() = audible; *self.audible.write().unwrap() = audible;
} }
pub fn set_clicked(&self, clicked: bool) -> Result<bool> { pub fn set_clicked(&self, gui_handler: &mut GuiHandler<'_>, clicked: bool) -> Result<bool> {
if self.clicked() != clicked { if self.clicked() != clicked {
self.clicked.store(clicked, SeqCst); self.clicked.store(clicked, SeqCst);
@ -122,7 +117,7 @@ impl Clickable {
} }
} }
self.executable.execute(())?; self.executable.execute(gui_handler, ())?;
} }
Ok(true) Ok(true)

View file

@ -2,6 +2,7 @@
use crate::prelude::*; use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use utilities::{impl_reprc, prelude::*}; use utilities::{impl_reprc, prelude::*};
use vulkan_rs::prelude::*; use vulkan_rs::prelude::*;
@ -33,17 +34,18 @@ pub struct Colorable {
impl Colorable { impl Colorable {
/// Factory method for `Colorable`, returns `Arc<Colorable>`. /// Factory method for `Colorable`, returns `Arc<Colorable>`.
pub fn new( pub fn new(
gui_handler: &mut GuiHandler<'_>,
framable: Arc<Framable>, framable: Arc<Framable>,
color: Color, color: Color,
fill_type: DisplayableFillType, fill_type: DisplayableFillType,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
let set = framable.gui_handler().color_descriptor(color)?; let set = gui_handler.color_descriptor(color)?;
let buffer = Buffer::builder() let buffer = Buffer::builder()
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
.set_memory_usage(MemoryUsage::CpuOnly) .set_memory_usage(MemoryUsage::CpuOnly)
.set_size(6) .set_size(6)
.build(framable.gui_handler().device().clone())?; .build(gui_handler.device().clone())?;
let colorable = Arc::new(Colorable { let colorable = Arc::new(Colorable {
framable, framable,
@ -67,7 +69,7 @@ impl Colorable {
colorable.framable.add_callback( colorable.framable.add_callback(
weak_colorable, weak_colorable,
Box::new(move || colorable_clone.update_frame()), Box::new(move |gui_handler| colorable_clone.update_frame(gui_handler)),
); );
Ok(colorable) Ok(colorable)
@ -78,10 +80,8 @@ impl Colorable {
/// # Arguments /// # Arguments
/// ///
/// * `colorable` is a `&Arc<Colorable>` instance that is going to be added /// * `colorable` is a `&Arc<Colorable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_colorable(self.ui_layer.load(SeqCst), self.clone())
.gui_handler()
.add_colorable(self.ui_layer.load(SeqCst), self.clone())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory. /// Delete method, has to be explicitly called, otherwise it will remain in memory.
@ -89,10 +89,8 @@ impl Colorable {
/// # Arguments /// # Arguments
/// ///
/// * `colorable` is a `&Arc<Colorable>` instance that is going to be deleted /// * `colorable` is a `&Arc<Colorable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_colorable(self.ui_layer.load(SeqCst), self)
.gui_handler()
.delete_colorable(self.ui_layer.load(SeqCst), self)
} }
pub fn clear_callback(self: &Arc<Self>) { pub fn clear_callback(self: &Arc<Self>) {
@ -109,8 +107,8 @@ impl Colorable {
/// # Arguments /// # Arguments
/// ///
/// * `color` defines the color /// * `color` defines the color
pub fn set_color(&self, color: Color) -> Result<()> { pub fn set_color(&self, color: Color, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
let set = self.framable.gui_handler().color_descriptor(color)?; let set = gui_handler.color_descriptor(color)?;
*self.color.write().unwrap() = color; *self.color.write().unwrap() = color;
*self.descriptor_set.write().unwrap() = set; *self.descriptor_set.write().unwrap() = set;
@ -149,7 +147,7 @@ impl Colorable {
} }
/// Update frame method if the original frame is invalidated /// 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 frame = self.buffer.map_complete()?;
let mut x_start = self.framable.left() as f32; 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 top = y_start + height * *self.top_factor.read().unwrap();
let bottom = y_start + height * *self.bottom_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[0].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy();
frame[1].position = (self.framable.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); frame[1].position = (gui_handler.ortho() * vec4(right, bottom, 0.0, 1.0)).xy();
frame[2].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); frame[2].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy();
frame[3].position = (self.framable.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 = (self.framable.ortho() * vec4(left, top, 0.0, 1.0)).xy(); frame[4].position = (gui_handler.ortho() * vec4(left, top, 0.0, 1.0)).xy();
frame[5].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); frame[5].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy();
Ok(()) Ok(())
} }

View file

@ -71,18 +71,17 @@ impl Displayable {
/// * `framable` is a `Arc<Framable>` instance /// * `framable` is a `Arc<Framable>` instance
/// * `name` is the name for a png /// * `name` is the name for a png
pub fn new( pub fn new(
gui_handler: &mut GuiHandler<'_>,
framable: Arc<Framable>, framable: Arc<Framable>,
displayable_type: impl Into<DisplayableType>, displayable_type: impl Into<DisplayableType>,
fill_type: DisplayableFillType, fill_type: DisplayableFillType,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
let descriptor_set = framable.gui_handler().image_descriptor_set()?; let descriptor_set = gui_handler.image_descriptor_set()?;
let displayable_type = displayable_type.into(); let displayable_type = displayable_type.into();
if let DisplayableType::Path(path) = &displayable_type { if let DisplayableType::Path(path) = &displayable_type {
let texture = framable let texture = gui_handler.displayable_image_from_path(path.clone())?;
.gui_handler()
.displayable_image_from_path(path.clone())?;
descriptor_set.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?; descriptor_set.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
} }
@ -90,7 +89,7 @@ impl Displayable {
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
.set_memory_usage(MemoryUsage::CpuOnly) .set_memory_usage(MemoryUsage::CpuOnly)
.set_size(6) .set_size(6)
.build(framable.gui_handler().device().clone())?; .build(gui_handler.device().clone())?;
let displayable = Arc::new(Displayable { let displayable = Arc::new(Displayable {
framable, framable,
@ -118,7 +117,7 @@ impl Displayable {
displayable.framable.add_callback( displayable.framable.add_callback(
weak_displayable, weak_displayable,
Box::new(move || displayable_clone.update_frame()), Box::new(move |gui_handler| displayable_clone.update_frame(gui_handler)),
); );
Ok(displayable) Ok(displayable)
@ -129,10 +128,8 @@ impl Displayable {
/// # Arguments /// # Arguments
/// ///
/// * `displayable` is a `&Arc<Displayable>` instance that is going to be added /// * `displayable` is a `&Arc<Displayable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_displayable(self.ui_layer.load(SeqCst), self.clone())
.gui_handler()
.add_displayable(self.ui_layer.load(SeqCst), self.clone())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory /// Delete method, has to be explicitly called, otherwise it will remain in memory
@ -140,10 +137,8 @@ impl Displayable {
/// # Arguments /// # Arguments
/// ///
/// * `displayable` is a `&Arc<Displayable>` instance that is going to be deleted /// * `displayable` is a `&Arc<Displayable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_displayable(self.ui_layer.load(SeqCst), self)
.gui_handler()
.delete_displayable(self.ui_layer.load(SeqCst), self)
} }
pub fn inner_type(&self) -> DisplayableType { pub fn inner_type(&self) -> DisplayableType {
@ -164,25 +159,21 @@ impl Displayable {
/// # Arguments /// # Arguments
/// ///
/// * `name` is the name of the texture in `gui/` without `.png` suffix /// * `name` is the name of the texture in `gui/` without `.png` suffix
pub fn set_image(&self, displayable_type: impl Into<DisplayableType>) -> Result<()> { pub fn set_image(
&self,
gui_handler: &mut GuiHandler<'_>,
displayable_type: impl Into<DisplayableType>,
) -> Result<()> {
let displayable_type = displayable_type.into(); let displayable_type = displayable_type.into();
let texture = match displayable_type.clone() { let texture = match displayable_type.clone() {
DisplayableType::Path(path) => Some( DisplayableType::Path(path) => Some(gui_handler.displayable_image_from_path(path)?),
self.framable
.gui_handler()
.displayable_image_from_path(path)?,
),
DisplayableType::Descriptor(descriptor) => { DisplayableType::Descriptor(descriptor) => {
let width = (self.framable.right() - self.framable.left()) as u32; let width = (self.framable.right() - self.framable.left()) as u32;
let height = (self.framable.bottom() - self.framable.top()) as u32; let height = (self.framable.bottom() - self.framable.top()) as u32;
if width > 0 && height > 0 { if width > 0 && height > 0 {
Some( Some(gui_handler.displayable_image_from_descriptor(width, height, descriptor)?)
self.framable
.gui_handler()
.displayable_image_from_descriptor(width, height, descriptor)?,
)
} else { } else {
None None
} }
@ -242,7 +233,7 @@ impl Displayable {
} }
/// Update frame method if the original frame is invalidated /// 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 frame = self.buffer.map_complete()?;
let mut x_start = self.framable.left() as f32; 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 let DisplayableType::Descriptor(descriptor) = &*self.displayable_type.read().unwrap() {
if width > 0.0 && height > 0.0 { if width > 0.0 && height > 0.0 {
let texture = self let texture = gui_handler.displayable_image_from_descriptor(
.framable width as u32,
.gui_handler() height as u32,
.displayable_image_from_descriptor( descriptor.clone(),
width as u32, )?;
height as u32,
descriptor.clone(),
)?;
self.descriptor_set self.descriptor_set
.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?; .update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
@ -286,12 +274,12 @@ impl Displayable {
let top = y_start + height * *self.top_factor.read().unwrap(); let top = y_start + height * *self.top_factor.read().unwrap();
let bottom = y_start + height * *self.bottom_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[0].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy();
frame[1].position = (self.framable.ortho() * vec4(right, bottom, 0.0, 1.0)).xy(); frame[1].position = (gui_handler.ortho() * vec4(right, bottom, 0.0, 1.0)).xy();
frame[2].position = (self.framable.ortho() * vec4(right, top, 0.0, 1.0)).xy(); frame[2].position = (gui_handler.ortho() * vec4(right, top, 0.0, 1.0)).xy();
frame[3].position = (self.framable.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 = (self.framable.ortho() * vec4(left, top, 0.0, 1.0)).xy(); frame[4].position = (gui_handler.ortho() * vec4(left, top, 0.0, 1.0)).xy();
frame[5].position = (self.framable.ortho() * vec4(left, bottom, 0.0, 1.0)).xy(); frame[5].position = (gui_handler.ortho() * vec4(left, bottom, 0.0, 1.0)).xy();
frame[0].texture_coordinates = vec2( frame[0].texture_coordinates = vec2(
*self.left_uv_factor.read().unwrap(), *self.left_uv_factor.read().unwrap(),

View file

@ -8,15 +8,13 @@ use crate::prelude::*;
/// `Executable` holds a closure which can be executed /// `Executable` holds a closure which can be executed
pub struct Executable<I: Send + Sync + 'static> { pub struct Executable<I: Send + Sync + 'static> {
gui_handler: Arc<GuiHandler>,
callback: RwLock<Option<Arc<dyn Fn(I) -> Result<()> + Send + Sync>>>, callback: RwLock<Option<Arc<dyn Fn(I) -> Result<()> + Send + Sync>>>,
} }
impl<I: Send + Sync + 'static> Executable<I> { impl<I: Send + Sync + 'static> Executable<I> {
/// Factory method for `Executable`, returns `Arc<Executable>` /// Factory method for `Executable`, returns `Arc<Executable>`
pub fn new(gui_handler: &Arc<GuiHandler>) -> Arc<Self> { pub fn new() -> Arc<Self> {
Arc::new(Executable { Arc::new(Executable {
gui_handler: gui_handler.clone(),
callback: RwLock::new(None), callback: RwLock::new(None),
}) })
} }
@ -39,11 +37,11 @@ impl<I: Send + Sync + 'static> Executable<I> {
} }
/// Execute the callback closure if possible /// 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() { if let Some(callback) = self.callback.read().unwrap().as_ref() {
let callback = callback.clone(); let callback = callback.clone();
self.gui_handler.add_callback(move || (callback)(input)); gui_handler.add_callback(move || (callback)(input));
} }
Ok(()) Ok(())

View file

@ -6,13 +6,11 @@ use anyhow::Result;
use std::{ use std::{
ffi::c_void, ffi::c_void,
sync::{ sync::{
atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering::SeqCst},
Arc, RwLock, Weak, Arc, RwLock, Weak,
atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering::SeqCst},
}, },
}; };
use vulkan_rs::prelude::cgmath::Matrix4;
/// Describes the vertical alignment for a `Framable` /// Describes the vertical alignment for a `Framable`
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum VerticalAlign { pub enum VerticalAlign {
@ -77,8 +75,6 @@ impl Drop for Handle {
/// `Framable` keeps track of the position and size of an item /// `Framable` keeps track of the position and size of an item
/// and calls functions on resize to keep everything aligned correctly /// and calls functions on resize to keep everything aligned correctly
pub struct Framable { pub struct Framable {
gui_handler: Arc<GuiHandler>,
left: AtomicI32, left: AtomicI32,
right: AtomicI32, right: AtomicI32,
top: AtomicI32, top: AtomicI32,
@ -87,7 +83,12 @@ pub struct Framable {
vertical_alignment: RwLock<VerticalAlign>, vertical_alignment: RwLock<VerticalAlign>,
horizontal_alignment: RwLock<HorizontalAlign>, horizontal_alignment: RwLock<HorizontalAlign>,
resize_callbacks: RwLock<Vec<(Handle, Box<dyn Fn() -> Result<()> + Send + Sync>)>>, resize_callbacks: RwLock<
Vec<(
Handle,
Box<dyn Fn(&mut GuiHandler<'_>) -> Result<()> + Send + Sync>,
)>,
>,
x_off: AtomicI32, x_off: AtomicI32,
y_off: AtomicI32, y_off: AtomicI32,
@ -111,12 +112,10 @@ pub struct Framable {
impl Framable { impl Framable {
/// Factory method for `Framable`, returns `Arc<Framable>` /// Factory method for `Framable`, returns `Arc<Framable>`
pub fn new(gui_handler: Arc<GuiHandler>, resize_allowed: bool) -> Result<Arc<Self>> { pub fn new(window_width: u32, window_height: u32, resize_allowed: bool) -> Result<Arc<Self>> {
Ok(Arc::new(Framable { Ok(Arc::new(Framable {
window_width: AtomicU32::new(gui_handler.width()), window_width: AtomicU32::new(window_width),
window_height: AtomicU32::new(gui_handler.height()), window_height: AtomicU32::new(window_height),
gui_handler,
left: AtomicI32::new(0), left: AtomicI32::new(0),
right: AtomicI32::new(0), right: AtomicI32::new(0),
@ -150,22 +149,21 @@ impl Framable {
/// # Arguments /// # Arguments
/// ///
/// * `framable` - is a `&Arc<Framable>` instance that is going to be added /// * `framable` - is a `&Arc<Framable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
// check if window size is the same as last time // check if window size is the same as last time
if self.gui_handler.width() != self.window_width.load(SeqCst) if gui_handler.width() != self.window_width.load(SeqCst)
|| self.gui_handler.height() != self.window_height.load(SeqCst) || gui_handler.height() != self.window_height.load(SeqCst)
{ {
// update window size // update window size
self.window_width.store(self.gui_handler.width(), SeqCst); self.window_width.store(gui_handler.width(), SeqCst);
self.window_height.store(self.gui_handler.height(), SeqCst); self.window_height.store(gui_handler.height(), SeqCst);
// force resize // force resize
self.resize()?; self.resize(gui_handler)?;
} }
if self.resize_allowed() { if self.resize_allowed() {
self.gui_handler gui_handler.add_framable(self.ui_layer.load(SeqCst), self.clone())?;
.add_framable(self.ui_layer.load(SeqCst), self.clone())?;
} }
Ok(()) Ok(())
@ -176,10 +174,9 @@ impl Framable {
/// # Arguments /// # Arguments
/// ///
/// * `framable` - is a `&Arc<Framable>` instance that is going to be deleted /// * `framable` - is a `&Arc<Framable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
if self.resize_allowed() { if self.resize_allowed() {
self.gui_handler gui_handler.delete_framable(self.ui_layer.load(SeqCst), self)?;
.delete_framable(self.ui_layer.load(SeqCst), self)?;
} }
Ok(()) Ok(())
@ -193,36 +190,49 @@ impl Framable {
self.ui_layer.load(SeqCst) 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_size.write().unwrap() = Some((width, height));
self.reference_scale_position.store(true, SeqCst); self.reference_scale_position.store(true, SeqCst);
self.reference_scale_size.store(true, SeqCst); self.reference_scale_size.store(true, SeqCst);
if self.is_framed() { if self.is_framed() {
self.resize()?; self.resize(gui_handler)?;
} }
Ok(()) 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) { if allowed != self.reference_scale_position.load(SeqCst) {
self.reference_scale_position.store(allowed, SeqCst); self.reference_scale_position.store(allowed, SeqCst);
if self.is_framed() { if self.is_framed() {
self.resize()?; self.resize(gui_handler)?;
} }
} }
Ok(()) 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) { if allowed != self.reference_scale_size.load(SeqCst) {
self.reference_scale_size.store(allowed, SeqCst); self.reference_scale_size.store(allowed, SeqCst);
if self.is_framed() { if self.is_framed() {
self.resize()?; self.resize(gui_handler)?;
} }
} }
@ -237,6 +247,7 @@ impl Framable {
/// width and a certain alignment /// width and a certain alignment
pub fn set_frame( pub fn set_frame(
&self, &self,
gui_handler: &GuiHandler<'_>,
x_off: i32, x_off: i32,
y_off: i32, y_off: i32,
w: u32, w: u32,
@ -252,7 +263,7 @@ impl Framable {
*self.vertical_alignment.write().unwrap() = vertical_align; *self.vertical_alignment.write().unwrap() = vertical_align;
*self.horizontal_alignment.write().unwrap() = horizontal_align; *self.horizontal_alignment.write().unwrap() = horizontal_align;
self.calculate_frame(); self.calculate_frame(gui_handler);
self.framed.store(true, SeqCst); self.framed.store(true, SeqCst);
} }
@ -296,16 +307,11 @@ impl Framable {
self.framed.load(SeqCst) self.framed.load(SeqCst)
} }
/// Returns the ortho 4x4 matrix, which describes the window
pub fn ortho(&self) -> Matrix4<f32> {
self.gui_handler.ortho()
}
/// Adds a callback closure which is executed on resize /// Adds a callback closure which is executed on resize
pub fn add_callback( pub fn add_callback(
&self, &self,
handle: impl Into<Handle>, handle: impl Into<Handle>,
callback: Box<dyn Fn() -> Result<()> + Send + Sync>, callback: Box<dyn Fn(&mut GuiHandler<'_>) -> Result<()> + Send + Sync>,
) { ) {
let handle = handle.into(); let handle = handle.into();
@ -348,9 +354,9 @@ impl Framable {
*self.horizontal_alignment.read().unwrap() *self.horizontal_alignment.read().unwrap()
} }
fn calculate_frame(&self) { fn calculate_frame(&self, gui_handler: &GuiHandler<'_>) {
let width = self.gui_handler.width(); let width = gui_handler.width();
let height = self.gui_handler.height(); let height = gui_handler.height();
let y_align = match *self.vertical_alignment.read().unwrap() { let y_align = match *self.vertical_alignment.read().unwrap() {
VerticalAlign::Top => 0, VerticalAlign::Top => 0,
@ -420,17 +426,27 @@ impl Framable {
self.bottom.store(bottom, SeqCst); 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!"); assert!(self.is_framed(), "framable needs to be framed first!");
self.x_off.store(x_offset, SeqCst); self.x_off.store(x_offset, SeqCst);
self.y_off.store(y_offset, SeqCst); self.y_off.store(y_offset, SeqCst);
self.resize()?; self.resize(gui_handler)?;
Ok(()) 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!"); assert!(self.is_framed(), "framable needs to be framed first!");
let left = self.left.load(SeqCst); let left = self.left.load(SeqCst);
@ -447,23 +463,19 @@ impl Framable {
self.bottom.store(y + height, SeqCst); self.bottom.store(y + height, SeqCst);
for (_, callback) in self.resize_callbacks.read().unwrap().iter() { for (_, callback) in self.resize_callbacks.read().unwrap().iter() {
callback()?; callback(gui_handler)?;
} }
Ok(()) Ok(())
} }
pub fn resize(&self) -> Result<()> { pub fn resize(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.calculate_frame(); self.calculate_frame(gui_handler);
for (_, callback) in self.resize_callbacks.read().unwrap().iter() { for (_, callback) in self.resize_callbacks.read().unwrap().iter() {
callback()?; callback(gui_handler)?;
} }
Ok(()) Ok(())
} }
pub(crate) fn gui_handler(&self) -> &Arc<GuiHandler> {
&self.gui_handler
}
} }

View file

@ -5,8 +5,8 @@ use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
Arc, Arc,
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
}; };
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
@ -56,10 +56,8 @@ impl Hoverable {
/// # Arguments /// # Arguments
/// ///
/// * `hoverable` is a `&Arc<Hoverable>` instance that is going to be added /// * `hoverable` is a `&Arc<Hoverable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_hoverable(self.ui_layer.load(SeqCst), self.clone())?;
.gui_handler()
.add_hoverable(self.ui_layer.load(SeqCst), self.clone())?;
Ok(()) Ok(())
} }
@ -69,11 +67,9 @@ impl Hoverable {
/// # Arguments /// # Arguments
/// ///
/// * `hoverable` is a `&Arc<Hoverable>` instance that is going to be deleted /// * `hoverable` is a `&Arc<Hoverable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_hoverable(self.ui_layer.load(SeqCst), self)?;
.gui_handler() self.set_hovered(gui_handler, false)?;
.delete_hoverable(self.ui_layer.load(SeqCst), self)?;
self.set_hovered(false)?;
Ok(()) Ok(())
} }
@ -107,12 +103,13 @@ impl Hoverable {
/// # Arguments /// # Arguments
/// ///
/// * `hovered` is the new hovered state /// * `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 { if self.hovered() != hovered {
self.hovered.store(hovered, SeqCst); self.hovered.store(hovered, SeqCst);
self.hover_changed_executable.execute(hovered)?; self.hover_changed_executable
self.on_hover_executable.execute(hovered)?; .execute(gui_handler, hovered)?;
self.on_hover_executable.execute(gui_handler, hovered)?;
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
{ {

View file

@ -9,8 +9,8 @@ use vulkan_rs::prelude::*;
use super::texturedvertex::TexturedVertex; use super::texturedvertex::TexturedVertex;
use std::sync::{ use std::sync::{
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
Arc, RwLock, Arc, RwLock,
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -85,16 +85,17 @@ impl Iconizable {
/// * `framable` is a `Arc<Framable>` instance /// * `framable` is a `Arc<Framable>` instance
/// * `icon` is a reference to an `Arc<Image>` /// * `icon` is a reference to an `Arc<Image>`
pub fn new( pub fn new(
gui_handler: &mut GuiHandler<'_>,
framable: Arc<Framable>, framable: Arc<Framable>,
icon_builder: impl Into<IconBuilderType>, icon_builder: impl Into<IconBuilderType>,
positioning: impl Into<Option<IconizablePositioning>>, positioning: impl Into<Option<IconizablePositioning>>,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
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() 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())?; .build(device.clone())?;
let descriptor_set = DescriptorPool::prepare_set(&desc_pool).allocate()?; let descriptor_set = DescriptorPool::prepare_set(&desc_pool).allocate()?;
@ -125,7 +126,7 @@ impl Iconizable {
iconizable.framable.add_callback( iconizable.framable.add_callback(
weak_iconizable, weak_iconizable,
Box::new(move || iconizable_clone.update_frame()), Box::new(move |gui_handler| iconizable_clone.update_frame(gui_handler)),
); );
Ok(iconizable) Ok(iconizable)
@ -136,10 +137,8 @@ impl Iconizable {
/// # Arguments /// # Arguments
/// ///
/// * `iconizable` is a `&Arc<Iconizable>` instance that is going to be added /// * `iconizable` is a `&Arc<Iconizable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_iconizable(self.ui_layer.load(SeqCst), self.clone())
.gui_handler()
.add_iconizable(self.ui_layer.load(SeqCst), self.clone())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory /// Delete method, has to be explicitly called, otherwise it will remain in memory
@ -147,10 +146,8 @@ impl Iconizable {
/// # Arguments /// # Arguments
/// ///
/// * `iconizable` is a `&Arc<Iconizable>` instance that is going to be deleted /// * `iconizable` is a `&Arc<Iconizable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_iconizable(self.ui_layer.load(SeqCst), self)
.gui_handler()
.delete_iconizable(self.ui_layer.load(SeqCst), self)
} }
pub fn set_ui_layer(&self, ui_layer: i32) { pub fn set_ui_layer(&self, ui_layer: i32) {
@ -175,7 +172,7 @@ impl Iconizable {
} }
/// Updates the frame /// 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"); assert!(self.framable.is_framed(), "framable is not framed yet");
// frame parameter // frame parameter
@ -239,7 +236,7 @@ impl Iconizable {
let right = left + resulting_width; let right = left + resulting_width;
let bottom = top + resulting_height; let bottom = top + resulting_height;
let ortho = self.framable.ortho(); let ortho = gui_handler.ortho();
let mut frame = self.buffer.map_complete()?; let mut frame = self.buffer.map_complete()?;
@ -270,8 +267,12 @@ impl Iconizable {
/// # Arguments /// # Arguments
/// ///
/// * `icon` the new icon /// * `icon` the new icon
pub fn set_icon(&self, icon_builder: impl Into<IconBuilderType>) -> Result<()> { pub fn set_icon(
let icon = self.framable.gui_handler().request_icon(icon_builder)?; &self,
gui_handler: &mut GuiHandler<'_>,
icon_builder: impl Into<IconBuilderType>,
) -> Result<()> {
let icon = gui_handler.request_icon(icon_builder)?;
self.descriptor_set self.descriptor_set
.update(&[DescriptorWrite::combined_samplers(0, &[&icon])])?; .update(&[DescriptorWrite::combined_samplers(0, &[&icon])])?;

View file

@ -5,22 +5,20 @@ use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
Arc, RwLock, Weak, Arc, RwLock, Weak,
atomic::{AtomicBool, AtomicI32, Ordering::SeqCst},
}; };
/// `Selectable` gives the ability to navigate per button or controller to /// `Selectable` gives the ability to navigate per button or controller to
/// optionally adjacent neighbour Selectables and to execute a closure /// optionally adjacent neighbour Selectables and to execute a closure
/// when the current Selectable is pressed /// when the current Selectable is pressed
pub struct Selectable<'a> { pub struct Selectable<'a> {
selected: AtomicBool, selected: AtomicBool,
east_neighbour: RwLock<Option<Weak<Selectable>>>, east_neighbour: RwLock<Option<Weak<Selectable<'a>>>>,
west_neighbour: RwLock<Option<Weak<Selectable>>>, west_neighbour: RwLock<Option<Weak<Selectable<'a>>>>,
north_neighbour: RwLock<Option<Weak<Selectable>>>, north_neighbour: RwLock<Option<Weak<Selectable<'a>>>>,
south_neighbour: RwLock<Option<Weak<Selectable>>>, south_neighbour: RwLock<Option<Weak<Selectable<'a>>>>,
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
select_audible: RwLock<Option<Arc<Audible>>>, select_audible: RwLock<Option<Arc<Audible>>>,
@ -38,10 +36,11 @@ pub struct Selectable<'a> {
selected_changed_executable: Arc<Executable<(&'a mut World, bool)>>, selected_changed_executable: Arc<Executable<(&'a mut World, bool)>>,
// exposed externally for event // exposed externally for event
on_select_executable: Arc<Executable<(&'mut World, bool)>>, on_select_executable: Arc<Executable<(&'a mut World, bool)>>,
// used for custom buttons // used for custom buttons
custom_callback: RwLock<Option<Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>>>, custom_callback:
RwLock<Option<Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>>>,
} }
impl<'a> Selectable<'a> { impl<'a> Selectable<'a> {
@ -51,15 +50,12 @@ impl<'a> Selectable<'a> {
/// ///
/// * `executable` is a `Arc<Executable>` instance /// * `executable` is a `Arc<Executable>` instance
pub fn new( pub fn new(
gui_handler: &'a GuiHandler<'a>, executable: Arc<Executable<&'a mut World>>,
executable: Arc<Executable<()>>, selected_changed_executable: Arc<Executable<(&'a mut World, bool)>>,
selected_changed_executable: Arc<Executable<bool>>, on_select_executable: Arc<Executable<(&'a mut World, bool)>>,
on_select_executable: Arc<Executable<bool>>,
isolate: bool, isolate: bool,
) -> Arc<Self> { ) -> Arc<Self> {
Arc::new(Selectable { Arc::new(Selectable {
selected: AtomicBool::new(false), selected: AtomicBool::new(false),
east_neighbour: RwLock::new(None), east_neighbour: RwLock::new(None),
@ -89,11 +85,8 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selectable` is a `&Arc<Selectable>` instance that is going to be added /// * `selectable` is a `&Arc<Selectable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.gui_handler gui_handler.add_selectable(self.ui_layer.load(SeqCst), self.clone())
.add_selectable(self.ui_layer.load(SeqCst), self.clone())?;
Ok(())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory. /// Delete method, has to be explicitly called, otherwise it will remain in memory.
@ -101,10 +94,9 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selectable` is a `&Arc<Selectable>` instance that is going to be deleted /// * `selectable` is a `&Arc<Selectable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.gui_handler gui_handler.delete_selectable(self.ui_layer.load(SeqCst), self)?;
.delete_selectable(self.ui_layer.load(SeqCst), self)?; self.set_selected(gui_handler, false)?;
self.set_selected(false)?;
Ok(()) Ok(())
} }
@ -118,8 +110,8 @@ impl<'a> Selectable<'a> {
/// # Argument /// # Argument
/// ///
/// * `selectable` is a `Arc<Selectable>` instance /// * `selectable` is a `Arc<Selectable>` instance
pub fn select(self: &Arc<Self>) -> Result<()> { pub fn select(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.gui_handler.set_selectable(Some(self.clone())) gui_handler.set_selectable(Some(self.clone()))
} }
pub fn set_custom_callback<F>(&self, custom_callback: F) pub fn set_custom_callback<F>(&self, custom_callback: F)
@ -145,12 +137,13 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selected` is the new selected state /// * `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 { if self.selected() != selected {
self.selected.store(selected, SeqCst); self.selected.store(selected, SeqCst);
self.selected_changed_executable.execute(selected)?; self.selected_changed_executable
self.on_select_executable.execute(selected)?; .execute(gui_handler, selected)?;
self.on_select_executable.execute(gui_handler, selected)?;
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
{ {
@ -171,7 +164,7 @@ impl<'a> Selectable<'a> {
} }
/// Executes the `Executable`'s callback /// 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")] #[cfg(feature = "audio")]
{ {
if let Some(audible) = self.click_audible.read().unwrap().as_ref() { 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(()) Ok(())
} }
@ -202,7 +195,7 @@ impl<'a> Selectable<'a> {
} }
/// Returns the current east neighbour, if possible /// Returns the current east neighbour, if possible
pub fn east_neighbour(&self) -> Option<Arc<Selectable>> { pub fn east_neighbour(&self) -> Option<Arc<Selectable<'a>>> {
if let Some(weak_neighbour) = self.east_neighbour.read().unwrap().as_ref() { if let Some(weak_neighbour) = self.east_neighbour.read().unwrap().as_ref() {
if let Some(neighbour) = weak_neighbour.upgrade() { if let Some(neighbour) = weak_neighbour.upgrade() {
return Some(neighbour); return Some(neighbour);
@ -217,7 +210,7 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selectable` the new east neighbour /// * `selectable` the new east neighbour
pub fn set_east_neighbour(&self, selectable: Option<&Arc<Selectable>>) { pub fn set_east_neighbour(&self, selectable: Option<&Arc<Selectable<'a>>>) {
if self.isolate { if self.isolate {
return; return;
} }
@ -231,7 +224,7 @@ impl<'a> Selectable<'a> {
} }
/// Returns the current west neighbour, if possible /// Returns the current west neighbour, if possible
pub fn west_neighbour(&self) -> Option<Arc<Selectable>> { pub fn west_neighbour(&self) -> Option<Arc<Selectable<'a>>> {
if let Some(weak_neighbour) = self.west_neighbour.read().unwrap().as_ref() { if let Some(weak_neighbour) = self.west_neighbour.read().unwrap().as_ref() {
if let Some(neighbour) = weak_neighbour.upgrade() { if let Some(neighbour) = weak_neighbour.upgrade() {
return Some(neighbour); return Some(neighbour);
@ -246,7 +239,7 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selectable` the new west neighbour /// * `selectable` the new west neighbour
pub fn set_west_neighbour(&self, selectable: Option<&Arc<Selectable>>) { pub fn set_west_neighbour(&self, selectable: Option<&Arc<Selectable<'a>>>) {
if self.isolate { if self.isolate {
return; return;
} }
@ -260,7 +253,7 @@ impl<'a> Selectable<'a> {
} }
/// Returns the current north neighbour, if possible /// Returns the current north neighbour, if possible
pub fn north_neighbour(&self) -> Option<Arc<Selectable>> { pub fn north_neighbour(&self) -> Option<Arc<Selectable<'a>>> {
if let Some(weak_neighbour) = self.north_neighbour.read().unwrap().as_ref() { if let Some(weak_neighbour) = self.north_neighbour.read().unwrap().as_ref() {
if let Some(neighbour) = weak_neighbour.upgrade() { if let Some(neighbour) = weak_neighbour.upgrade() {
return Some(neighbour); return Some(neighbour);
@ -275,7 +268,7 @@ impl<'a> Selectable<'a> {
/// # Argumnents /// # Argumnents
/// ///
/// * `selectable` the new north neighbour /// * `selectable` the new north neighbour
pub fn set_north_neighbour(&self, selectable: Option<&Arc<Selectable>>) { pub fn set_north_neighbour(&self, selectable: Option<&Arc<Selectable<'a>>>) {
if self.isolate { if self.isolate {
return; return;
} }
@ -289,7 +282,7 @@ impl<'a> Selectable<'a> {
} }
/// Returns the current south neighbour, if possible /// Returns the current south neighbour, if possible
pub fn south_neighbour(&self) -> Option<Arc<Selectable>> { pub fn south_neighbour(&self) -> Option<Arc<Selectable<'a>>> {
if let Some(weak_neighbour) = self.south_neighbour.read().unwrap().as_ref() { if let Some(weak_neighbour) = self.south_neighbour.read().unwrap().as_ref() {
if let Some(neighbour) = weak_neighbour.upgrade() { if let Some(neighbour) = weak_neighbour.upgrade() {
return Some(neighbour); return Some(neighbour);
@ -304,7 +297,7 @@ impl<'a> Selectable<'a> {
/// # Arguments /// # Arguments
/// ///
/// * `selectable` the new south neighbour /// * `selectable` the new south neighbour
pub fn set_south_neighbour(&self, selectable: Option<&Arc<Selectable>>) { pub fn set_south_neighbour(&self, selectable: Option<&Arc<Selectable<'a>>>) {
if self.isolate { if self.isolate {
return; return;
} }
@ -317,7 +310,7 @@ impl<'a> Selectable<'a> {
} }
} }
pub fn connect_vertically(upper: &Arc<Selectable>, lower: &Arc<Selectable>) { pub fn connect_vertically<'c>(upper: &Arc<Selectable<'c>>, lower: &Arc<Selectable<'c>>) {
if upper.isolate || lower.isolate { if upper.isolate || lower.isolate {
return; return;
} }
@ -326,7 +319,7 @@ impl<'a> Selectable<'a> {
*lower.north_neighbour.write().unwrap() = Some(Arc::downgrade(upper)); *lower.north_neighbour.write().unwrap() = Some(Arc::downgrade(upper));
} }
pub fn connect_horizontally(left: &Arc<Selectable>, right: &Arc<Selectable>) { pub fn connect_horizontally<'c>(left: &Arc<Selectable<'c>>, right: &Arc<Selectable<'c>>) {
if left.isolate || right.isolate { if left.isolate || right.isolate {
return; return;
} }

View file

@ -11,8 +11,8 @@ use super::texturedvertex::TexturedVertex;
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
sync::{ sync::{
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
Arc, RwLock, Arc, RwLock,
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
}, },
}; };
@ -47,7 +47,7 @@ impl TryFrom<String> for TextAlignment {
return Err(anyhow::Error::msg(format!( return Err(anyhow::Error::msg(format!(
"Failed parsing TextAlignment from: {}", "Failed parsing TextAlignment from: {}",
text text
))) )));
} }
}) })
} }
@ -80,19 +80,20 @@ impl Textable {
/// * `height_ratio` the ratio of the height in respect to the framable height /// * `height_ratio` the ratio of the height in respect to the framable height
/// * `text_alignment` where the text is aligned to /// * `text_alignment` where the text is aligned to
pub fn new( pub fn new(
gui_handler: &mut GuiHandler<'_>,
framable: Arc<Framable>, framable: Arc<Framable>,
text: String, text: String,
height_ratio: f32, height_ratio: f32,
text_alignment: TextAlignment, text_alignment: TextAlignment,
text_color: Color, text_color: Color,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
let set = framable.gui_handler().color_descriptor(text_color)?; let set = gui_handler.color_descriptor(text_color)?;
let buffer = if text.is_empty() { let buffer = if text.is_empty() {
None None
} else { } else {
Some(Self::create_text_buffer( Some(Self::create_text_buffer(
framable.gui_handler().device(), gui_handler.device(),
text.len() as u32 * 6, text.len() as u32 * 6,
)?) )?)
}; };
@ -120,7 +121,7 @@ impl Textable {
textable.framable.add_callback( textable.framable.add_callback(
weak_textable, weak_textable,
Box::new(move || textable_clone.update_text()), Box::new(move |gui_handler| textable_clone.update_text(gui_handler)),
); );
Ok(textable) Ok(textable)
@ -142,10 +143,8 @@ impl Textable {
/// # Arguments /// # Arguments
/// ///
/// * `textable` is a `&Arc<Textable>` instance that is going to be added /// * `textable` is a `&Arc<Textable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.add_textable(self.ui_layer.load(SeqCst), self.clone())
.gui_handler()
.add_textable(self.ui_layer.load(SeqCst), self.clone())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory. /// Delete method, has to be explicitly called, otherwise it will remain in memory.
@ -153,10 +152,8 @@ impl Textable {
/// # Arguments /// # Arguments
/// ///
/// * `textable` is a `&Arc<Textable>` instance that is going to be deleted /// * `textable` is a `&Arc<Textable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.framable gui_handler.delete_textable(self.ui_layer.load(SeqCst), self)
.gui_handler()
.delete_textable(self.ui_layer.load(SeqCst), self)
} }
pub fn set_ui_layer(&self, ui_layer: i32) { pub fn set_ui_layer(&self, ui_layer: i32) {
@ -173,8 +170,12 @@ impl Textable {
/// # Arguments /// # Arguments
/// ///
/// * `text_color` defines the color of the text /// * `text_color` defines the color of the text
pub fn set_text_color(&self, text_color: Color) -> Result<()> { pub fn set_text_color(
let set = self.framable.gui_handler().color_descriptor(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; *self.descriptor_set.write().unwrap() = set;
@ -186,9 +187,13 @@ impl Textable {
/// # Arguments /// # Arguments
/// ///
/// * `text_alignment` where the text is aligned to /// * `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.text_alignment.write().unwrap() = text_alignment;
self.update_text()?; self.update_text(gui_handler)?;
Ok(()) Ok(())
} }
@ -214,14 +219,14 @@ impl Textable {
/// ///
/// * `text` the text to be displayed /// * `text` the text to be displayed
/// * `height_ratio` the ratio of the height in respect to the framable height /// * `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(); let text = text.to_string();
if text.is_empty() { if text.is_empty() {
self.vertex_count.store(0, SeqCst); self.vertex_count.store(0, SeqCst);
*self.text.write().unwrap() = String::new(); *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); let weak_buffer = Arc::downgrade(&self.buffer);
Box::new(move || { Box::new(move || {
@ -234,7 +239,7 @@ impl Textable {
} else { } else {
self.vertex_count.store(text.len() as u32 * 6, SeqCst); self.vertex_count.store(text.len() as u32 * 6, SeqCst);
*self.text.write().unwrap() = text; *self.text.write().unwrap() = text;
self.update_text()?; self.update_text(gui_handler)?;
} }
Ok(()) Ok(())
@ -245,9 +250,9 @@ impl Textable {
/// # Arguments /// # Arguments
/// ///
/// * `height_ratio` the ratio of the height in respect to the framable height /// * `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.height_ratio.write().unwrap() = height_ratio;
self.update_text()?; self.update_text(gui_handler)?;
Ok(()) Ok(())
} }
@ -279,12 +284,12 @@ impl Textable {
} }
/// Updates the texts buffer /// Updates the texts buffer
pub fn update_text(&self) -> Result<()> { pub fn update_text(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.calculate_text_size(); self.calculate_text_size();
let (x, y) = self.calc_pos_from_alignment(); let (x, y) = self.calc_pos_from_alignment();
self.create_buffer(x, y)?; self.create_buffer(gui_handler, x, y)?;
Ok(()) 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 weak_buffer = Arc::downgrade(&self.buffer);
let text = self.text.read().unwrap().clone(); let text = self.text.read().unwrap().clone();
let character_size = self.character_size.load(SeqCst); 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 || { let async_buffer_creation = Box::new(move || {
if let Some(buffer) = weak_buffer.upgrade() { if let Some(buffer) = weak_buffer.upgrade() {
@ -484,14 +494,12 @@ impl Textable {
Ok(()) Ok(())
}); });
self.framable gui_handler.enqueue_text_update(async_buffer_creation);
.gui_handler()
.enqueue_text_update(async_buffer_creation);
Ok(()) Ok(())
} }
fn text_changed_through_write(&self) -> Result<()> { fn text_changed_through_write(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.vertex_count self.vertex_count
.store(self.text.read().unwrap().len() as u32 * 6, SeqCst); .store(self.text.read().unwrap().len() as u32 * 6, SeqCst);
self.character_size.store( self.character_size.store(
@ -500,28 +508,28 @@ impl Textable {
SeqCst, SeqCst,
); );
self.update_text()?; self.update_text(gui_handler)?;
Ok(()) Ok(())
} }
} }
impl ModifyText for Textable { 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.write().unwrap() = text;
self.text_changed_through_write() self.text_changed_through_write(gui_handler)
} }
fn add_letter(&self, letter: char) -> Result<String> { fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<String> {
self.text.write().unwrap().push(letter); self.text.write().unwrap().push(letter);
self.text_changed_through_write()?; self.text_changed_through_write(gui_handler)?;
Ok(self.text.read().unwrap().clone()) Ok(self.text.read().unwrap().clone())
} }
fn remove_last(&self) -> Result<Option<String>> { fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<Option<String>> {
self.text.write().unwrap().pop(); self.text.write().unwrap().pop();
self.text_changed_through_write()?; self.text_changed_through_write(gui_handler)?;
let text = self.text.read().unwrap().clone(); let text = self.text.read().unwrap().clone();

View file

@ -4,20 +4,18 @@ use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use std::sync::{ use std::sync::{
atomic::{AtomicI32, Ordering::SeqCst},
Arc, RwLock, Arc, RwLock,
atomic::{AtomicI32, Ordering::SeqCst},
}; };
pub trait ModifyText: Send + Sync { pub trait ModifyText: Send + Sync {
fn set_text(&self, text: String) -> Result<()>; fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()>;
fn add_letter(&self, letter: char) -> Result<String>; fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<String>;
fn remove_last(&self) -> Result<Option<String>>; fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<Option<String>>;
} }
/// `Writeable` gives the ability to modify the text inside an `Textable` /// `Writeable` gives the ability to modify the text inside an `Textable`
pub struct Writeable { pub struct Writeable {
gui_handler: Arc<GuiHandler>,
modifyable: Arc<dyn ModifyText>, modifyable: Arc<dyn ModifyText>,
text_change_executable: Arc<Executable<Option<String>>>, text_change_executable: Arc<Executable<Option<String>>>,
@ -29,12 +27,10 @@ pub struct Writeable {
impl Writeable { impl Writeable {
/// Factory method for `Writeable`, returns `Arc<Writeable>`. /// Factory method for `Writeable`, returns `Arc<Writeable>`.
pub fn new( pub fn new(
gui_handler: Arc<GuiHandler>,
modifyable: Arc<dyn ModifyText>, modifyable: Arc<dyn ModifyText>,
text_change_executable: Arc<Executable<Option<String>>>, text_change_executable: Arc<Executable<Option<String>>>,
) -> Result<Arc<Self>> { ) -> Result<Arc<Self>> {
Ok(Arc::new(Writeable { Ok(Arc::new(Writeable {
gui_handler,
modifyable, modifyable,
text_change_executable, text_change_executable,
@ -44,8 +40,8 @@ impl Writeable {
})) }))
} }
pub fn set_active(self: &Arc<Self>) -> Result<()> { pub fn set_active(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
if self.gui_handler.set_active_writeable(self.clone())? { if gui_handler.set_active_writeable(self.clone())? {
if let Some(exec) = &*self.activation_changed_executable.read().unwrap() { if let Some(exec) = &*self.activation_changed_executable.read().unwrap() {
exec(true)?; exec(true)?;
} }
@ -74,9 +70,8 @@ impl Writeable {
/// # Arguments /// # Arguments
/// ///
/// * `writeable` is a `&Arc<Writeable>` instance that is going to be added /// * `writeable` is a `&Arc<Writeable>` instance that is going to be added
pub fn add(self: &Arc<Self>) -> Result<()> { pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.gui_handler gui_handler.add_writeable(self.ui_layer.load(SeqCst), self.clone())
.add_writeable(self.ui_layer.load(SeqCst), self.clone())
} }
/// Delete method, has to be explicitly called, otherwise it will remain in memory. /// Delete method, has to be explicitly called, otherwise it will remain in memory.
@ -84,9 +79,8 @@ impl Writeable {
/// # Arguments /// # Arguments
/// ///
/// * `writeable` is a `&Arc<Writeable>` instance that is going to be deleted /// * `writeable` is a `&Arc<Writeable>` instance that is going to be deleted
pub fn delete(self: &Arc<Self>) -> Result<()> { pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.gui_handler gui_handler.delete_writeable(self.ui_layer.load(SeqCst), self)
.delete_writeable(self.ui_layer.load(SeqCst), self)
} }
pub fn set_ui_layer(&self, ui_layer: i32) { pub fn set_ui_layer(&self, ui_layer: i32) {
@ -98,11 +92,11 @@ impl Writeable {
/// # Arguments /// # Arguments
/// ///
/// * `text` that replaces the current text /// * `text` that replaces the current text
pub fn set_text(&self, text: String) -> Result<()> { pub fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()> {
self.modifyable.set_text(text.clone())?; self.modifyable.set_text(gui_handler, text.clone())?;
self.text_change_executable 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(()) Ok(())
} }
@ -112,17 +106,19 @@ impl Writeable {
/// # Arguments /// # Arguments
/// ///
/// * `letter` the letter thats going to be added /// * `letter` the letter thats going to be added
pub fn add_letter(&self, letter: char) -> Result<()> { pub fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<()> {
self.text_change_executable self.text_change_executable.execute(
.execute(Some(self.modifyable.add_letter(letter)?))?; gui_handler,
Some(self.modifyable.add_letter(gui_handler, letter)?),
)?;
Ok(()) Ok(())
} }
/// Removes the last letter /// Removes the last letter
pub fn remove_last(&self) -> Result<()> { pub fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
self.text_change_executable self.text_change_executable
.execute(self.modifyable.remove_last()?)?; .execute(gui_handler, self.modifyable.remove_last(gui_handler)?)?;
Ok(()) Ok(())
} }

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
pub use super::builder::{builder::GuiBuilder, snippet::GuiSnippet}; pub use super::builder::{builder::GuiBuilder, snippet::GuiSnippet};
pub use super::context_interface::{ContextInterface, TargetMode, Unfold}; pub use super::context_interface::{Chain, ContextInterface, TargetMode, Unfold};
pub use super::controller_button::ControllerButton; pub use super::controller_button::ControllerButton;
pub use super::element_creator::*; pub use super::element_creator::*;
pub use super::elements::prelude::*; pub use super::elements::prelude::*;