Compare commits

..

6 commits

Author SHA1 Message Date
hodasemi 792e06abdc Set icon from path 2024-08-29 12:37:22 +02:00
hodasemi e0dc572580 Fix lock 2024-08-29 11:13:28 +02:00
hodasemi 9c0250e1f6 Process callbacks asynchronously 2024-08-29 11:09:17 +02:00
hodasemi 20332deb41 Fix audio feature 2024-08-27 11:42:24 +02:00
hodasemi be69061dd9 Rework resize 2024-08-27 11:24:44 +02:00
hodasemi 304a29397b List states 2024-08-26 11:46:43 +02:00
8 changed files with 53 additions and 19 deletions

View file

@ -5,7 +5,7 @@ authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2021"
[dependencies] [dependencies]
quick-xml = "0.36.0" quick-xml = "0.31.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" }
vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" } vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }

View file

@ -135,9 +135,9 @@ impl ButtonBuilder {
}, },
)?; )?;
let click_executable = Executable::new(); let click_executable = Executable::new(&gui_handler);
let select_executable = Executable::new(); let select_executable = Executable::new(&gui_handler);
let on_select_executable = Executable::new(); let on_select_executable = Executable::new(&gui_handler);
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
let click_sound = self let click_sound = self

View file

@ -3,6 +3,7 @@ use crate::{
prelude::*, prelude::*,
}; };
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath;
use utilities::prelude::*; use utilities::prelude::*;
use vulkan_rs::prelude::*; use vulkan_rs::prelude::*;
@ -142,6 +143,10 @@ impl Icon {
self.iconizable_wrapper.set_icon(icon, self.visible()) self.iconizable_wrapper.set_icon(icon, self.visible())
} }
pub fn set_icon_from_path(&self, asset_path: AssetPath) -> Result<()> {
self.iconizable_wrapper.set_icon(asset_path, self.visible())
}
pub fn set_margin(&self, margin: u32) -> Result<()> { pub fn set_margin(&self, margin: u32) -> Result<()> {
self.iconizable_wrapper.set_margin(margin) self.iconizable_wrapper.set_margin(margin)
} }

View file

