use godot::{
classes::{
AnimationPlayer, Label, Node, Node2D, Node3D, Sprite2D,
class_macros::private::virtuals::Os::{Color, Transform2D, Transform3D, Vector2},
},
obj::{GdMut, WithBaseField},
prelude::{Basis, EulerOrder, Gd, Vector3},
};
impl From<&crate::view::Transform2D> for Transform2D {
fn from(v: &crate::view::Transform2D) -> Self {
Self::from_angle_scale_skew_origin(
v.rotation,
Vector2::from(&v.scale),
v.skew,
Vector2::from(&v.position),
)
}
}
impl From<&crate::view::Vec2> for Vector2 {
fn from(v: &crate::view::Vec2) -> Self {
Self::new(v.x, v.y)
}
}
fn set_transform_2d(
_world: &crate::godot::nodes::SiloWorld,
s: GdMut<crate::godot::nodes::SiloVariant>,
v: &crate::view::Transform2D,
) {
if let Some(p) = s.base().get_parent() {
if let Ok(mut p) = p.try_cast::<Node2D>() {
p.set_transform(Transform2D::from(v));
}
}
}
impl From<&crate::view::Vec3> for Vector3 {
fn from(v: &crate::view::Vec3) -> Self {
Self::new(v.x, v.y, v.z)
}
}
impl From<&crate::view::Transform3D> for Transform3D {
fn from(v: &crate::view::Transform3D) -> Self {
let basis = Basis::from_euler(EulerOrder::XYZ, Vector3::from(&v.rotation));
let scaled_basis = basis.scaled(Vector3::from(&v.scale));
Self::new(scaled_basis, Vector3::from(&v.position))
}
}
fn set_transform_3d(
_world: &crate::godot::nodes::SiloWorld,
s: GdMut<crate::godot::nodes::SiloVariant>,
v: &crate::view::Transform3D,
) {
if let Some(p) = s.base().get_parent() {
if let Ok(mut p) = p.try_cast::<Node3D>() {
p.set_transform(Transform3D::from(v));
}
}
}
impl From<&crate::view::Color> for Color {
fn from(v: &crate::view::Color) -> Self {
Self::from_rgba(v.r, v.g, v.b, v.a)
}
}
fn set_color(
_world: &crate::godot::nodes::SiloWorld,
s: GdMut<crate::godot::nodes::SiloVariant>,
v: &crate::view::Color,
) {
if let Some(p) = s.base().get_parent() {
if let Ok(mut p) = p.try_cast::<Sprite2D>() {
p.set_modulate(Color::from(v));
}
}
}
fn set_skin_str(
world: &crate::godot::nodes::SiloWorld,
mut s: Gd<Node>,
skin: &str,
) -> Option<Gd<Node>> {
if let Some(v) = s.find_child(skin) {
return Some(v);
} else {
if let Some(skin_scene) = world.get_skin(&skin.to_string()) {
let mut v = skin_scene
.instantiate()
.expect("Failed to instantiate skin");
v.set_name(skin);
s.add_child(&v);
return Some(v);
}
}
None
}
fn set_text(
world: &crate::godot::nodes::SiloWorld,
s: GdMut<crate::godot::nodes::SiloVariant>,
v: &crate::view::Text,
) {
if let Some(p) = s.base().get_parent() {
if let Some(skin) = &v.skin {
if let Some(node) = set_skin_str(world, p.clone(), skin) {
if let Ok(mut label) = node.try_cast::<Label>() {
label.set_text(&v.text);
}
}
} else if let Ok(mut label) = p.try_cast::<Label>() {
label.set_text(&v.text);
}
}
}
fn find_child<T>(node: &Gd<Node>) -> Option<Gd<T>>
where
T: godot::prelude::GodotClass + godot::prelude::Inherits<godot::prelude::Node>,
{
for child in node.get_children().iter_shared() {
if let Ok(found) = child.try_cast::<T>() {
return Some(found);
}
}
None
}
fn set_skin(
world: &crate::godot::nodes::SiloWorld,
s: GdMut<crate::godot::nodes::SiloVariant>,
v: &crate::view::Skin,
) {
if let Some(p) = s.base().get_parent() {
if let Some(node) = set_skin_str(world, p.clone(), &v.skin) {
if let Some(s) = &v.state {
if let Some(mut ap_node) = find_child::<AnimationPlayer>(&node) {
ap_node.set_current_animation(s);
ap_node.play();
}
}
}
}
}
pub fn initialize() {
crate::godot::reg::add_variant::<crate::view::Transform2D>(set_transform_2d);
crate::godot::reg::add_variant::<crate::view::Transform3D>(set_transform_3d);
crate::godot::reg::add_variant::<crate::view::Color>(set_color);
crate::godot::reg::add_variant::<crate::view::Text>(set_text);
crate::godot::reg::add_variant::<crate::view::Skin>(set_skin);
}