diff --git a/rust/src/formats/ui_xml.rs b/rust/src/formats/ui_xml.rs index 7af13f9..cab9fb7 100644 --- a/rust/src/formats/ui_xml.rs +++ b/rust/src/formats/ui_xml.rs @@ -6,13 +6,16 @@ pub enum UiTag { Menu(UiMenu), Image(UiImage), TextButton(UiTextButton), + TextArea(UiTextArea), + StaticText(UiStaticText), + ToggleButton(UiToggleButton), } #[derive(Debug, Deserialize)] pub struct UiMenu { pub selected: String, #[serde(rename = "OnBack")] - pub on_back: String, + pub on_back: Option, #[serde(rename = "$value")] pub children: Vec, } @@ -42,10 +45,59 @@ pub struct UiTextButton { pub on_select: String, } +#[derive(Debug, Deserialize)] +pub struct UiTextArea { + #[serde(deserialize_with = "deserialize_vec2")] + pub position: [i32; 2], + #[serde(deserialize_with = "deserialize_vec2")] + pub size: [i32; 2], + #[serde(rename = "$value")] + pub children: Vec, +} + +#[derive(Debug, Deserialize)] +pub struct UiStaticText { + pub text: String, + #[serde(deserialize_with = "deserialize_vec2")] + pub position: [i32; 2], + #[serde(rename = "halign")] + pub horizontal_align: HorizontalAlign, + #[serde(rename = "fademode")] + pub fade_mode: FadeMode, +} + +#[derive(Debug, Deserialize)] +pub struct UiToggleButton { + pub name: Option, + pub text: String, + #[serde(deserialize_with = "deserialize_vec2")] + pub position: [i32; 2], + pub value: String, + #[serde(rename = "minValue")] + pub min_value: i32, + #[serde(rename = "maxValue")] + pub max_value: i32, + #[serde(rename = "valueStep")] + pub value_step: i32, + pub target: String, + #[serde(rename = "targetLOffset", deserialize_with = "deserialize_vec2")] + 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, + #[serde(rename = "OnChange")] + pub on_change: String, + #[serde(rename = "OnSelect")] + pub on_select: String, +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "lowercase")] pub enum HorizontalAlign { + Left, Center, + Right, } #[derive(Debug, Deserialize)] diff --git a/rust/src/godot/datafile.rs b/rust/src/godot/datafile.rs index ce07342..820c8b4 100644 --- a/rust/src/godot/datafile.rs +++ b/rust/src/godot/datafile.rs @@ -178,9 +178,9 @@ impl ResourceFormatLoaderVirtual for DatafileLoader { game_object.to_variant() } Ok(DatafileFile::Ui(ui)) => { - let ui = convert_ui(ui); + let ui = convert_ui(ui, None); let mut scene = PackedScene::new(); - scene.pack(ui.upcast()); + scene.pack(ui); self.save_to_cache(scene.share().upcast(), format!("{}.scn", datafile_path)); scene.to_variant() diff --git a/rust/src/godot/ui.rs b/rust/src/godot/ui.rs index 856cc63..3f943f0 100644 --- a/rust/src/godot/ui.rs +++ b/rust/src/godot/ui.rs @@ -1,25 +1,30 @@ use crate::formats::ui_xml::{HorizontalAlign, UiTag}; -use godot::builtin::{GodotString, Vector2}; +use godot::builtin::{Array, Dictionary, GodotString, Signal, ToVariant, Vector2}; use godot::engine::global::HorizontalAlignment; use godot::engine::node::InternalMode; -use godot::engine::{Button, Container, Control, TextureRect}; -use godot::prelude::*; +use godot::engine::{Button, Control, Node, TextureRect}; +use godot::obj::{Gd, Share}; +use godot::sys::GDEXTENSION_VARIANT_TYPE_STRING; +use itertools::Itertools; -pub fn convert_ui(ui: UiTag) -> Gd { +const ACTION_META_NAME: &str = "action"; + +pub fn convert_ui(ui: UiTag, owner: Option>) -> Gd { match ui { UiTag::Menu(menu) => { - let mut gd_menu = Container::new_alloc(); + let mut gd_menu = Control::new_alloc(); + let owner_node = owner.unwrap_or_else(|| gd_menu.share().upcast()); + for child in menu.children { - gd_menu.add_child( - convert_ui(child).upcast(), - false, - InternalMode::INTERNAL_MODE_FRONT, - ); + let mut child = convert_ui(child, Some(owner_node.share())); + gd_menu.add_child(child.share(), false, InternalMode::INTERNAL_MODE_FRONT); + child.set_owner(owner_node.share()); } gd_menu.upcast() } UiTag::Image(image) => { let mut gd_image = TextureRect::new_alloc(); + gd_image.set_name(image.texture.into()); gd_image.set_position( Vector2 { x: image.position[0] as f32, @@ -52,6 +57,28 @@ pub fn convert_ui(ui: UiTag) -> Gd { gd_button.set_name(GodotString::from(name)); } gd_button.set_text(GodotString::from(button.text)); + + let mut call = button.on_select.split_whitespace().collect_vec(); + if let Some((name,)) = call.drain(..1).collect_tuple() { + gd_button.set_meta( + ACTION_META_NAME.into(), + Dictionary::from([ + (&"name".to_variant(), &name.to_variant()), + ( + &"args".to_variant(), + &Array::from( + call.into_iter() + .map(GodotString::from) + .collect::>() + .as_slice(), + ) + .to_variant(), + ), + ]) + .to_variant(), + ); + } + gd_button.upcast() } }