mirror of
https://github.com/Theaninova/mhlib.git
synced 2026-01-21 01:12:58 +00:00
ui
This commit is contained in:
@@ -76,7 +76,10 @@ where
|
||||
"xml" => {
|
||||
serde_xml_rs::from_str::<UiTag>(String::from_utf8(data).map_err(custom_err)?.as_str())
|
||||
.map_err(custom_err)
|
||||
.map(DatafileFile::Ui)
|
||||
.map(|mut it| {
|
||||
it.post_process();
|
||||
DatafileFile::Ui(it)
|
||||
})
|
||||
}
|
||||
"txt" => {
|
||||
let stem = path
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub enum UiTag {
|
||||
Menu(UiMenu),
|
||||
Image(UiImage),
|
||||
@@ -11,7 +11,7 @@ pub enum UiTag {
|
||||
ToggleButton(UiToggleButton),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiMenu {
|
||||
pub selected: String,
|
||||
#[serde(rename = "OnBack")]
|
||||
@@ -20,54 +20,55 @@ pub struct UiMenu {
|
||||
pub children: Vec<UiTag>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiImage {
|
||||
pub texture: String,
|
||||
#[serde(deserialize_with = "deserialize_vec2")]
|
||||
pub position: [i32; 2],
|
||||
#[serde(deserialize_with = "deserialize_vec2")]
|
||||
pub size: [i32; 2],
|
||||
#[serde(rename = "fademode")]
|
||||
#[serde(rename = "fademode", default)]
|
||||
pub fade_mode: FadeMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiTextButton {
|
||||
pub name: Option<String>,
|
||||
pub text: String,
|
||||
#[serde(deserialize_with = "deserialize_vec2")]
|
||||
pub position: [i32; 2],
|
||||
#[serde(rename = "halign")]
|
||||
#[serde(rename = "halign", default)]
|
||||
pub horizontal_align: HorizontalAlign,
|
||||
#[serde(rename = "fademode")]
|
||||
#[serde(rename = "fademode", default)]
|
||||
pub fade_mode: FadeMode,
|
||||
#[serde(rename = "OnSelect")]
|
||||
pub on_select: String,
|
||||
}
|
||||
|
||||
/// This sometimes appears completely empty
|
||||
#[derive(Debug, Deserialize)]
|
||||
/// This is a really weird node, sometimes it has children and sometimes, don't ask me why,
|
||||
/// it appears as a normal tag and then gets closed by an empty tag of this kind.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiTextArea {
|
||||
#[serde(deserialize_with = "deserialize_vec2", default)]
|
||||
pub position: [i32; 2],
|
||||
#[serde(deserialize_with = "deserialize_vec2", default)]
|
||||
pub size: [i32; 2],
|
||||
#[serde(deserialize_with = "deserialize_vec2_opt", default)]
|
||||
pub position: Option<[i32; 2]>,
|
||||
#[serde(deserialize_with = "deserialize_vec2_opt", default)]
|
||||
pub size: Option<[i32; 2]>,
|
||||
#[serde(rename = "$value", default)]
|
||||
pub children: Vec<UiTag>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiStaticText {
|
||||
pub text: String,
|
||||
#[serde(deserialize_with = "deserialize_vec2")]
|
||||
pub position: [i32; 2],
|
||||
#[serde(rename = "halign")]
|
||||
#[serde(rename = "halign", default)]
|
||||
pub horizontal_align: HorizontalAlign,
|
||||
#[serde(rename = "fademode")]
|
||||
#[serde(rename = "fademode", default)]
|
||||
pub fade_mode: FadeMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct UiToggleButton {
|
||||
pub name: Option<String>,
|
||||
pub text: String,
|
||||
@@ -85,15 +86,49 @@ pub struct UiToggleButton {
|
||||
pub target_l_offset: [i32; 2],
|
||||
#[serde(rename = "targetROffset", deserialize_with = "deserialize_vec2")]
|
||||
pub target_r_offset: [i32; 2],
|
||||
#[serde(rename = "noSound")]
|
||||
pub no_sound: Option<bool>,
|
||||
#[serde(rename = "noSound", default)]
|
||||
pub no_sound: bool,
|
||||
#[serde(rename = "OnChange")]
|
||||
pub on_change: String,
|
||||
#[serde(rename = "OnSelect")]
|
||||
pub on_select: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
impl UiTag {
|
||||
pub fn post_process(&mut self) {
|
||||
if let UiTag::Menu(menu) = self {
|
||||
let children: Vec<UiTag> = menu.children.drain(..).collect();
|
||||
let mut area_stack: Vec<Vec<UiTag>> = vec![vec![]];
|
||||
|
||||
for mut child in children {
|
||||
child.post_process();
|
||||
if let UiTag::TextArea(mut area) = child {
|
||||
let children = area_stack.pop().unwrap();
|
||||
let opening_tag = area_stack.last_mut().map(|it| it.last_mut());
|
||||
|
||||
if let Some(Some(UiTag::TextArea(opening_tag))) = opening_tag {
|
||||
opening_tag.children = children;
|
||||
} else {
|
||||
area_stack.push(children);
|
||||
}
|
||||
|
||||
if area.position.is_some() && area.size.is_some() {
|
||||
let children = area.children.drain(..).collect();
|
||||
area_stack.last_mut().unwrap().push(UiTag::TextArea(area));
|
||||
area_stack.push(children);
|
||||
}
|
||||
} else {
|
||||
area_stack.last_mut().unwrap().push(child);
|
||||
}
|
||||
}
|
||||
|
||||
menu.children = area_stack.pop().unwrap();
|
||||
debug_assert!(area_stack.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum HorizontalAlign {
|
||||
Left,
|
||||
@@ -101,17 +136,46 @@ pub enum HorizontalAlign {
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
impl Default for HorizontalAlign {
|
||||
fn default() -> HorizontalAlign {
|
||||
HorizontalAlign::Left
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum FadeMode {
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for FadeMode {
|
||||
fn default() -> Self {
|
||||
FadeMode::None
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_vec2_opt<'de, D>(deserializer: D) -> Result<Option<[i32; 2]>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if let Some(buf) = Option::<String>::deserialize(deserializer)? {
|
||||
to_vec2::<D>(buf).map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_vec2<'de, D>(deserializer: D) -> Result<[i32; 2], D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let buf = String::deserialize(deserializer)?;
|
||||
to_vec2::<D>(String::deserialize(deserializer)?)
|
||||
}
|
||||
|
||||
fn to_vec2<'de, D>(buf: String) -> Result<[i32; 2], D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let mut values: Vec<Result<i32, D::Error>> = buf
|
||||
.split(',')
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user