rive_rs/shapes/
cubic_vertex.rs
1use 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}