rive_rs/bones/
weight.rs
1use std::cell::Cell;
6
7use crate::component::Component;
8use crate::core::{Core, CoreContext, ObjectRef, OnAdded, Property};
9use crate::math::{self, Mat};
10use crate::shapes::PathVertex;
11use crate::status_code::StatusCode;
12
13#[derive(Debug)]
14pub struct Weight {
15 component: Component,
16 values: Property<u64>,
17 indices: Property<u64>,
18 translation: Cell<math::Vec>,
19}
20
21impl ObjectRef<'_, Weight> {
22 pub fn values(&self) -> u64 {
23 self.values.get()
24 }
25
26 pub fn set_values(&self, values: u64) {
27 self.values.set(values);
28 }
29
30 pub fn indices(&self) -> u64 {
31 self.indices.get()
32 }
33
34 pub fn set_indices(&self, indices: u64) {
35 self.indices.set(indices);
36 }
37}
38
39impl ObjectRef<'_, Weight> {
40 pub fn translation(&self) -> math::Vec {
41 self.translation.get()
42 }
43
44 pub fn set_translation(&self, translation: math::Vec) {
45 self.translation.set(translation);
46 }
47}
48
49impl Weight {
50 pub fn deform(
51 x: f32,
52 y: f32,
53 indices: usize,
54 weights: usize,
55 world: Mat,
56 bone_transforms: &[Cell<Mat>],
57 ) -> math::Vec {
58 let mut deformation = Mat::zero();
59 let r = world * math::Vec::new(x, y);
60
61 let encoded_weight_value = |index, data| (data >> (index * 8)) & 0xFF;
62
63 for i in 0usize..4 {
64 let weight = encoded_weight_value(i, weights);
65 if weight == 0 {
66 continue;
67 }
68
69 let normalized_weight = weight as f32 / 255.0;
70 let index = encoded_weight_value(i, indices);
71
72 let transform = bone_transforms[index].get();
73
74 deformation.scale_x += transform.scale_x * normalized_weight;
75 deformation.shear_y += transform.shear_y * normalized_weight;
76 deformation.shear_x += transform.shear_x * normalized_weight;
77 deformation.scale_y += transform.scale_y * normalized_weight;
78 deformation.translate_x += transform.translate_x * normalized_weight;
79 deformation.translate_y += transform.translate_y * normalized_weight;
80 }
81
82 deformation * r
83 }
84}
85
86impl Core for Weight {
87 parent_types![(component, Component)];
88
89 properties![(102, values, set_values), (103, indices, set_indices), component];
90}
91
92impl OnAdded for ObjectRef<'_, Weight> {
93 on_added!([on_added_clean, import], Component);
94
95 fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode {
96 let component = self.cast::<Component>();
97
98 let code = component.on_added_dirty(context);
99 if code != StatusCode::Ok {
100 return code;
101 }
102
103 if let Some(parent) = component.parent().and_then(|core| core.try_cast::<PathVertex>()) {
104 parent.as_ref().set_weight(self.as_object());
105 } else {
106 return StatusCode::MissingObject;
107 }
108
109 StatusCode::Ok
110 }
111}
112
113impl Default for Weight {
114 fn default() -> Self {
115 Self {
116 component: Component::default(),
117 values: Property::new(255),
118 indices: Property::new(1),
119 translation: Cell::new(math::Vec::default()),
120 }
121 }
122}