use std::{collections::HashMap, rc::Rc}; use wgui::{ components::button::ComponentButton, event::CallbackDataCommon, layout::WidgetID, parser::Fetchable, renderer_vk::text::custom_glyph::CustomGlyphData, widget::sprite::WidgetSprite, }; use crate::{ backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, state::LeftRight, windowing::window::Positioning, }; static POS_NAMES: [&str; 6] = ["static", "anchored", "floating", "hmd", "hand_l", "hand_r"]; struct PosButtonState { name: &'static str, sprite: CustomGlyphData, component: Rc, positioning: Positioning, } #[derive(Default)] pub(super) struct PositioningHandler { top_sprite_id: WidgetID, buttons: HashMap<&'static str, Rc>, active_button: Option>, } impl PositioningHandler { pub fn new(panel: &mut EditModeWrapPanel) -> anyhow::Result { let mut buttons = HashMap::new(); for name in &POS_NAMES { let button_id = format!("pos_{name}"); let component = panel.parser_state.fetch_component_as(&button_id)?; let sprite_id = format!("{button_id}_sprite"); let id = panel.parser_state.get_widget_id(&sprite_id)?; let sprite_w = panel .layout .state .widgets .get_as::(id) .ok_or_else(|| { anyhow::anyhow!("Element with id=\"{sprite_id}\" must be a ") })?; let sprite = sprite_w.params.glyph_data.clone().ok_or_else(|| { anyhow::anyhow!("Element with id=\"{sprite_id}\" must have a valid src!") })?; buttons.insert( *name, Rc::new(PosButtonState { component, name, sprite, positioning: key_to_pos(name), }), ); } let top_sprite_id = panel.parser_state.get_widget_id("top_pos_sprite")?; Ok(Self { buttons, active_button: None, top_sprite_id, }) } fn change_highlight(&mut self, common: &mut CallbackDataCommon, key: &str) { if let Some(old) = self.active_button.take() { old.component.set_sticky_state(common, false); } let new = self.buttons.get_mut(key).unwrap(); new.component.set_sticky_state(common, true); self.active_button = Some(new.clone()); // change top sprite if let Some(mut sprite) = common .state .widgets .get_as::(self.top_sprite_id) { sprite.params.glyph_data = Some(new.sprite.clone()); } } pub fn pos_button_clicked( &mut self, common: &mut CallbackDataCommon, key: &str, ) -> Box { self.change_highlight(common, key); let pos = key_to_pos(key); Box::new(move |app, owc| { let state = owc.active_state.as_mut().unwrap(); //want panic state.positioning = pos; state.save_transform(app); }) } pub fn reset(&mut self, common: &mut CallbackDataCommon, pos: Positioning) { let key = pos_to_key(pos); self.change_highlight(common, key); } } fn key_to_pos(key: &str) -> Positioning { match key { "static" => Positioning::Static, "anchored" => Positioning::Anchored, "floating" => Positioning::Floating, "hmd" => Positioning::FollowHead { lerp: 1.0 }, "hand_l" => Positioning::FollowHand { hand: LeftRight::Left, lerp: 1.0, }, "hand_r" => Positioning::FollowHand { hand: LeftRight::Right, lerp: 1.0, }, _ => { panic!("cannot translate to positioning: {key}") } } } const fn pos_to_key(pos: Positioning) -> &'static str { match pos { Positioning::Static => "static", Positioning::Anchored => "anchored", Positioning::Floating => "floating", Positioning::FollowHead { .. } | Positioning::FollowHeadPaused { .. } => "hmd", Positioning::FollowHand { hand: LeftRight::Left, .. } | Positioning::FollowHandPaused { hand: LeftRight::Left, .. } => "hand_l", Positioning::FollowHand { hand: LeftRight::Right, .. } | Positioning::FollowHandPaused { hand: LeftRight::Right, .. } => "hand_r", } }