rive_rs/shapes/
path_vertex.rs
1use std::cell::Cell;
6
7use crate::bones::Weight;
8use crate::container_component::ContainerComponent;
9use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property};
10use crate::math::{self, Mat};
11use crate::option_cell::OptionCell;
12use crate::shapes::Path;
13use crate::status_code::StatusCode;
14use crate::Component;
15
16use super::CubicVertex;
17
18#[derive(Debug, Default)]
19pub struct PathVertex {
20 container_component: ContainerComponent,
21 x: Property<f32>,
22 y: Property<f32>,
23 weight: OptionCell<Object<Weight>>,
24}
25
26impl ObjectRef<'_, PathVertex> {
27 pub fn x(&self) -> f32 {
28 self.x.get()
29 }
30
31 pub fn set_x(&self, x: f32) {
32 if self.x() == x {
33 return;
34 }
35
36 self.x.set(x);
37
38 self.mark_path_dirty();
39
40 if let Some(cubic_vertex) = self.try_cast::<CubicVertex>() {
41 cubic_vertex.invalidate_in();
42 cubic_vertex.invalidate_out();
43 }
44 }
45
46 pub fn y(&self) -> f32 {
47 self.y.get()
48 }
49
50 pub fn set_y(&self, y: f32) {
51 if self.y() == y {
52 return;
53 }
54
55 self.y.set(y);
56
57 self.mark_path_dirty();
58
59 if let Some(cubic_vertex) = self.try_cast::<CubicVertex>() {
60 cubic_vertex.invalidate_in();
61 cubic_vertex.invalidate_out();
62 }
63 }
64}
65
66impl ObjectRef<'_, PathVertex> {
67 fn parent_path(&self) -> Option<Object<Path>> {
68 self.cast::<Component>().parent().and_then(|parent| parent.try_cast::<Path>())
69 }
70
71 pub(crate) fn mark_path_dirty(&self) {
72 if let Some(path) = self.parent_path() {
73 path.as_ref().mark_path_dirty();
74 }
75 }
76
77 pub fn weight(&self) -> Option<Object<Weight>> {
78 self.weight.get()
79 }
80
81 pub(crate) fn set_weight(&self, weight: Object<Weight>) {
82 self.weight.set(Some(weight));
83 }
84
85 pub fn deform(&self, world_transform: Mat, bone_transforms: &[Cell<Mat>]) {
86 if let Some(weight) = self.weight() {
87 let weight = weight.as_ref();
88 weight.set_translation(Weight::deform(
89 self.x(),
90 self.y(),
91 weight.indices() as usize,
92 weight.values() as usize,
93 world_transform,
94 bone_transforms,
95 ));
96 }
97
98 if let Some(cubic_vertex) = self.try_cast::<CubicVertex>() {
99 cubic_vertex.deform(world_transform, bone_transforms);
100 }
101 }
102
103 pub fn render_translation(&self) -> math::Vec {
104 self.weight()
105 .map(|weight| weight.as_ref().translation())
106 .unwrap_or_else(|| math::Vec::new(self.x(), self.y()))
107 }
108}
109
110impl Core for PathVertex {
111 parent_types![(container_component, ContainerComponent)];
112
113 properties![(24, x, set_x), (25, y, set_y), container_component];
114}
115
116impl OnAdded for ObjectRef<'_, PathVertex> {
117 on_added!([on_added_clean, import], ContainerComponent);
118
119 fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode {
120 let code = self.cast::<ContainerComponent>().on_added_dirty(context);
121 if code != StatusCode::Ok {
122 return code;
123 }
124
125 if let Some(path) = self.parent_path() {
126 path.as_ref().push_vertex(self.as_object());
127 StatusCode::Ok
128 } else {
129 StatusCode::MissingObject
130 }
131 }
132}