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