use godot::{ classes::{ AnimationNodeBlendSpace2D, AnimationPlayer, AnimationTree, ISkeletonModifier3D, Skeleton3D, SkeletonModifier3D, }, prelude::*, }; #[derive(GodotClass)] #[class(base=Node3D, init)] pub struct SoldierMesh { #[export] hand_attachment: Option>, #[export] animation_tree: Option>, #[export] skeleton: Option>, #[export] raygun: Option>, #[export] skeleton_modifier: Option>, base: Base, } #[godot_api] impl INode3D for SoldierMesh { fn ready(&mut self) {} } impl SoldierMesh { pub fn update_movement(&mut self, movement: Vector2) { if let Some(tree) = &mut self.animation_tree { tree.set("parameters/Movement/blend_position", &movement.to_variant()); } } pub fn update_y_look(&mut self, rotation: f32) { if let Some(skeleton) = &mut self.skeleton_modifier { skeleton.bind_mut().rotation = rotation; } } pub fn spawn_raygun(&mut self) { if let Some(raygun) = &self.raygun { let node = raygun.instantiate_as::(); self.spawn_weapon(node); } } fn spawn_weapon(&mut self, node: Gd) { if let Some(hand) = &mut self.hand_attachment { hand.add_child(&node); } } } #[derive(GodotClass)] #[class(base=SkeletonModifier3D, init)] pub struct SoldierSkeletonModifier { pub rotation: f32, base: Base, } #[godot_api] impl ISkeletonModifier3D for SoldierSkeletonModifier { fn process_modification_with_delta(&mut self, _delta: f64) { let rot = self.rotation; let rhand_quat = Quaternion::from_euler(Vector3::FORWARD * -rot); let lhand_quat = Quaternion::from_euler(Vector3::RIGHT * rot); if let Some(skeleton) = &mut self.base_mut().get_skeleton() { let head_idx = skeleton.find_bone("HEAD"); let uar_idx = skeleton.find_bone("UA.R"); let uar_rot = skeleton.get_bone_pose_rotation(uar_idx); let ual_idx = skeleton.find_bone("UA.L"); let ual_rot = skeleton.get_bone_pose_rotation(ual_idx); skeleton.set_bone_pose_rotation(head_idx, Quaternion::from_euler(Vector3::RIGHT * rot)); skeleton.set_bone_pose_rotation(uar_idx, uar_rot * rhand_quat); skeleton.set_bone_pose_rotation(ual_idx, ual_rot * lhand_quat); } } }