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>>
where
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 {
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( ( ( $( [<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)?
.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<Arc<Image>> {
pub(crate) fn displayable_image_from_path(
&mut self,
mut path: AssetPath,
) -> Result<Arc<Image>> {
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<F>(&self, f: F)
pub fn set_on_selected_event<F>(&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<bool> {
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<bool> {
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<bool> {
pub fn remove_char(&mut self) -> Result<bool> {
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<bool> {
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.[<add_ $element>]($element);
}
@ -998,8 +1007,8 @@ macro_rules! add_element {
let mut elements = Elements::default();
elements.[<add_ $element>]($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<Arc<Selectable<'a>>>) -> 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<usize>,
) -> 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<Vec<Arc<Image>>>,
) -> 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)?;
}
}

View file

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