1use std::cell::{Cell, OnceCell};
6use std::iter;
7
8use crate::TransformComponent;
9use crate::bones::Tendon;
10use crate::bones::skinnable::{self, Skinnable};
11use crate::component::Component;
12use crate::component_dirt::ComponentDirt;
13use crate::container_component::ContainerComponent;
14use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property};
15use crate::dyn_vec::DynVec;
16use crate::math::Mat;
17use crate::option_cell::OptionCell;
18use crate::shapes::PathVertex;
19use crate::status_code::StatusCode;
20
21#[derive(Debug)]
22pub struct Skin {
23 container_component: ContainerComponent,
24 xx: Property<f32>,
25 yx: Property<f32>,
26 xy: Property<f32>,
27 yy: Property<f32>,
28 tx: Property<f32>,
29 ty: Property<f32>,
30 world_transform: Cell<Mat>,
31 tendons: DynVec<Object<Tendon>>,
32 bone_transforms: OnceCell<Box<[Cell<Mat>]>>,
33 skinnable: OptionCell<Object>,
34}
35
36impl ObjectRef<'_, Skin> {
37 pub fn xx(&self) -> f32 {
38 self.xx.get()
39 }
40
41 pub fn set_xx(&self, xx: f32) {
42 self.xx.set(xx);
43 }
44
45 pub fn yx(&self) -> f32 {
46 self.yx.get()
47 }
48
49 pub fn set_yx(&self, yx: f32) {
50 self.yx.set(yx);
51 }
52
53 pub fn xy(&self) -> f32 {
54 self.xy.get()
55 }
56
57 pub fn set_xy(&self, xy: f32) {
58 self.xy.set(xy);
59 }
60
61 pub fn yy(&self) -> f32 {
62 self.yy.get()
63 }
64
65 pub fn set_yy(&self, yy: f32) {
66 self.yy.set(yy);
67 }
68
69 pub fn tx(&self) -> f32 {
70 self.tx.get()
71 }
72
73 pub fn set_tx(&self, tx: f32) {
74 self.tx.set(tx);
75 }
76
77 pub fn ty(&self) -> f32 {
78 self.ty.get()
79 }
80
81 pub fn set_ty(&self, ty: f32) {
82 self.ty.set(ty);
83 }
84}
85
86impl ObjectRef<'_, Skin> {
87 pub fn push_tendon(&self, tendon: Object<Tendon>) {
88 self.tendons.push(tendon);
89 }
90
91 pub fn deform(&self, vertices: impl Iterator<Item = Object<PathVertex>>) {
92 let bone_transforms =
93 self.bone_transforms.get().expect("bone_transforms should already be set");
94 for vertex in vertices {
95 vertex.as_ref().deform(self.world_transform.get(), bone_transforms);
96 }
97 }
98
99 pub fn build_dependencies(&self) {
100 for tendon in self.tendons.iter() {
101 let tendon = tendon.as_ref();
102 let bone = tendon.bone().expect("Tendon's bone must be set");
103 bone.as_ref().cast::<Component>().push_dependent(self.cast::<Component>().as_object());
104 }
105
106 self.bone_transforms
107 .set(iter::repeat(Cell::new(Mat::default())).take(self.tendons.len() + 1).collect())
108 .expect("bone_transform has been set twice");
109 }
110
111 pub fn on_dirty(&self, _dirt: ComponentDirt) {
112 let skinnable = self.skinnable.get().expect("Skinnable should already be set");
113 skinnable::as_ref(skinnable.as_ref()).mark_skin_dirty();
114 }
115
116 pub fn update(&self, _value: ComponentDirt) {
117 if let Some(bone_transforms) = self.bone_transforms.get() {
118 for (bone_transform, tendon) in bone_transforms.iter().skip(1).zip(self.tendons.iter())
119 {
120 let tendon = tendon.as_ref();
121 let bone =
122 tendon.bone().expect("Tendon's bone must be set").cast::<TransformComponent>();
123 bone_transform.set(bone.as_ref().world_transform() * tendon.inverse_bind());
124 }
125 }
126 }
127}
128
129impl Core for Skin {
130 parent_types![(container_component, ContainerComponent)];
131
132 properties![
133 (104, xx, set_xx),
134 (105, yx, set_yx),
135 (106, xy, set_xy),
136 (107, yy, set_yy),
137 (108, tx, set_tx),
138 (109, ty, set_ty),
139 container_component,
140 ];
141}
142
143impl OnAdded for ObjectRef<'_, Skin> {
144 on_added!([on_added_dirty, import], ContainerComponent);
145
146 fn on_added_clean(&self, _context: &dyn CoreContext) -> StatusCode {
147 self.world_transform.set(Mat {
148 scale_x: self.xx(),
149 shear_y: self.xy(),
150 shear_x: self.yx(),
151 scale_y: self.yy(),
152 translate_x: self.tx(),
153 translate_y: self.ty(),
154 });
155
156 self.skinnable.set(
157 self.cast::<Component>().parent().and_then(|parent| skinnable::try_from(parent.into())),
158 );
159 if let Some(skinnable) = self.skinnable.get() {
160 skinnable::as_ref(skinnable.as_ref()).set_skin(self.as_object());
161 } else {
162 return StatusCode::MissingObject;
163 }
164
165 StatusCode::Ok
166 }
167}
168
169impl Default for Skin {
170 fn default() -> Self {
171 Self {
172 container_component: ContainerComponent::default(),
173 xx: Property::new(1.0),
174 yx: Property::new(0.0),
175 xy: Property::new(0.0),
176 yy: Property::new(1.0),
177 tx: Property::new(0.0),
178 ty: Property::new(0.0),
179 world_transform: Cell::new(Mat::default()),
180 tendons: DynVec::new(),
181 bone_transforms: OnceCell::new(),
182 skinnable: OptionCell::new(),
183 }
184 }
185}