1pub mod idle;
2
3pub use self::idle::IdleAnimation;
5
6use super::{FigureBoneData, Offsets, Skeleton, TrailSource, make_bone, vek::*};
7use common::comp::{self};
8use core::convert::TryFrom;
9
10pub type Body = comp::ship::Body;
11
12skeleton_impls!(struct ShipSkeleton {
13 + bone0,
14 + bone1,
15 + bone2,
16 + bone3,
17});
18
19impl Skeleton for ShipSkeleton {
20 type Attr = SkeletonAttr;
21 type Body = Body;
22
23 const BONE_COUNT: usize = 4;
24 #[cfg(feature = "use-dyn-lib")]
25 const COMPUTE_FN: &'static [u8] = b"ship_compute_mats\0";
26
27 #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "ship_compute_mats"))]
28 fn compute_matrices_inner(
29 &self,
30 base_mat: Mat4<f32>,
31 buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
32 body: Self::Body,
33 ) -> Offsets {
34 let scale_mat = Mat4::scaling_3d(1.0);
36
37 let attr = SkeletonAttr::from(&body);
38
39 let bone0_mat = base_mat * scale_mat * Mat4::<f32>::from(self.bone0);
40 let bone1_mat = bone0_mat * Mat4::<f32>::from(self.bone1);
41 let bone2_mat = bone0_mat * Mat4::<f32>::from(self.bone2);
42
43 *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
44 make_bone(bone0_mat),
45 make_bone(bone1_mat),
46 make_bone(bone2_mat),
47 make_bone(bone0_mat * Mat4::<f32>::from(self.bone3)),
48 ];
49 Offsets {
50 mount_bone: Transform {
52 position: (base_mat * scale_mat)
53 .mul_point(comp::Body::Ship(body).mount_offset().into_tuple().into()),
54 ..Default::default()
55 },
56 primary_trail_mat: attr
57 .bone1_prop_trail_offset
58 .map(|offset| (bone1_mat, TrailSource::Propeller(offset))),
59 secondary_trail_mat: attr
60 .bone2_prop_trail_offset
61 .map(|offset| (bone2_mat, TrailSource::Propeller(offset))),
62 ..Default::default()
63 }
64 }
65}
66
67pub struct SkeletonAttr {
68 bone0: (f32, f32, f32),
69 bone1: (f32, f32, f32),
70 bone2: (f32, f32, f32),
71 bone3: (f32, f32, f32),
72 bone1_ori: f32,
73 bone2_ori: f32,
74 bone_rotation_rate: f32,
75 bone1_prop_trail_offset: Option<f32>,
76 bone2_prop_trail_offset: Option<f32>,
77}
78
79impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
80 type Error = ();
81
82 fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
83 match body {
84 comp::Body::Ship(body) => Ok(SkeletonAttr::from(body)),
85 _ => Err(()),
86 }
87 }
88}
89
90impl Default for SkeletonAttr {
91 fn default() -> Self {
92 Self {
93 bone0: (0.0, 0.0, 0.0),
94 bone1: (0.0, 0.0, 0.0),
95 bone2: (0.0, 0.0, 0.0),
96 bone3: (0.0, 0.0, 0.0),
97 bone1_ori: 0.0,
98 bone2_ori: 0.0,
99 bone_rotation_rate: 0.0,
100 bone1_prop_trail_offset: None,
101 bone2_prop_trail_offset: None,
102 }
103 }
104}
105
106impl<'a> From<&'a Body> for SkeletonAttr {
107 fn from(body: &'a Body) -> Self {
108 use comp::ship::Body::*;
109 Self {
110 bone0: match body {
111 DefaultAirship => (0.0, 0.0, 0.0),
112 AirBalloon => (0.0, 0.0, 0.0),
113 SailBoat => (0.0, 0.0, 0.0),
114 Galleon => (0.0, 0.0, 0.0),
115 Skiff => (0.0, 0.0, 0.0),
116 Submarine => (0.0, 0.0, 0.0),
117 Carriage => (0.0, 0.0, 0.0),
118 Cart => (0.0, 0.0, 0.0),
119 Volume => (0.0, 0.0, 0.0),
120 },
121 bone1: match body {
122 DefaultAirship => (-13.0, -25.0, 10.0),
123 AirBalloon => (0.0, 0.0, 0.0),
124 SailBoat => (0.0, 0.0, 0.0),
125 Galleon => (0.0, 0.0, 0.0),
126 Skiff => (0.0, 0.0, 0.0),
127 Submarine => (0.0, -15.0, 3.5),
128 Carriage => (0.0, 3.0, 2.0),
129 Cart => (0.0, 1.0, 1.0),
130 Volume => (0.0, 0.0, 0.0),
131 },
132 bone2: match body {
133 DefaultAirship => (13.0, -25.0, 10.0),
134 AirBalloon => (0.0, 0.0, 0.0),
135 SailBoat => (0.0, 0.0, 0.0),
136 Galleon => (0.0, 0.0, 0.0),
137 Skiff => (0.0, 0.0, 0.0),
138 Submarine => (0.0, 0.0, 0.0),
139 Carriage => (0.0, -3.0, 2.0),
140 Cart => (0.0, -2.5, 1.0),
141 Volume => (0.0, 0.0, 0.0),
142 },
143 bone3: match body {
144 DefaultAirship => (0.0, -27.5, 8.5),
145 AirBalloon => (0.0, -9.0, 8.0),
146 SailBoat => (0.0, 0.0, 0.0),
147 Galleon => (0.0, 0.0, 0.0),
148 Skiff => (0.0, 0.0, 0.0),
149 Submarine => (0.0, -18.0, 3.5),
150 Carriage => (0.0, 0.0, 0.0),
151 Cart => (0.0, 0.0, 0.0),
152 Volume => (0.0, 0.0, 0.0),
153 },
154 bone1_ori: match body {
155 Carriage | Cart => std::f32::consts::PI * 0.5,
156 _ => 0.0,
157 },
158 bone2_ori: match body {
159 Carriage | Cart => std::f32::consts::PI * -0.5,
160 _ => 0.0,
161 },
162 bone_rotation_rate: match body {
163 Carriage => 0.25,
164 Cart => 0.4,
165 _ => 0.8,
166 },
167 bone1_prop_trail_offset: match body {
168 DefaultAirship => Some(8.5),
169 Submarine => Some(3.5),
170 _ => None,
171 },
172 bone2_prop_trail_offset: match body {
173 DefaultAirship => Some(8.5),
174 _ => None,
175 },
176 }
177 }
178}