236 lines
7.3 KiB
Rust
236 lines
7.3 KiB
Rust
use crate::prelude::*;
|
|
use anyhow::Result;
|
|
use utilities::prelude::*;
|
|
|
|
use assetpath::AssetPath;
|
|
|
|
use super::gridinfo::GridInfo;
|
|
use super::mandatory::Mandatory;
|
|
|
|
use std::convert::TryFrom;
|
|
use std::str::from_utf8;
|
|
use std::sync::{Arc, RwLock, Weak};
|
|
|
|
use super::validator::{
|
|
cow_to_button_select_mode, cow_to_fill_type, cow_to_path, cow_to_str, cow_to_text_alignment,
|
|
str_into,
|
|
};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum NeighbourDirection {
|
|
East,
|
|
West,
|
|
North,
|
|
South,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct NeighbourInfo {
|
|
pub direction: NeighbourDirection,
|
|
pub id: String,
|
|
}
|
|
|
|
pub struct ButtonInfo {
|
|
// global unique id, if set
|
|
pub id: String,
|
|
|
|
// slots inside grid
|
|
pub x_slot: Mandatory<usize>,
|
|
pub y_slot: Mandatory<usize>,
|
|
|
|
pub x_dim: u32,
|
|
pub y_dim: u32,
|
|
|
|
// texturing
|
|
pub normal: Option<FillTypeInfo>,
|
|
pub selected: Option<FillTypeInfo>,
|
|
|
|
pub click_sound: AssetPath,
|
|
pub hover_sound: AssetPath,
|
|
|
|
pub text: RwLock<String>,
|
|
pub text_color: Color,
|
|
pub text_ratio: Option<f32>,
|
|
pub text_alignment: TextAlignment,
|
|
|
|
pub icon: Option<String>,
|
|
pub margin: u32,
|
|
|
|
pub select_mode: ButtonSelectMode,
|
|
|
|
pub neighbour_infos: Vec<NeighbourInfo>,
|
|
|
|
// the chosen element for controller input
|
|
pub select: bool,
|
|
|
|
pub parent: Weak<GridInfo>,
|
|
}
|
|
|
|
impl ButtonInfo {
|
|
pub fn new<'a>(
|
|
gui_handler: &Arc<GuiHandler>,
|
|
attributes: quick_xml::events::attributes::Attributes<'a>,
|
|
grid: &Arc<GridInfo>,
|
|
) -> Result<ButtonInfo> {
|
|
let mut button_info = ButtonInfo {
|
|
id: String::new(),
|
|
|
|
x_slot: Mandatory::default(),
|
|
y_slot: Mandatory::default(),
|
|
|
|
x_dim: 1,
|
|
y_dim: 1,
|
|
|
|
normal: Self::find_menu_button(grid),
|
|
selected: Self::find_menu_button_selected(grid),
|
|
|
|
click_sound: match Self::find_click_sound(grid) {
|
|
Some(sound) => sound,
|
|
None => gui_handler.click_sound().clone(),
|
|
},
|
|
|
|
hover_sound: match Self::find_hover_sound(grid) {
|
|
Some(sound) => sound,
|
|
None => gui_handler.hover_sound().clone(),
|
|
},
|
|
|
|
text: RwLock::default(),
|
|
text_color: Color::Black,
|
|
text_ratio: None,
|
|
text_alignment: TextAlignment::Center,
|
|
|
|
icon: None,
|
|
margin: 0,
|
|
|
|
select_mode: ButtonSelectMode::Bigger,
|
|
|
|
neighbour_infos: Vec::new(),
|
|
|
|
select: false,
|
|
|
|
parent: Arc::downgrade(grid),
|
|
};
|
|
|
|
for attribute_res in attributes {
|
|
let attribute = attribute_res?;
|
|
|
|
match attribute.key.into_inner() {
|
|
b"id" => button_info.id = cow_to_str(attribute.value),
|
|
b"x_slot" => button_info.x_slot.set(str_into(attribute.value)?),
|
|
b"y_slot" => button_info.y_slot.set(str_into(attribute.value)?),
|
|
b"x_size" => button_info.x_dim = str_into(attribute.value)?,
|
|
b"y_size" => button_info.y_dim = str_into(attribute.value)?,
|
|
b"normal" => button_info.normal = Some(cow_to_fill_type(attribute.value)),
|
|
b"selected" => button_info.selected = Some(cow_to_fill_type(attribute.value)),
|
|
b"click_sound" => button_info.click_sound = cow_to_path(attribute.value),
|
|
b"hover_sound" => button_info.hover_sound = cow_to_path(attribute.value),
|
|
b"select_mode" => {
|
|
button_info.select_mode = cow_to_button_select_mode(attribute.value)?
|
|
}
|
|
b"icon" => button_info.icon = Some(cow_to_str(attribute.value)),
|
|
b"icon_margin" => button_info.margin = str_into(attribute.value)?,
|
|
b"text_color" => {
|
|
button_info.text_color = Color::try_from(cow_to_str(attribute.value).as_str())?
|
|
}
|
|
b"text_ratio" => button_info.text_ratio = Some(str_into(attribute.value)?),
|
|
b"text_alignment" => {
|
|
button_info.text_alignment = cow_to_text_alignment(attribute.value)?
|
|
}
|
|
b"select" => button_info.select = str_into(attribute.value)?,
|
|
b"west_neighbour" => {
|
|
button_info.add_neighbour(NeighbourDirection::West, cow_to_str(attribute.value))
|
|
}
|
|
b"east_neighbour" => {
|
|
button_info.add_neighbour(NeighbourDirection::East, cow_to_str(attribute.value))
|
|
}
|
|
b"north_neighbour" => button_info
|
|
.add_neighbour(NeighbourDirection::North, cow_to_str(attribute.value)),
|
|
b"south_neighbour" => button_info
|
|
.add_neighbour(NeighbourDirection::South, cow_to_str(attribute.value)),
|
|
_ => {
|
|
return Err(anyhow::Error::msg(format!(
|
|
"Unsupported attribute in Button: {}",
|
|
from_utf8(attribute.key.into_inner())?
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(button_info)
|
|
}
|
|
|
|
fn add_neighbour(&mut self, direction: NeighbourDirection, id: String) {
|
|
match self
|
|
.neighbour_infos
|
|
.iter_mut()
|
|
.find(|info| info.direction == direction)
|
|
{
|
|
Some(info) => info.id = id,
|
|
None => self.neighbour_infos.push(NeighbourInfo { direction, id }),
|
|
}
|
|
}
|
|
|
|
fn find_menu_button(grid: &GridInfo) -> Option<FillTypeInfo> {
|
|
// return immediately if present
|
|
if let Some(menu_button) = &grid.button_normal {
|
|
return Some(menu_button.clone());
|
|
}
|
|
|
|
// check for parent
|
|
if let Some(weak_parent) = &grid.parent {
|
|
if let Some(parent) = weak_parent.upgrade() {
|
|
return Self::find_menu_button(&parent);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn find_menu_button_selected(grid: &GridInfo) -> Option<FillTypeInfo> {
|
|
// return immediately if present
|
|
if let Some(menu_button_selected) = &grid.button_selected {
|
|
return Some(menu_button_selected.clone());
|
|
}
|
|
|
|
// check for parent
|
|
if let Some(weak_parent) = &grid.parent {
|
|
if let Some(parent) = weak_parent.upgrade() {
|
|
return Self::find_menu_button_selected(&parent);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn find_click_sound(grid: &GridInfo) -> Option<AssetPath> {
|
|
// return immediately if present
|
|
if let Some(click_sound) = &grid.click_sound {
|
|
return Some(click_sound.clone());
|
|
}
|
|
|
|
// check for parent
|
|
if let Some(weak_parent) = &grid.parent {
|
|
if let Some(parent) = weak_parent.upgrade() {
|
|
return Self::find_click_sound(&parent);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn find_hover_sound(grid: &GridInfo) -> Option<AssetPath> {
|
|
// return immediately if present
|
|
if let Some(hover_sound) = &grid.hover_sound {
|
|
return Some(hover_sound.clone());
|
|
}
|
|
|
|
// check for parent
|
|
if let Some(weak_parent) = &grid.parent {
|
|
if let Some(parent) = weak_parent.upgrade() {
|
|
return Self::find_hover_sound(&parent);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|