rive_rs/shapes/
polygon.rs
1use std::cmp::Ordering;
6use std::rc::Rc;
7
8use crate::component::Component;
9use crate::component_dirt::ComponentDirt;
10use crate::core::{Core, Object, ObjectRef, OnAdded, Property};
11use crate::dyn_vec::DynVec;
12use crate::shapes::{ParametricPath, Path, PathVertex, StraightVertex};
13
14#[derive(Debug, Default)]
15pub struct Polygon {
16 parametric_path: ParametricPath,
17 points: Property<u64>,
18 corner_radius: Property<f32>,
19 vertices: DynVec<Rc<StraightVertex>>,
20}
21
22impl ObjectRef<'_, Polygon> {
23 pub fn points(&self) -> u64 {
24 self.points.get()
25 }
26
27 pub fn set_points(&self, points: u64) {
28 self.points.set(points);
29 self.cast::<Path>().mark_path_dirty();
30 }
31
32 pub fn corner_radius(&self) -> f32 {
33 self.corner_radius.get()
34 }
35
36 pub fn set_corner_radius(&self, corner_radius: f32) {
37 self.corner_radius.set(corner_radius);
38 self.cast::<Path>().mark_path_dirty();
39 }
40}
41
42impl ObjectRef<'_, Polygon> {
43 fn expected_len(&self) -> usize {
44 self.points() as usize
45 }
46
47 fn resize_vertices(&self, new_len: usize) {
48 match self.vertices.len().cmp(&new_len) {
49 Ordering::Less => {
50 for _ in 0..new_len - self.vertices.len() {
51 let vertex = Rc::new(StraightVertex::default());
52
53 self.cast::<Path>().push_vertex(Object::new(&(vertex.clone() as Rc<dyn Core>)));
54 self.vertices.push(vertex);
55 }
56 }
57 Ordering::Greater => {
58 self.cast::<Path>().vertices.truncate(new_len);
59 self.vertices.truncate(new_len);
60 }
61 _ => (),
62 }
63 }
64
65 fn build_polygon(&self) {
66 let parametric_path = self.cast::<ParametricPath>();
67
68 let half_width = parametric_path.width() * 0.5;
69 let half_height = parametric_path.height() * 0.5;
70
71 let mut angle = -std::f32::consts::FRAC_PI_2;
72 let increment = std::f32::consts::PI / self.points() as f32;
73
74 for vertex in self.vertices.iter() {
75 let (sin, cos) = angle.sin_cos();
76
77 let vertex_ref = ObjectRef::from(&*vertex);
78 vertex_ref.cast::<PathVertex>().set_x(cos * half_width);
79 vertex_ref.cast::<PathVertex>().set_y(sin * half_height);
80 vertex_ref.set_radius(self.corner_radius());
81
82 angle += increment;
83 }
84 }
85
86 pub fn update(&self, value: ComponentDirt) {
87 let path = self.cast::<Path>();
88
89 if Component::value_has_dirt(value, ComponentDirt::PATH) {
90 let expected_len = self.expected_len();
91 if self.vertices.len() != expected_len {
92 self.resize_vertices(expected_len);
93 }
94
95 self.build_polygon();
96 }
97
98 path.update(value);
99 }
100}
101
102impl Core for Polygon {
103 parent_types![(parametric_path, ParametricPath)];
104
105 properties!(
106 (125, points, set_points),
107 (126, corner_radius, set_corner_radius),
108 parametric_path
109 );
110}
111
112impl OnAdded for ObjectRef<'_, Polygon> {
113 on_added!(ParametricPath);
114}