Fix GuiHandler

This commit is contained in:
Michael Hübner 2025-03-04 09:48:30 +01:00
parent 0976860b9f
commit afc101effc
3 changed files with 140 additions and 65 deletions

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

@ -439,8 +439,8 @@ impl<'a> GuiHandler<'a> {
let image = Image::from_file(path)? let image = Image::from_file(path)?
.max_mip_map_levels() .max_mip_map_levels()
.attach_pretty_sampler(self.device())? .attach_pretty_sampler(&self.device)?
.build(self.device(), self.queue())?; .build(&self.device, &self.queue)?;
*weak_image = Arc::downgrade(&image); *weak_image = Arc::downgrade(&image);
@ -499,7 +499,10 @@ impl<'a> GuiHandler<'a> {
DescriptorPool::prepare_set(&desc_pool).allocate() DescriptorPool::prepare_set(&desc_pool).allocate()
} }
pub(crate) fn displayable_image_from_path(&self, mut path: AssetPath) -> Result<Arc<Image>> { pub(crate) fn displayable_image_from_path(
&mut self,
mut path: AssetPath,
) -> Result<Arc<Image>> {
if !path.has_prefix() { if !path.has_prefix() {
path.set_prefix( path.set_prefix(
&self &self
@ -583,7 +586,7 @@ impl<'a> GuiHandler<'a> {
self.hover_sound.as_ref() self.hover_sound.as_ref()
} }
pub fn set_on_selected_event<F>(&self, f: F) pub fn set_on_selected_event<F>(&mut self, f: F)
where where
F: Fn() -> Result<()> + Send + Sync + 'static, F: Fn() -> Result<()> + Send + Sync + 'static,
{ {
@ -611,6 +614,8 @@ impl<'a> GuiHandler<'a> {
} }
} }
let callback_self = unsafe { remove_life_time_mut(self) };
match hovered { match hovered {
Some(hovered) => { Some(hovered) => {
if let Some(current) = &self.current_hoverable { if let Some(current) = &self.current_hoverable {
@ -618,7 +623,7 @@ impl<'a> GuiHandler<'a> {
return Ok(()); return Ok(());
} }
current.set_hovered(self, false)?; current.set_hovered(callback_self, false)?;
} }
hovered.set_hovered(self, true)?; hovered.set_hovered(self, true)?;
@ -637,7 +642,7 @@ impl<'a> GuiHandler<'a> {
self.current_hoverable self.current_hoverable
.as_ref() .as_ref()
.unwrap() .unwrap()
.set_hovered(self, false)?; .set_hovered(callback_self, false)?;
self.current_hoverable = None; self.current_hoverable = None;
} }
} }
@ -676,12 +681,14 @@ impl<'a> GuiHandler<'a> {
} }
pub fn mouse_up(&mut self, mouse_button: MouseButton) -> Result<bool> { pub fn mouse_up(&mut self, mouse_button: MouseButton) -> Result<bool> {
let callback_self = unsafe { remove_life_time_mut(self) };
if mouse_button == MouseButton::Left { if mouse_button == MouseButton::Left {
if self.current_clickable.is_some() { if self.current_clickable.is_some() {
self.current_clickable self.current_clickable
.as_ref() .as_ref()
.unwrap() .unwrap()
.set_clicked(self, false)?; .set_clicked(callback_self, false)?;
if self if self
.current_clickable .current_clickable
@ -690,7 +697,7 @@ impl<'a> GuiHandler<'a> {
.is_pressed(self.mouse_x as i32, self.mouse_y as i32) .is_pressed(self.mouse_x as i32, self.mouse_y as i32)
{ {
if let Some(hoverable) = self.current_hoverable.as_ref() { if let Some(hoverable) = self.current_hoverable.as_ref() {
hoverable.set_hovered(self, true)?; hoverable.set_hovered(callback_self, true)?;
} }
} }
@ -708,8 +715,10 @@ impl<'a> GuiHandler<'a> {
} }
pub fn accept_selection(&mut self) -> Result<bool> { pub fn accept_selection(&mut self) -> Result<bool> {
let callback_self = unsafe { remove_life_time_mut(self) };
if let Some(current_selectable) = &self.current_selectable { if let Some(current_selectable) = &self.current_selectable {
current_selectable.click_event(self)?; current_selectable.click_event(callback_self)?;
return Ok(true); return Ok(true);
} }
@ -767,10 +776,12 @@ impl<'a> GuiHandler<'a> {
self.current_writeable.clone() self.current_writeable.clone()
} }
pub fn remove_char(&self) -> Result<bool> { pub fn remove_char(&mut self) -> Result<bool> {
let callback_self = unsafe { remove_life_time_mut(self) };
match &self.current_writeable { match &self.current_writeable {
Some(current_writable) => { Some(current_writable) => {
current_writable.remove_last()?; current_writable.remove_last(callback_self)?;
Ok(true) Ok(true)
} }
None => Ok(false), None => Ok(false),
@ -784,41 +795,42 @@ impl<'a> GuiHandler<'a> {
pub fn update_selection(&mut self, direction: GuiDirection) -> Result<bool> { pub fn update_selection(&mut self, direction: GuiDirection) -> Result<bool> {
if direction != self.last_direction { if direction != self.last_direction {
self.last_direction = direction; self.last_direction = direction;
let callback_self = unsafe { remove_life_time_mut(self) };
match self.current_selectable.write().unwrap().as_mut() { match &mut self.current_selectable {
Some(current_selectable) => match direction { Some(current_selectable) => match direction {
GuiDirection::Left => { GuiDirection::Left => {
if let Some(neighbour) = current_selectable.west_neighbour() { if let Some(neighbour) = current_selectable.west_neighbour() {
current_selectable.set_selected(self, false)?; current_selectable.set_selected(callback_self, false)?;
*current_selectable = neighbour; *current_selectable = neighbour;
current_selectable.set_selected(self, true)?; current_selectable.set_selected(callback_self, true)?;
}; };
Ok(true) Ok(true)
} }
GuiDirection::Right => { GuiDirection::Right => {
if let Some(neighbour) = current_selectable.east_neighbour() { if let Some(neighbour) = current_selectable.east_neighbour() {
current_selectable.set_selected(self, false)?; current_selectable.set_selected(callback_self, false)?;
*current_selectable = neighbour; *current_selectable = neighbour;
current_selectable.set_selected(self, true)?; current_selectable.set_selected(callback_self, true)?;
}; };
Ok(true) Ok(true)
} }
GuiDirection::Up => { GuiDirection::Up => {
if let Some(neighbour) = current_selectable.north_neighbour() { if let Some(neighbour) = current_selectable.north_neighbour() {
current_selectable.set_selected(self, false)?; current_selectable.set_selected(callback_self, false)?;
*current_selectable = neighbour; *current_selectable = neighbour;
current_selectable.set_selected(self, true)?; current_selectable.set_selected(callback_self, true)?;
}; };
Ok(true) Ok(true)
} }
GuiDirection::Down => { GuiDirection::Down => {
if let Some(neighbour) = current_selectable.south_neighbour() { if let Some(neighbour) = current_selectable.south_neighbour() {
current_selectable.set_selected(self, false)?; current_selectable.set_selected(callback_self, false)?;
*current_selectable = neighbour; *current_selectable = neighbour;
current_selectable.set_selected(self, true)?; current_selectable.set_selected(callback_self, true)?;
}; };
Ok(true) Ok(true)
@ -861,7 +873,7 @@ impl<'a> GuiHandler<'a> {
fn render( fn render(
&self, &self,
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
command_buffer_state: &CommandBufferState, command_buffer_state: &mut CommandBufferState,
render_target: &RenderTarget, render_target: &RenderTarget,
single_color_objects: &GuiSeparator, single_color_objects: &GuiSeparator,
rectangle_objects: &GuiSeparator, rectangle_objects: &GuiSeparator,
@ -940,15 +952,14 @@ impl<'a> GuiHandler<'a> {
buffer_recorder.set_scissor(&scissor); buffer_recorder.set_scissor(&scissor);
buffer_recorder.set_viewport(&viewport); buffer_recorder.set_viewport(&viewport);
let mut text_buffers = command_buffer_state.text_buffers.write().unwrap(); command_buffer_state.text_buffers.clear();
text_buffers.clear();
// ---------- render textables ---------- // ---------- render textables ----------
for textable in elements.iter_textables() { for textable in elements.iter_textables() {
if let Some(text_buffer) = textable.buffer() { if let Some(text_buffer) = textable.buffer() {
buffer_recorder.bind_vertex_buffer(&text_buffer); buffer_recorder.bind_vertex_buffer(&text_buffer);
text_buffers.push(text_buffer); command_buffer_state.text_buffers.push(text_buffer);
buffer_recorder.bind_descriptor_sets_minimal(&[ buffer_recorder.bind_descriptor_sets_minimal(&[
&self.bitmap_desc_set, &self.bitmap_desc_set,
@ -987,10 +998,8 @@ impl<'a> GuiHandler<'a> {
macro_rules! add_element { macro_rules! add_element {
($layers: expr, $layer_id: ident, $element: ident) => { ($layers: expr, $layer_id: ident, $element: ident) => {
let mut layers = $layers.lock().unwrap();
paste! { paste! {
match layers.iter_mut().find(|(id, _)| *id == $layer_id) { match $layers.iter_mut().find(|(id, _)| *id == $layer_id) {
Some((_, layer)) => { Some((_, layer)) => {
layer.[<add_ $element>]($element); layer.[<add_ $element>]($element);
} }
@ -998,8 +1007,8 @@ macro_rules! add_element {
let mut elements = Elements::default(); let mut elements = Elements::default();
elements.[<add_ $element>]($element); elements.[<add_ $element>]($element);
layers.push(($layer_id, elements)); $layers.push(($layer_id, elements));
layers.sort_by(|(left_id, _), (right_id, _)| left_id.cmp(right_id)); $layers.sort_by(|(left_id, _), (right_id, _)| left_id.cmp(right_id));
} }
} }
} }
@ -1225,8 +1234,10 @@ impl<'a> GuiHandler<'a> {
} }
pub(crate) fn set_selectable(&mut self, selectable: Option<Arc<Selectable<'a>>>) -> Result<()> { pub(crate) fn set_selectable(&mut self, selectable: Option<Arc<Selectable<'a>>>) -> Result<()> {
let callback_self = unsafe { remove_life_time_mut(self) };
if let Some(selectable) = &self.current_selectable { if let Some(selectable) = &self.current_selectable {
selectable.set_selected(self, false)?; selectable.set_selected(callback_self, false)?;
} }
if let Some(selectable) = &selectable { if let Some(selectable) = &selectable {
@ -1578,7 +1589,7 @@ impl<'a> GuiHandler<'a> {
impl<'a> GuiHandler<'a> { impl<'a> GuiHandler<'a> {
pub fn process( pub fn process(
&self, &mut self,
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
) -> Result<()> { ) -> Result<()> {
@ -1594,21 +1605,23 @@ impl<'a> GuiHandler<'a> {
self.needs_update = false; self.needs_update = false;
} }
let callback_self = unsafe { remove_life_time_mut(self) };
self.command_buffers self.command_buffers
.chain(&self.render_targets) .chain_mut_1(&self.render_targets)
.chain(&self.text_objects) .chain_mut_1(&mut self.text_objects)
.unfold() .unfold()
.chain(&self.rectangle_objects) .chain_mut_1(&self.rectangle_objects)
.unfold() .unfold()
.chain(&self.single_color_objects) .chain_mut_1(&self.single_color_objects)
.unfold() .unfold()
.chain(indices) .chain_mut_1(indices)
.unfold() .unfold()
.chain(&self.text_to_screen.pipeline) .chain_mut_1(&self.text_to_screen.pipeline)
.unfold() .unfold()
.chain(&self.text_to_screen.descriptor) .chain_mut_1(&self.text_to_screen.descriptor)
.unfold() .unfold()
.execute( .execute_into(
|( |(
command_buffers, command_buffers,
render_target, render_target,
@ -1619,16 +1632,16 @@ impl<'a> GuiHandler<'a> {
text_pipeline, text_pipeline,
text_descriptor, text_descriptor,
)| { )| {
self.render( callback_self.render(
buffer_recorder, buffer_recorder,
&command_buffers[****index], &mut command_buffers[***index],
render_target, render_target,
single_color_object, single_color_object,
rectangle_objects, rectangle_objects,
text_objects, text_objects,
text_pipeline, text_pipeline,
text_descriptor, text_descriptor,
****index, ***index,
) )
}, },
)?; )?;
@ -1642,9 +1655,8 @@ impl<'a> GuiHandler<'a> {
height: u32, height: u32,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
) -> Result<()> { ) -> Result<()> {
images images.chain_mut_2(&mut self.render_targets).execute_into(
.chain(&self.render_targets) |(images, old_render_target)| {
.execute(|(images, old_render_target)| {
let new_render_target = Self::create_render_target( let new_render_target = Self::create_render_target(
&self.device, &self.device,
&images, &images,
@ -1653,10 +1665,11 @@ impl<'a> GuiHandler<'a> {
self.text_sample_count, self.text_sample_count,
)?; )?;
**old_render_target = new_render_target; *old_render_target = new_render_target;
Ok(()) Ok(())
})?; },
)?;
self.text_to_screen.update_on_resize(&self.render_targets)?; self.text_to_screen.update_on_resize(&self.render_targets)?;
@ -1666,9 +1679,11 @@ impl<'a> GuiHandler<'a> {
self.width = width; self.width = width;
self.height = height; self.height = height;
let callback_self = unsafe { remove_life_time_mut(self) };
for (_, elements) in self.layers.iter() { for (_, elements) in self.layers.iter() {
for framable in elements.iter_framables() { for framable in elements.iter_framables() {
framable.resize(self)?; framable.resize(callback_self)?;
} }
} }

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::*;