diff --git a/src/context_interface.rs b/src/context_interface.rs index 380aef4..1edbf4e 100644 --- a/src/context_interface.rs +++ b/src/context_interface.rs @@ -55,20 +55,6 @@ impl TargetMode { } } - pub fn chain<'a, R>(&'a self, other: &'a TargetMode) -> 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(&self, mut f: F) -> anyhow::Result> where F: FnMut(&T) -> anyhow::Result, @@ -90,6 +76,56 @@ impl TargetMode { } } +pub trait Chain<'a, R, T> { + fn chain(&'a self, other: &'a TargetMode) -> TargetMode<(&'a R, &'a T)>; + fn chain_mut_1(&'a mut self, other: &'a TargetMode) -> TargetMode<(&'a mut R, &'a T)>; + fn chain_mut_2(&'a self, other: &'a mut TargetMode) -> TargetMode<(&'a R, &'a mut T)>; +} + +impl<'a, R, T> Chain<'a, R, T> for TargetMode { + fn chain(&'a self, other: &'a TargetMode) -> 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) -> 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) -> 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 { type Output; @@ -104,9 +140,33 @@ macro_rules! impl_unfold { fn unfold(self) -> Self::Output { match self { - TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ &$rhs_var)), + TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ $rhs_var)), TargetMode::Stereo( ( ( $( [], )+ ) , [] ), ( ( $( [], )+ ) , [] ) ) - => TargetMode::Stereo( ( $( [], )+ &[] ), ( $( [], )+ &[] ) ), + => TargetMode::Stereo( ( $( [], )+ [] ), ( $( [], )+ [] ) ), + } + } + } + + 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( ( ( $( [], )+ ) , [] ), ( ( $( [], )+ ) , [] ) ) + => TargetMode::Stereo( ( $( [], )+ [] ), ( $( [], )+ [] ) ), + } + } + } + + 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( ( ( $( [], )+ ) , [] ), ( ( $( [], )+ ) , [] ) ) + => TargetMode::Stereo( ( $( [], )+ [] ), ( $( [], )+ [] ) ), } } } diff --git a/src/gui_handler/gui_handler.rs b/src/gui_handler/gui_handler.rs index 516f12e..8bb3379 100644 --- a/src/gui_handler/gui_handler.rs +++ b/src/gui_handler/gui_handler.rs @@ -439,8 +439,8 @@ impl<'a> GuiHandler<'a> { let image = Image::from_file(path)? .max_mip_map_levels() - .attach_pretty_sampler(self.device())? - .build(self.device(), self.queue())?; + .attach_pretty_sampler(&self.device)? + .build(&self.device, &self.queue)?; *weak_image = Arc::downgrade(&image); @@ -499,7 +499,10 @@ impl<'a> GuiHandler<'a> { DescriptorPool::prepare_set(&desc_pool).allocate() } - pub(crate) fn displayable_image_from_path(&self, mut path: AssetPath) -> Result> { + pub(crate) fn displayable_image_from_path( + &mut self, + mut path: AssetPath, + ) -> Result> { if !path.has_prefix() { path.set_prefix( &self @@ -583,7 +586,7 @@ impl<'a> GuiHandler<'a> { self.hover_sound.as_ref() } - pub fn set_on_selected_event(&self, f: F) + pub fn set_on_selected_event(&mut self, f: F) where 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 { Some(hovered) => { if let Some(current) = &self.current_hoverable { @@ -618,7 +623,7 @@ impl<'a> GuiHandler<'a> { return Ok(()); } - current.set_hovered(self, false)?; + current.set_hovered(callback_self, false)?; } hovered.set_hovered(self, true)?; @@ -637,7 +642,7 @@ impl<'a> GuiHandler<'a> { self.current_hoverable .as_ref() .unwrap() - .set_hovered(self, false)?; + .set_hovered(callback_self, false)?; self.current_hoverable = None; } } @@ -676,12 +681,14 @@ impl<'a> GuiHandler<'a> { } pub fn mouse_up(&mut self, mouse_button: MouseButton) -> Result { + let callback_self = unsafe { remove_life_time_mut(self) }; + if mouse_button == MouseButton::Left { if self.current_clickable.is_some() { self.current_clickable .as_ref() .unwrap() - .set_clicked(self, false)?; + .set_clicked(callback_self, false)?; if self .current_clickable @@ -690,7 +697,7 @@ impl<'a> GuiHandler<'a> { .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)?; + hoverable.set_hovered(callback_self, true)?; } } @@ -708,8 +715,10 @@ impl<'a> GuiHandler<'a> { } pub fn accept_selection(&mut self) -> Result { + let callback_self = unsafe { remove_life_time_mut(self) }; + if let Some(current_selectable) = &self.current_selectable { - current_selectable.click_event(self)?; + current_selectable.click_event(callback_self)?; return Ok(true); } @@ -767,10 +776,12 @@ impl<'a> GuiHandler<'a> { self.current_writeable.clone() } - pub fn remove_char(&self) -> Result { + pub fn remove_char(&mut self) -> Result { + let callback_self = unsafe { remove_life_time_mut(self) }; + match &self.current_writeable { Some(current_writable) => { - current_writable.remove_last()?; + current_writable.remove_last(callback_self)?; Ok(true) } None => Ok(false), @@ -784,41 +795,42 @@ impl<'a> GuiHandler<'a> { pub fn update_selection(&mut self, direction: GuiDirection) -> Result { if direction != self.last_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 { GuiDirection::Left => { 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.set_selected(self, true)?; + current_selectable.set_selected(callback_self, true)?; }; Ok(true) } GuiDirection::Right => { 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.set_selected(self, true)?; + current_selectable.set_selected(callback_self, true)?; }; Ok(true) } GuiDirection::Up => { 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.set_selected(self, true)?; + current_selectable.set_selected(callback_self, true)?; }; Ok(true) } GuiDirection::Down => { 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.set_selected(self, true)?; + current_selectable.set_selected(callback_self, true)?; }; Ok(true) @@ -861,7 +873,7 @@ impl<'a> GuiHandler<'a> { fn render( &self, buffer_recorder: &mut CommandBufferRecorder<'_>, - command_buffer_state: &CommandBufferState, + command_buffer_state: &mut CommandBufferState, render_target: &RenderTarget, single_color_objects: &GuiSeparator, rectangle_objects: &GuiSeparator, @@ -940,15 +952,14 @@ impl<'a> GuiHandler<'a> { buffer_recorder.set_scissor(&scissor); buffer_recorder.set_viewport(&viewport); - let mut text_buffers = command_buffer_state.text_buffers.write().unwrap(); - text_buffers.clear(); + command_buffer_state.text_buffers.clear(); // ---------- render textables ---------- for textable in elements.iter_textables() { if let Some(text_buffer) = textable.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(&[ &self.bitmap_desc_set, @@ -987,10 +998,8 @@ impl<'a> GuiHandler<'a> { macro_rules! add_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); } @@ -998,8 +1007,8 @@ macro_rules! add_element { let mut elements = Elements::default(); elements.[]($element); - layers.push(($layer_id, elements)); - layers.sort_by(|(left_id, _), (right_id, _)| left_id.cmp(right_id)); + $layers.push(($layer_id, elements)); + $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>>) -> Result<()> { + let callback_self = unsafe { remove_life_time_mut(self) }; + if let Some(selectable) = &self.current_selectable { - selectable.set_selected(self, false)?; + selectable.set_selected(callback_self, false)?; } if let Some(selectable) = &selectable { @@ -1578,7 +1589,7 @@ impl<'a> GuiHandler<'a> { impl<'a> GuiHandler<'a> { pub fn process( - &self, + &mut self, buffer_recorder: &mut CommandBufferRecorder<'_>, indices: &TargetMode, ) -> Result<()> { @@ -1594,21 +1605,23 @@ impl<'a> GuiHandler<'a> { self.needs_update = false; } + let callback_self = unsafe { remove_life_time_mut(self) }; + self.command_buffers - .chain(&self.render_targets) - .chain(&self.text_objects) + .chain_mut_1(&self.render_targets) + .chain_mut_1(&mut self.text_objects) .unfold() - .chain(&self.rectangle_objects) + .chain_mut_1(&self.rectangle_objects) .unfold() - .chain(&self.single_color_objects) + .chain_mut_1(&self.single_color_objects) .unfold() - .chain(indices) + .chain_mut_1(indices) .unfold() - .chain(&self.text_to_screen.pipeline) + .chain_mut_1(&self.text_to_screen.pipeline) .unfold() - .chain(&self.text_to_screen.descriptor) + .chain_mut_1(&self.text_to_screen.descriptor) .unfold() - .execute( + .execute_into( |( command_buffers, render_target, @@ -1619,16 +1632,16 @@ impl<'a> GuiHandler<'a> { text_pipeline, text_descriptor, )| { - self.render( + callback_self.render( buffer_recorder, - &command_buffers[****index], + &mut command_buffers[***index], render_target, single_color_object, rectangle_objects, text_objects, text_pipeline, text_descriptor, - ****index, + ***index, ) }, )?; @@ -1642,9 +1655,8 @@ impl<'a> GuiHandler<'a> { height: u32, images: &TargetMode>>, ) -> Result<()> { - images - .chain(&self.render_targets) - .execute(|(images, old_render_target)| { + images.chain_mut_2(&mut self.render_targets).execute_into( + |(images, old_render_target)| { let new_render_target = Self::create_render_target( &self.device, &images, @@ -1653,10 +1665,11 @@ impl<'a> GuiHandler<'a> { self.text_sample_count, )?; - **old_render_target = new_render_target; + *old_render_target = new_render_target; Ok(()) - })?; + }, + )?; self.text_to_screen.update_on_resize(&self.render_targets)?; @@ -1666,9 +1679,11 @@ impl<'a> GuiHandler<'a> { self.width = width; self.height = height; + let callback_self = unsafe { remove_life_time_mut(self) }; + for (_, elements) in self.layers.iter() { for framable in elements.iter_framables() { - framable.resize(self)?; + framable.resize(callback_self)?; } } diff --git a/src/prelude.rs b/src/prelude.rs index 7a300ae..fcc0468 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,5 @@ 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::element_creator::*; pub use super::elements::prelude::*;