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;
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}