rive_rs/shapes/
rectangle.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::rc::Rc;

use crate::component::Component;
use crate::component_dirt::ComponentDirt;
use crate::core::{Core, Object, ObjectRef, OnAdded, Property};
use crate::shapes::{ParametricPath, Path, StraightVertex};

use super::PathVertex;

#[derive(Debug)]
pub struct Rectangle {
    parametric_path: ParametricPath,
    corner_radius: Property<f32>,
    vertex1: Rc<StraightVertex>,
    vertex2: Rc<StraightVertex>,
    vertex3: Rc<StraightVertex>,
    vertex4: Rc<StraightVertex>,
}

impl ObjectRef<'_, Rectangle> {
    pub fn corner_radius(&self) -> f32 {
        self.corner_radius.get()
    }

    pub fn set_corner_radius(&self, corner_radius: f32) {
        self.corner_radius.set(corner_radius);
        self.cast::<Path>().mark_path_dirty();
    }
}

impl ObjectRef<'_, Rectangle> {
    pub fn update(&self, value: ComponentDirt) {
        if Component::value_has_dirt(value, ComponentDirt::PATH) {
            let radius = self.corner_radius();
            let parametric_path = self.cast::<ParametricPath>();

            let width = parametric_path.width();
            let height = parametric_path.height();

            let ox = -parametric_path.origin_x() * width;
            let oy = -parametric_path.origin_y() * height;

            let vertex1_ref = ObjectRef::from(&*self.vertex1);
            vertex1_ref.cast::<PathVertex>().set_x(ox);
            vertex1_ref.cast::<PathVertex>().set_y(oy);
            vertex1_ref.set_radius(radius);

            let vertex2_ref = ObjectRef::from(&*self.vertex2);
            vertex2_ref.cast::<PathVertex>().set_x(ox + width);
            vertex2_ref.cast::<PathVertex>().set_y(oy);
            vertex2_ref.set_radius(radius);

            let vertex3_ref = ObjectRef::from(&*self.vertex3);
            vertex3_ref.cast::<PathVertex>().set_x(ox + width);
            vertex3_ref.cast::<PathVertex>().set_y(oy + height);
            vertex3_ref.set_radius(radius);

            let vertex4_ref = ObjectRef::from(&*self.vertex4);
            vertex4_ref.cast::<PathVertex>().set_x(ox);
            vertex4_ref.cast::<PathVertex>().set_y(oy + height);
            vertex4_ref.set_radius(radius);
        }

        self.cast::<Path>().update(value);
    }
}

impl Core for Rectangle {
    parent_types![(parametric_path, ParametricPath)];

    properties![(31, corner_radius, set_corner_radius), parametric_path];
}

impl OnAdded for ObjectRef<'_, Rectangle> {
    on_added!(ParametricPath);
}

impl Default for Rectangle {
    fn default() -> Self {
        let rectangle = Self {
            parametric_path: ParametricPath::default(),
            corner_radius: Property::new(0.0),
            vertex1: Rc::new(StraightVertex::default()),
            vertex2: Rc::new(StraightVertex::default()),
            vertex3: Rc::new(StraightVertex::default()),
            vertex4: Rc::new(StraightVertex::default()),
        };

        let rectangle_ref = ObjectRef::from(&rectangle);
        let path = rectangle_ref.cast::<Path>();

        path.push_vertex(Object::new(&(rectangle.vertex1.clone() as Rc<dyn Core>)));
        path.push_vertex(Object::new(&(rectangle.vertex2.clone() as Rc<dyn Core>)));
        path.push_vertex(Object::new(&(rectangle.vertex3.clone() as Rc<dyn Core>)));
        path.push_vertex(Object::new(&(rectangle.vertex4.clone() as Rc<dyn Core>)));

        rectangle
    }
}