rive_rs/bones/
tendon.rs
1use std::cell::Cell;
6
7use crate::bones::{Bone, Skin};
8use crate::component::Component;
9use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property};
10use crate::math::Mat;
11use crate::option_cell::OptionCell;
12use crate::status_code::StatusCode;
13
14#[derive(Debug)]
15pub struct Tendon {
16 component: Component,
17 bone_id: Property<u64>,
18 xx: Property<f32>,
19 yx: Property<f32>,
20 xy: Property<f32>,
21 yy: Property<f32>,
22 tx: Property<f32>,
23 ty: Property<f32>,
24 inverse_bind: Cell<Mat>,
25 bone: OptionCell<Object<Bone>>,
26}
27
28impl ObjectRef<'_, Tendon> {
29 pub fn bone_id(&self) -> u64 {
30 self.bone_id.get()
31 }
32
33 pub fn set_bone_id(&self, bone_id: u64) {
34 self.bone_id.set(bone_id);
35 }
36
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<'_, Tendon> {
87 pub fn inverse_bind(&self) -> Mat {
88 self.inverse_bind.get()
89 }
90
91 pub fn bone(&self) -> Option<Object<Bone>> {
92 self.bone.get()
93 }
94}
95
96impl Core for Tendon {
97 parent_types![(component, Component)];
98
99 properties![
100 (95, bone_id, set_bone_id),
101 (96, xx, set_xx),
102 (97, yx, set_yx),
103 (98, xy, set_xy),
104 (99, yy, set_yy),
105 (100, tx, set_tx),
106 (101, ty, set_ty),
107 component,
108 ];
109}
110
111impl OnAdded for ObjectRef<'_, Tendon> {
112 on_added!([import], Component);
113
114 fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode {
115 let bind = Mat {
116 scale_x: self.xx(),
117 shear_y: self.xy(),
118 shear_x: self.yx(),
119 scale_y: self.yy(),
120 translate_x: self.tx(),
121 translate_y: self.ty(),
122 };
123
124 if let Some(inverse_bind) = bind.invert() {
125 self.inverse_bind.set(inverse_bind);
126 } else {
127 return StatusCode::FailedInversion;
128 }
129
130 let code = self.cast::<Component>().on_added_dirty(context);
131 if code != StatusCode::Ok {
132 return code;
133 }
134
135 if let Some(bone) =
136 context.resolve(self.bone_id() as usize).and_then(|core| core.try_cast())
137 {
138 self.bone.set(Some(bone));
139 StatusCode::Ok
140 } else {
141 StatusCode::MissingObject
142 }
143 }
144
145 fn on_added_clean(&self, _context: &dyn CoreContext) -> StatusCode {
146 if let Some(parent) = self
147 .try_cast::<Component>()
148 .and_then(|component| component.parent())
149 .and_then(|core| core.try_cast::<Skin>())
150 {
151 parent.as_ref().push_tendon(self.as_object());
152 } else {
153 return StatusCode::MissingObject;
154 }
155
156 StatusCode::Ok
157 }
158}
159
160impl Default for Tendon {
161 fn default() -> Self {
162 Self {
163 component: Component::default(),
164 bone_id: Property::new(0),
165 xx: Property::new(1.0),
166 yx: Property::new(0.0),
167 xy: Property::new(0.0),
168 yy: Property::new(1.0),
169 tx: Property::new(0.0),
170 ty: Property::new(0.0),
171 inverse_bind: Cell::new(Mat::default()),
172 bone: OptionCell::new(),
173 }
174 }
175}