rive_rs/bones/
tendon.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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}