rive_rs/bones/
skin.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, 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}