@ -82,7 +82,7 @@ impl MultiLineTextFieldBuilder {
} }
let text = Arc::new(SplittedText::new(self.text)); let text = Arc::new(SplittedText::new(self.text));
let text_changed_exec = Executable::new(); let text_changed_exec = Executable::new(&gui_handler);
let writeable = Writeable::new(gui_handler, text.clone(), text_changed_exec.clone())?; let writeable = Writeable::new(gui_handler, text.clone(), text_changed_exec.clone())?;
let multi_line_text_field = Arc::new(MultiLineTextField { let multi_line_text_field = Arc::new(MultiLineTextField {

View file

@ -69,7 +69,7 @@ impl TextFieldBuilder {
self.text_color, self.text_color,
)?; )?;
let text_changed_executable = Executable::new(); let text_changed_executable = Executable::new(&gui_handler);
let writeable = Writeable::new( let writeable = Writeable::new(
gui_handler, gui_handler,

View file

@ -4,15 +4,19 @@ use anyhow::Result;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use crate::prelude::*;
/// `Executable` holds a closure which can be executed /// `Executable` holds a closure which can be executed
pub struct Executable<I> { pub struct Executable<I: Send + Sync + 'static> {
callback: RwLock<Option<Box<dyn Fn(I) -> Result<()> + Send + Sync>>>, gui_handler: Arc<GuiHandler>,
callback: RwLock<Option<Arc<dyn Fn(I) -> Result<()> + Send + Sync>>>,
} }
impl<I> 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() -> Arc<Self> { pub fn new(gui_handler: &Arc<GuiHandler>) -> Arc<Self> {
Arc::new(Executable { Arc::new(Executable {
gui_handler: gui_handler.clone(),
callback: RwLock::new(None), callback: RwLock::new(None),
}) })
} }
@ -29,7 +33,7 @@ impl<I> Executable<I> {
let mut function = self.callback.write().unwrap(); let mut function = self.callback.write().unwrap();
match callback.into() { match callback.into() {
Some(f) => *function = Some(Box::new(f)), Some(f) => *function = Some(Arc::new(f)),
None => *function = None, None => *function = None,
} }
} }
@ -37,7 +41,9 @@ impl<I> 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, input: I) -> Result<()> {
if let Some(callback) = self.callback.read().unwrap().as_ref() { if let Some(callback) = self.callback.read().unwrap().as_ref() {
(callback)(input)?; let callback = callback.clone();
self.gui_handler.add_callback(move || (callback)(input));
} }
Ok(()) Ok(())

View file

@ -14,12 +14,12 @@ use super::{
use cgmath::{ortho, vec2}; use cgmath::{ortho, vec2};
use std::sync::Weak;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, AtomicU32, Ordering::SeqCst}, atomic::{AtomicBool, AtomicU32, Ordering::SeqCst},
Arc, Mutex, RwLock, Arc, Mutex, RwLock,
}; };
use std::{collections::HashMap, ptr}; use std::{collections::HashMap, ptr};
use std::{mem, sync::Weak};
use paste::paste; use paste::paste;
@ -191,7 +191,7 @@ impl TextToScreen {
} }
pub struct GuiHandler { pub struct GuiHandler {
context: Arc<dyn ContextInterface>, _context: Arc<dyn ContextInterface>,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Mutex<Queue>>, queue: Arc<Mutex<Queue>>,
@ -257,6 +257,8 @@ pub struct GuiHandler {
current_selectable: RwLock<Option<Arc<Selectable>>>, current_selectable: RwLock<Option<Arc<Selectable>>>,
text_sample_count: VkSampleCountFlags, text_sample_count: VkSampleCountFlags,
callback_list: Mutex<Vec<Box<dyn FnOnce() -> Result<()> + Send + Sync>>>,
} }
impl GuiHandler { impl GuiHandler {
@ -309,7 +311,7 @@ impl GuiHandler {
.build(device.clone())?; .build(device.clone())?;
Ok(Arc::new(GuiHandler { Ok(Arc::new(GuiHandler {
context: context.clone(), _context: context.clone(),
device: device.clone(), device: device.clone(),
queue: queue.clone(), queue: queue.clone(),
@ -403,6 +405,8 @@ impl GuiHandler {
current_writeable: RwLock::new(None), current_writeable: RwLock::new(None),
text_sample_count, text_sample_count,
callback_list: Mutex::default(),
})) }))
} }
@ -416,7 +420,7 @@ impl GuiHandler {
#[cfg(feature = "audio")] #[cfg(feature = "audio")]
pub(crate) fn context(&self) -> &Arc<dyn ContextInterface> { pub(crate) fn context(&self) -> &Arc<dyn ContextInterface> {
&self.context &self._context
} }
pub fn width(&self) -> u32 { pub fn width(&self) -> u32 {
@ -881,6 +885,16 @@ impl GuiHandler {
*self.tooltip_ui.write().unwrap() = tooltip; *self.tooltip_ui.write().unwrap() = tooltip;
} }
pub(crate) fn add_callback<F: FnOnce() -> Result<()> + Send + Sync + 'static>(&self, f: F) {
self.callback_list.lock().unwrap().push(Box::new(f));
}
pub fn process_callbacks(&self) -> Result<()> {
let callbacks = mem::take(&mut *self.callback_list.lock().unwrap());
callbacks.into_iter().try_for_each(|callback| callback())
}
fn render( fn render(
&self, &self,
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
@ -1657,9 +1671,13 @@ impl GuiHandler {
Ok(()) Ok(())
} }
pub fn resize(&self, width: u32, height: u32) -> Result<()> { pub fn resize(
self.context &self,
.images() width: u32,
height: u32,
images: &TargetMode<Vec<Arc<Image>>>,
) -> Result<()> {
images
.chain(&self.render_targets) .chain(&self.render_targets)
.execute(|(images, render_target)| { .execute(|(images, render_target)| {
let mut rt_lock = render_target.write().unwrap(); let mut rt_lock = render_target.write().unwrap();

View file

@ -238,6 +238,11 @@ impl States {
self self
} }
/// lists available states
pub fn states(&self) -> impl Iterator<Item = &str> {
self.states.keys().map(|s| s.as_str())
}
/// Adds a single state /// Adds a single state
pub fn add_state<'a>( pub fn add_state<'a>(
&mut self, &mut self,