use crate::prelude::*; use anyhow::{bail, Context, Result}; use assetpath::AssetPath; use super::validator::buttoninfo::{NeighbourDirection, NeighbourInfo}; use super::validator::gridinfo::GridInfo; use super::validator::uiinfoelement::UiInfoElement; use super::validator::validator::{handle_function_suffix, Validator}; use std::any::Any; use std::collections::HashMap; use std::sync::{Arc, RwLock}; pub struct GuiBuilder { grids: Vec>, default_select: Option>, ids: HashMap, decline_callback: RwLock Result<()> + Send + Sync>>>, } impl GuiBuilder { pub fn new(gui_handler: &Arc, path: &AssetPath) -> Result> { let validator = Validator::new( #[cfg(feature = "audio")] gui_handler, path, ) .with_context(|| format!("validator for {}", path.full_path()))?; Ok(Arc::new(Self::_new(gui_handler, validator).with_context( || format!("for file {}", path.full_path()), )?)) } pub fn from_str(gui_handler: &Arc, s: &str) -> Result> { let validator = Validator::from_str( #[cfg(feature = "audio")] gui_handler, s, )?; Ok(Arc::new(Self::_new(gui_handler, validator)?)) } pub fn merge<'a>( gui_handler: &Arc, pathes: impl IntoIterator, ) -> Result> { let mut me = Self { grids: Default::default(), default_select: Default::default(), ids: Default::default(), decline_callback: Default::default(), }; for path in pathes.into_iter() { let validator = Validator::new( #[cfg(feature = "audio")] gui_handler, path, )?; let builder = Self::_new(gui_handler, validator) .with_context(|| format!("for file {}", path.full_path()))?; me.grids.extend(builder.grids); if me.default_select.is_some() && builder.default_select.is_some() { bail!("multiple default selects are not supported!"); } if builder.default_select.is_some() { me.default_select = builder.default_select; } me.ids.extend(builder.ids); } Ok(Arc::new(me)) } #[inline] fn _new(gui_handler: &Arc, validator: Validator) -> Result { let root = validator.root(); let mut ids = HashMap::new(); let mut opt_default_select = None; let mut custom_neighbours = Vec::new(); let mut grids = Vec::new(); for child in &root.children { let tree = Self::create_tree( gui_handler, &mut ids, child, &mut opt_default_select, &mut custom_neighbours, validator.dimensions(), validator.layer().unwrap_or(5), )?; grids.push(tree); } Self::connect_custom_neighbours(&ids, custom_neighbours)?; Ok(GuiBuilder { grids, default_select: opt_default_select, ids, decline_callback: RwLock::new(None), }) } pub(crate) fn connect_custom_neighbours( ids: &HashMap, neighbour_infos: Vec<(String, Vec)>, ) -> Result<()> { for (id, neighbour_infos) in neighbour_infos.iter() { let button: Arc