mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-12 12:36:17 +00:00
ui
This commit is contained in:
@@ -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<String>,
|
||||
#[serde(rename = "$value")]
|
||||
pub children: Vec<UiTag>,
|
||||
}
|
||||
@@ -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<UiTag>,
|
||||
}
|
||||
|
||||
#[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<String>,
|
||||
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<bool>,
|
||||
#[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)]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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<Control> {
|
||||
const ACTION_META_NAME: &str = "action";
|
||||
|
||||
pub fn convert_ui(ui: UiTag, owner: Option<Gd<Node>>) -> Gd<Node> {
|
||||
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<Control> {
|
||||
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::<Vec<GodotString>>()
|
||||
.as_slice(),
|
||||
)
|
||||
.to_variant(),
|
||||
),
|
||||
])
|
||||
.to_variant(),
|
||||
);
|
||||
}
|
||||
|
||||
gd_button.upcast()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user