rive_rs/
draw_target.rs
1use crate::component::Component;
6use crate::component_dirt::ComponentDirt;
7use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property, TryFromU64};
8use crate::drawable::Drawable;
9use crate::dyn_vec::DynVec;
10use crate::option_cell::OptionCell;
11use crate::shapes::ClippingShape;
12use crate::status_code::StatusCode;
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub enum DrawTargetPlacement {
16 Before,
17 After,
18}
19
20impl Default for DrawTargetPlacement {
21 fn default() -> Self {
22 Self::Before
23 }
24}
25
26impl TryFromU64 for DrawTargetPlacement {
27 fn try_from(val: u64) -> Option<Self> {
28 match val {
29 0 => Some(Self::Before),
30 1 => Some(Self::After),
31 _ => None,
32 }
33 }
34}
35
36#[derive(Debug)]
37pub struct DrawTarget {
38 component: Component,
39 drawable_id: Property<u64>,
40 placement: Property<DrawTargetPlacement>,
41 drawable: OptionCell<Object<Drawable>>,
42 pub(crate) first: OptionCell<Object<Drawable>>,
43 pub(crate) last: OptionCell<Object<Drawable>>,
44 clipping_shapes: DynVec<Object<ClippingShape>>,
45}
46
47impl ObjectRef<'_, DrawTarget> {
48 pub fn drawable_id(&self) -> u64 {
49 self.drawable_id.get()
50 }
51
52 pub fn set_drawable_id(&self, drawable_id: u64) {
53 self.drawable_id.set(drawable_id);
54 }
55
56 pub fn placement(&self) -> DrawTargetPlacement {
57 self.placement.get()
58 }
59
60 pub fn set_placement(&self, placement: DrawTargetPlacement) {
61 if self.placement() == placement {
62 return;
63 }
64
65 self.placement.set(placement);
66
67 if let Some(artboard) = self.component.artboard() {
68 artboard.cast::<Component>().as_ref().add_dirt(ComponentDirt::DRAW_ORDER, false);
69 }
70 }
71}
72
73impl ObjectRef<'_, DrawTarget> {
74 pub fn drawable(&self) -> Option<Object<Drawable>> {
75 self.drawable.get()
76 }
77
78 pub fn push_clipping_shape(&self, clipping_shape: Object<ClippingShape>) {
79 self.clipping_shapes.push(clipping_shape);
80 }
81
82 pub fn clipping_shapes(&self) -> impl Iterator<Item = Object<ClippingShape>> + '_ {
83 self.clipping_shapes.iter()
84 }
85}
86
87impl Core for DrawTarget {
88 parent_types![(component, Component)];
89
90 properties![(119, drawable_id, set_drawable_id), (120, placement, set_placement), component];
91}
92
93impl OnAdded for ObjectRef<'_, DrawTarget> {
94 on_added!([on_added_clean, import], Component);
95
96 fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode {
97 let code = self.cast::<Component>().on_added_dirty(context);
98 if code != StatusCode::Ok {
99 return code;
100 }
101
102 if let Some(drawable) =
103 context.resolve(self.drawable_id() as usize).and_then(|core| core.try_cast())
104 {
105 self.drawable.set(Some(drawable));
106 StatusCode::Ok
107 } else {
108 StatusCode::MissingObject
109 }
110 }
111}
112
113impl Default for DrawTarget {
114 fn default() -> Self {
115 Self {
116 component: Component::default(),
117 drawable_id: Property::new(0),
118 placement: Property::new(DrawTargetPlacement::Before),
119 drawable: OptionCell::new(),
120 first: OptionCell::new(),
121 last: OptionCell::new(),
122 clipping_shapes: DynVec::new(),
123 }
124 }
125}