mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-17 15:06:23 +00:00
ui
This commit is contained in:
@@ -6,13 +6,16 @@ pub enum UiTag {
|
|||||||
Menu(UiMenu),
|
Menu(UiMenu),
|
||||||
Image(UiImage),
|
Image(UiImage),
|
||||||
TextButton(UiTextButton),
|
TextButton(UiTextButton),
|
||||||
|
TextArea(UiTextArea),
|
||||||
|
StaticText(UiStaticText),
|
||||||
|
ToggleButton(UiToggleButton),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct UiMenu {
|
pub struct UiMenu {
|
||||||
pub selected: String,
|
pub selected: String,
|
||||||
#[serde(rename = "OnBack")]
|
#[serde(rename = "OnBack")]
|
||||||
pub on_back: String,
|
pub on_back: Option<String>,
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub children: Vec<UiTag>,
|
pub children: Vec<UiTag>,
|
||||||
}
|
}
|
||||||
@@ -42,10 +45,59 @@ pub struct UiTextButton {
|
|||||||
pub on_select: String,
|
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)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum HorizontalAlign {
|
pub enum HorizontalAlign {
|
||||||
|
Left,
|
||||||
Center,
|
Center,
|
||||||
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|||||||
@@ -178,9 +178,9 @@ impl ResourceFormatLoaderVirtual for DatafileLoader {
|
|||||||
game_object.to_variant()
|
game_object.to_variant()
|
||||||
}
|
}
|
||||||
Ok(DatafileFile::Ui(ui)) => {
|
Ok(DatafileFile::Ui(ui)) => {
|
||||||
let ui = convert_ui(ui);
|
let ui = convert_ui(ui, None);
|
||||||
let mut scene = PackedScene::new();
|
let mut scene = PackedScene::new();
|
||||||
scene.pack(ui.upcast());
|
scene.pack(ui);
|
||||||
|
|
||||||
self.save_to_cache(scene.share().upcast(), format!("{}.scn", datafile_path));
|
self.save_to_cache(scene.share().upcast(), format!("{}.scn", datafile_path));
|
||||||
scene.to_variant()
|
scene.to_variant()
|
||||||
|
|||||||
@@ -1,25 +1,30 @@
|
|||||||
use crate::formats::ui_xml::{HorizontalAlign, UiTag};
|
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::global::HorizontalAlignment;
|
||||||
use godot::engine::node::InternalMode;
|
use godot::engine::node::InternalMode;
|
||||||
use godot::engine::{Button, Container, Control, TextureRect};
|
use godot::engine::{Button, Control, Node, TextureRect};
|
||||||
use godot::prelude::*;
|
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 {
|
match ui {
|
||||||
UiTag::Menu(menu) => {
|
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 {
|
for child in menu.children {
|
||||||
gd_menu.add_child(
|
let mut child = convert_ui(child, Some(owner_node.share()));
|
||||||
convert_ui(child).upcast(),
|
gd_menu.add_child(child.share(), false, InternalMode::INTERNAL_MODE_FRONT);
|
||||||
false,
|
child.set_owner(owner_node.share());
|
||||||
InternalMode::INTERNAL_MODE_FRONT,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
gd_menu.upcast()
|
gd_menu.upcast()
|
||||||
}
|
}
|
||||||
UiTag::Image(image) => {
|
UiTag::Image(image) => {
|
||||||
let mut gd_image = TextureRect::new_alloc();
|
let mut gd_image = TextureRect::new_alloc();
|
||||||
|
gd_image.set_name(image.texture.into());
|
||||||
gd_image.set_position(
|
gd_image.set_position(
|
||||||
Vector2 {
|
Vector2 {
|
||||||
x: image.position[0] as f32,
|
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_name(GodotString::from(name));
|
||||||
}
|
}
|
||||||
gd_button.set_text(GodotString::from(button.text));
|
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()
|
gd_button.upcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user