rive_rs/shapes/
cubic_vertex.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::{CubicWeight, Weight};
8use crate::core::{Core, ObjectRef, OnAdded};
9use crate::math::{self, Mat};
10use crate::shapes::{CubicAsymmetricVertex, CubicDetachedVertex, CubicMirroredVertex, PathVertex};
11
12#[derive(Debug, Default)]
13pub struct CubicVertex {
14    path_vertex: PathVertex,
15    in_is_valid: Cell<bool>,
16    out_is_valid: Cell<bool>,
17    in_point: Cell<math::Vec>,
18    out_point: Cell<math::Vec>,
19}
20
21impl ObjectRef<'_, CubicVertex> {
22    pub fn in_point(&self) -> math::Vec {
23        if !self.in_is_valid.get() {
24            self.compute_in();
25            self.in_is_valid.set(true);
26        }
27
28        self.in_point.get()
29    }
30
31    pub fn set_in_point(&self, in_point: math::Vec) {
32        self.in_point.set(in_point);
33        self.in_is_valid.set(true);
34    }
35
36    pub fn out_point(&self) -> math::Vec {
37        if !self.out_is_valid.get() {
38            self.compute_out();
39            self.out_is_valid.set(true);
40        }
41
42        self.out_point.get()
43    }
44
45    pub fn set_out_point(&self, out_point: math::Vec) {
46        self.out_point.set(out_point);
47        self.out_is_valid.set(true);
48    }
49
50    pub fn render_in(&self) -> math::Vec {
51        if let Some(weight) = self.cast::<PathVertex>().weight() {
52            weight.as_ref().cast::<CubicWeight>().in_translation()
53        } else {
54            self.in_point()
55        }
56    }
57
58    pub fn render_out(&self) -> math::Vec {
59        if let Some(weight) = self.cast::<PathVertex>().weight() {
60            weight.as_ref().cast::<CubicWeight>().out_translation()
61        } else {
62            self.out_point()
63        }
64    }
65
66    pub fn compute_in(&self) {
67        if let Some(cubic_asymmetric_vertex) = self.try_cast::<CubicAsymmetricVertex>() {
68            return cubic_asymmetric_vertex.compute_in();
69        }
70
71        if let Some(cubic_detached_vertex) = self.try_cast::<CubicDetachedVertex>() {
72            return cubic_detached_vertex.compute_in();
73        }
74
75        if let Some(cubic_mirrored_vertex) = self.try_cast::<CubicMirroredVertex>() {
76            return cubic_mirrored_vertex.compute_in();
77        }
78
79        unreachable!();
80    }
81
82    pub fn compute_out(&self) {
83        if let Some(cubic_asymmetric_vertex) = self.try_cast::<CubicAsymmetricVertex>() {
84            return cubic_asymmetric_vertex.compute_out();
85        }
86
87        if let Some(cubic_detached_vertex) = self.try_cast::<CubicDetachedVertex>() {
88            return cubic_detached_vertex.compute_out();
89        }
90
91        if let Some(cubic_mirrored_vertex) = self.try_cast::<CubicMirroredVertex>() {
92            return cubic_mirrored_vertex.compute_out();
93        }
94
95        unreachable!();
96    }
97
98    pub fn deform(&self, world_transform: Mat, bone_transforms: &[Cell<Mat>]) {
99        let cubic_weight = self
100            .cast::<PathVertex>()
101            .weight()
102            .expect("CubicVertex must have a CubicWeight")
103            .cast::<CubicWeight>();
104        let cubic_weight = cubic_weight.as_ref();
105
106        let in_point = self.in_point();
107        cubic_weight.set_in_translation(Weight::deform(
108            in_point.x,
109            in_point.y,
110            cubic_weight.in_indices() as usize,
111            cubic_weight.in_values() as usize,
112            world_transform,
113            bone_transforms,
114        ));
115
116        let out_point = self.out_point();
117        cubic_weight.set_out_translation(Weight::deform(
118            out_point.x,
119            out_point.y,
120            cubic_weight.out_indices() as usize,
121            cubic_weight.out_values() as usize,
122            world_transform,
123            bone_transforms,
124        ));
125    }
126
127    pub(crate) fn invalidate_in(&self) {
128        self.in_is_valid.set(false);
129    }
130
131    pub(crate) fn invalidate_out(&self) {
132        self.out_is_valid.set(false);
133    }
134}
135
136impl Core for CubicVertex {
137    parent_types![(path_vertex, PathVertex)];
138
139    properties!(path_vertex);
140}
141
142impl OnAdded for ObjectRef<'_, CubicVertex> {
143    on_added!(PathVertex);
144}