This commit is contained in:
2023-05-06 19:02:24 +02:00
parent d066215cf3
commit 76948c6501
46 changed files with 1031 additions and 85 deletions

View File

@@ -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

View File

@@ -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()