rive_rs/core/
mod.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::any::{self, Any, TypeId};
6use std::fmt;
7use std::rc::Rc;
8
9use crate::animation::Loop;
10use crate::artboard::Artboard;
11use crate::draw_target::DrawTargetPlacement;
12use crate::importers::ImportStack;
13use crate::shapes::paint::{BlendMode, Color32, StrokeCap, StrokeJoin};
14use crate::shapes::FillRule;
15use crate::StatusCode;
16
17mod binary_reader;
18mod object;
19mod property;
20
21pub use binary_reader::BinaryReader;
22pub use object::{Object, ObjectRef};
23pub use property::{Property, TryFromU64};
24
25macro_rules! types {
26    ( $( ( $id:expr , $type:ty ) ),* $( , )? ) => {
27        pub fn get_type_id(id: u16) -> Option<TypeId> {
28            match id {
29                $(
30                    $id => Some(TypeId::of::<$type>()),
31                )*
32                _ => None,
33            }
34        }
35
36        impl dyn Core {
37            pub fn from_type_id(id: TypeId) -> Option<(Rc<dyn Core>, Object)> {
38                match id {
39                    $(
40                        id if id == TypeId::of::<$type>() => {
41                            let rc: Rc<dyn Core> = Rc::new(<$type>::default());
42                            let object = Object::<$type>::new(&rc);
43                            Some((rc, object.into()))
44                        }
45                    )*
46                    _ => None,
47                }
48            }
49        }
50    };
51}
52
53macro_rules! parent_types {
54    ( ( $field_head:ident , $type_head:ty ) $( , ( $field_tail:ident , $type_tail:ty ) )* $( , )? ) => {
55        fn ref_of(&self, id: ::std::any::TypeId) -> Option<&dyn Core> {
56            if id == ::std::any::TypeId::of::<$type_head>() {
57                Some(&self.$field_head)
58            }
59            $(
60                else if id == ::std::any::TypeId::of::<$type_tail>() {
61                    Some(&self.$field_tail)
62                }
63            )*
64            else {
65                self.$field_head
66                    .ref_of(id)
67                    $(
68                        .or_else(|| self.$field_tail.ref_of(id))
69                    )*
70            }
71        }
72    };
73}
74
75macro_rules! properties {
76    ( $parent:ident ) => {
77        fn property_of(&self, key: u16) -> Option<&dyn ::std::any::Any> {
78            self.$parent.property_of(key)
79        }
80
81        fn animate(&self, object: &ObjectRef<'_>, key: u64, animator: &dyn ::std::any::Any) {
82            self.$parent.animate(object, key, animator);
83        }
84    };
85
86    ( $( ( $key:expr , $field:ident , $setter:ident ) ),* , $parent:ident $( , )? ) => {
87        fn property_of(&self, key: u16) -> Option<&dyn ::std::any::Any> {
88            match key {
89                $(
90                    $key => Some(&self.$field),
91                )*
92                _ => self.$parent.property_of(key),
93            }
94        }
95
96        fn animate(&self, object: &ObjectRef<'_>, key: u64, animator: &dyn ::std::any::Any) {
97            $(
98                if key == $key {
99                    if let Some(animator) = animator.downcast_ref::<crate::animation::Animator<_>>() {
100                        return animator.animate(&object.cast(), ObjectRef::<Self>::$setter);
101                    }
102                }
103            )*
104
105            self.$parent.animate(&object, key, animator);
106        }
107    };
108
109    ( $( ( $key:expr , $field:ident , $setter:ident ) ),* $( , )? ) => {
110        fn property_of(&self, key: u16) -> Option<&dyn ::std::any::Any> {
111            match key {
112                $(
113                    $key => Some(&self.$field),
114                )*
115                _ => None,
116            }
117        }
118
119        fn animate(&self, object: &ObjectRef<'_>, key: u64, animator: &dyn ::std::any::Any) {
120            $(
121                if key == $key {
122                    if let Some(animator) = animator.downcast_ref::<crate::animation::Animator<_>>() {
123                        return animator.animate(&object.cast(), ObjectRef::<Self>::$setter);
124                    }
125                }
126            )*
127        }
128    };
129}
130
131macro_rules! on_added {
132    ( @impl import ) => {
133        fn import(&self,  _object: crate::core::Object, _import_stack: &crate::importers::ImportStack) -> crate::status_code::StatusCode {
134            crate::status_code::StatusCode::Ok
135        }
136    };
137
138    ( @impl $method:ident ) => {
139        fn $method(&self, _context: &dyn crate::core::CoreContext) -> crate::status_code::StatusCode {
140            crate::status_code::StatusCode::Ok
141        }
142    };
143
144    ( @impl import , $type:ty ) => {
145        fn import(&self, object: crate::core::Object, import_stack: &crate::importers::ImportStack) -> crate::status_code::StatusCode {
146            self.cast::<$type>().import(object, import_stack)
147        }
148    };
149
150    ( @impl $method:ident , $type:ty ) => {
151        fn $method(&self, context: &dyn crate::core::CoreContext) -> crate::status_code::StatusCode {
152            self.cast::<$type>().$method(context)
153        }
154    };
155
156    () => {
157        on_added!(@impl on_added_dirty);
158        on_added!(@impl on_added_clean);
159        on_added!(@impl import);
160    };
161
162    ( [ $( $method:ident ),+ ] ) => {
163        $(
164            on_added!(@impl $method);
165        )+
166    };
167
168    ( [ $( $method:ident ),+ ] , $type:ty ) => {
169        $(
170            on_added!(@impl $method, $type);
171        )+
172    };
173
174    ( $type:ty ) => {
175        on_added!(@impl on_added_dirty, $type);
176        on_added!(@impl on_added_clean, $type);
177        on_added!(@impl import, $type);
178    };
179}
180
181macro_rules! match_cast {
182    ( $val:expr , { $( $to:ident ( $name:ident ) => $block:expr ),*  $( , _ => $default:expr )? $( , )? } ) => {{
183        let f = || {
184            $(
185                if let Some($name) = $val.try_cast::<$to>() {
186                    return $block;
187                }
188            )*
189            $($default)?
190        };
191
192        f()
193    }};
194}
195
196pub trait AsAny: Any + fmt::Debug {
197    fn as_any(&self) -> &dyn Any;
198    fn any_type_name(&self) -> &'static str;
199}
200
201impl<T: Any + fmt::Debug> AsAny for T {
202    #[inline(always)]
203    fn as_any(&self) -> &dyn Any {
204        self
205    }
206
207    #[inline(always)]
208    fn any_type_name(&self) -> &'static str {
209        core::any::type_name::<T>()
210    }
211}
212
213trait Cast: Core {
214    #[inline]
215    fn is<T>(&self) -> bool
216    where
217        T: Core,
218    {
219        self.as_any().is::<T>() || self.ref_of(TypeId::of::<T>()).is_some()
220    }
221
222    #[inline]
223    fn try_cast<T>(&self) -> Option<&T>
224    where
225        T: Core,
226    {
227        self.as_any()
228            .downcast_ref()
229            .or_else(|| self.ref_of(TypeId::of::<T>()).and_then(|any| any.as_any().downcast_ref()))
230    }
231
232    #[inline]
233    fn cast<T>(&self) -> &T
234    where
235        T: Core,
236    {
237        self.try_cast().unwrap_or_else(|| panic!("failed cast to {}", any::type_name::<T>()))
238    }
239}
240
241impl Cast for dyn Core {}
242
243#[allow(unused_variables)]
244pub trait Core: AsAny {
245    #[inline]
246    fn ref_of(&self, id: TypeId) -> Option<&dyn Core> {
247        None
248    }
249
250    #[inline]
251    fn property_of(&self, key: u16) -> Option<&dyn Any> {
252        None
253    }
254
255    #[inline]
256    fn animate(&self, object: &ObjectRef<'_>, key: u64, animator: &dyn Any) {}
257
258    #[inline]
259    fn type_name(&self) -> &'static str {
260        self.any_type_name().rsplit("::").next().unwrap()
261    }
262}
263
264impl dyn Core {
265    #[inline]
266    pub fn get_property<T: Clone + Default + 'static>(&self, key: u16) -> Option<&Property<T>> {
267        self.property_of(key).and_then(<dyn Any>::downcast_ref::<Property<T>>)
268    }
269
270    pub(crate) fn write(&self, property_key: u16, reader: &mut BinaryReader<'_>) -> bool {
271        if let Some(property) = self.property_of(property_key) {
272            macro_rules! write_types {
273                ( $property:expr , $reader:expr , [ $( $type:ident ),* $( , )? ] ) => {
274                    match $property.type_id() {
275                        $(
276                            id if id == TypeId::of::<Property<$type>>() => {
277                                let property = property.downcast_ref::<Property<$type>>().unwrap();
278                                return $reader.write(property);
279                            }
280                        )*
281                        _ => (),
282                    }
283                };
284            }
285
286            write_types!(
287                property,
288                reader,
289                [
290                    bool,
291                    u32,
292                    u64,
293                    f32,
294                    String,
295                    Color32,
296                    BlendMode,
297                    DrawTargetPlacement,
298                    FillRule,
299                    Loop,
300                    StrokeCap,
301                    StrokeJoin,
302                ]
303            );
304        }
305
306        false
307    }
308}
309
310pub trait OnAdded {
311    fn on_added_dirty(&self, context: &dyn CoreContext) -> StatusCode;
312
313    fn on_added_clean(&self, context: &dyn CoreContext) -> StatusCode;
314
315    fn import(&self, object: Object, import_stack: &ImportStack) -> StatusCode;
316}
317
318pub trait CoreContext {
319    fn resolve(&self, id: usize) -> Option<Object>;
320    fn artboard(&self) -> Object<Artboard> {
321        self.resolve(0)
322            .and_then(|object| object.try_cast())
323            .expect("frist object should always be the Artboard")
324    }
325}
326
327types![
328    (1, crate::Artboard),
329    (2, crate::Node),
330    (3, crate::shapes::Shape),
331    (4, crate::shapes::Ellipse),
332    (5, crate::shapes::StraightVertex),
333    (6, crate::shapes::CubicDetachedVertex),
334    (7, crate::shapes::Rectangle),
335    (8, crate::shapes::Triangle),
336    (9, crate::shapes::PathComposer),
337    (10, crate::Component),
338    (11, crate::ContainerComponent),
339    (13, crate::Drawable),
340    (14, crate::shapes::PathVertex),
341    (15, crate::shapes::ParametricPath),
342    (16, crate::shapes::PointsPath),
343    (17, crate::shapes::paint::RadialGradient),
344    (18, crate::shapes::paint::SolidColor),
345    (19, crate::shapes::paint::GradientStop),
346    (20, crate::shapes::paint::Fill),
347    (21, crate::shapes::paint::ShapePaint),
348    (22, crate::shapes::paint::LinearGradient),
349    (23, crate::Backboard),
350    (24, crate::shapes::paint::Stroke),
351    (25, crate::animation::KeyedObject),
352    (26, crate::animation::KeyedProperty),
353    (27, crate::animation::Animation),
354    (28, crate::animation::CubicInterpolator),
355    (29, crate::animation::KeyFrame),
356    (30, crate::animation::KeyFrameDouble),
357    (31, crate::animation::LinearAnimation),
358    (34, crate::shapes::CubicAsymmetricVertex),
359    (35, crate::shapes::CubicMirroredVertex),
360    (37, crate::animation::KeyFrameColor),
361    (38, crate::TransformComponent),
362    (39, crate::bones::SkeletalComponent),
363    (40, crate::bones::Bone),
364    (41, crate::bones::RootBone),
365    (42, crate::shapes::ClippingShape),
366    (43, crate::bones::Skin),
367    (44, crate::bones::Tendon),
368    (45, crate::bones::Weight),
369    (46, crate::bones::CubicWeight),
370    (47, crate::shapes::paint::TrimPath),
371    (48, crate::DrawTarget),
372    (49, crate::DrawRules),
373    (50, crate::animation::KeyFrameId),
374    (51, crate::shapes::Polygon),
375    (52, crate::shapes::Star),
376    (53, crate::animation::StateMachine),
377    (54, crate::animation::StateMachineComponent),
378    (55, crate::animation::StateMachineInput),
379    (56, crate::animation::StateMachineDouble),
380    (57, crate::animation::StateMachineLayer),
381    (58, crate::animation::StateMachineTrigger),
382    (59, crate::animation::StateMachineBool),
383    (60, crate::animation::LayerState),
384    (61, crate::animation::AnimationState),
385    (62, crate::animation::AnyState),
386    (63, crate::animation::EntryState),
387    (64, crate::animation::ExitState),
388    (65, crate::animation::StateTransition),
389    (66, crate::animation::StateMachineLayerComponent),
390    (67, crate::animation::TransitionCondition),
391    (68, crate::animation::TransitionTriggerCondition),
392    (69, crate::animation::TransitionValueCondition),
393    (70, crate::animation::TransitionDoubleCondition),
394    (71, crate::animation::TransitionBoolCondition),
395];