1use std::cell::{Cell, Ref, RefCell};
6use std::collections::{HashMap, VecDeque};
7use std::iter;
8use std::rc::Rc;
9
10use crate::animation::{LinearAnimation, StateMachine};
11use crate::component::Component;
12use crate::component_dirt::ComponentDirt;
13use crate::container_component::ContainerComponent;
14use crate::core::{Core, CoreContext, Object, ObjectRef, OnAdded, Property};
15use crate::dependency_sorter::DependencySorter;
16use crate::draw_target::{DrawTarget, DrawTargetPlacement};
17use crate::drawable::Drawable;
18use crate::math::{self, Aabb, Mat};
19use crate::option_cell::OptionCell;
20use crate::renderer::Renderer;
21use crate::shapes::{CommandPath, CommandPathBuilder, ShapePaintContainer};
22use crate::status_code::StatusCode;
23
24#[derive(Clone, Debug)]
25pub struct ObjectsIter<T: Core> {
26 objects: Rc<RefCell<Vec<Object<T>>>>,
27 head: usize,
28 tail: usize,
29}
30
31impl<T: Core> ObjectsIter<T> {
32 fn new(objects: Rc<RefCell<Vec<Object<T>>>>) -> Self {
33 let len = objects.borrow().len();
34 Self { objects, head: 0, tail: len }
35 }
36}
37
38impl<T: Core> Iterator for ObjectsIter<T> {
39 type Item = Object<T>;
40
41 #[inline]
42 fn next(&mut self) -> Option<Self::Item> {
43 if self.head == self.tail {
44 return None;
45 }
46
47 let result = self.objects.borrow().iter().nth(self.head).cloned();
48
49 if result.is_some() {
50 self.head += 1;
51 }
52
53 result
54 }
55
56 #[inline]
57 fn size_hint(&self) -> (usize, Option<usize>) {
58 let len = self.tail - self.head;
59 (len, Some(len))
60 }
61
62 #[inline]
63 fn count(self) -> usize {
64 self.tail - self.head
65 }
66
67 #[inline]
68 fn nth(&mut self, n: usize) -> Option<Self::Item> {
69 self.objects.borrow().iter().nth(self.head + n).cloned()
70 }
71}
72
73impl<T: Core> DoubleEndedIterator for ObjectsIter<T> {
74 #[inline]
75 fn next_back(&mut self) -> Option<Self::Item> {
76 if self.head == self.tail {
77 return None;
78 }
79
80 let result = self.objects.borrow().iter().nth(self.tail - 1).cloned();
81
82 if result.is_some() {
83 self.tail -= 1;
84 }
85
86 result
87 }
88
89 #[inline]
90 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
91 if n >= self.tail {
92 return None;
93 }
94
95 self.objects.borrow().iter().nth(self.tail - 1 - n).cloned()
96 }
97}
98
99impl<T: Core> ExactSizeIterator for ObjectsIter<T> {
100 #[inline]
101 fn len(&self) -> usize {
102 self.tail - self.head
103 }
104}
105
106#[derive(Debug, Default)]
107struct ArtboardInner {
108 objects: RefCell<Vec<Object>>,
109 animations: Rc<RefCell<Vec<Object<LinearAnimation>>>>,
110 state_machines: Rc<RefCell<Vec<Object<StateMachine>>>>,
111 dependency_order: RefCell<VecDeque<Object<Component>>>,
112 drawables: RefCell<Vec<Object<Drawable>>>,
113 draw_targets: RefCell<Vec<Object<DrawTarget>>>,
114 dirt_depth: Cell<usize>,
115 background_path: RefCell<Option<CommandPath>>,
116 clip_path: RefCell<Option<CommandPath>>,
117 first_drawable: OptionCell<Object<Drawable>>,
118 root: OptionCell<Rc<dyn Core>>,
119}
120
121fn objects_of<T: Core>(objects: &[Object]) -> impl Iterator<Item = Object<T>> + '_ {
122 objects.iter().cloned().filter_map(|object| object.try_cast())
123}
124
125impl ArtboardInner {
126 pub fn initialize(&self) -> StatusCode {
127 for object in self.objects.borrow().iter() {
128 let code = object.as_ref().on_added_dirty(self);
129 if code != StatusCode::Ok {
130 return code;
131 }
132 }
133
134 for object in self.animations.borrow().iter() {
135 let code = object.as_ref().on_added_dirty(self);
136 if code != StatusCode::Ok {
137 return code;
138 }
139 }
140
141 for object in self.state_machines.borrow().iter() {
142 let code = object.as_ref().on_added_dirty(self);
143 if code != StatusCode::Ok {
144 return code;
145 }
146 }
147
148 let mut component_draw_rules = HashMap::new();
149
150 for object in self.objects.borrow().iter() {
151 let code = object.as_ref().on_added_clean(self);
152 if code != StatusCode::Ok {
153 return code;
154 }
155
156 if let Some(draw_rules) = object.try_cast() {
157 if let Some(component) = self
158 .resolve(draw_rules.cast::<Component>().as_ref().parent_id() as usize)
159 .and_then(|core| core.try_cast())
160 {
161 component_draw_rules.insert(component, draw_rules);
162 } else {
163 return StatusCode::MissingObject;
164 }
165 }
166 }
167
168 for object in self.animations.borrow().iter() {
169 let code = object.as_ref().on_added_clean(self);
170 if code != StatusCode::Ok {
171 return code;
172 }
173 }
174
175 for object in self.state_machines.borrow().iter() {
176 let code = object.as_ref().on_added_clean(self);
177 if code != StatusCode::Ok {
178 return code;
179 }
180 }
181
182 for component in objects_of::<Component>(self.objects.borrow().as_slice()) {
183 component.as_ref().build_dependencies();
184 }
185
186 for drawable in objects_of::<Drawable>(self.objects.borrow().as_slice()) {
187 self.drawables.borrow_mut().push(drawable.clone());
188
189 let parents = iter::once(drawable.cast::<ContainerComponent>())
190 .chain(drawable.cast::<Component>().as_ref().parents());
191
192 for parent in parents {
193 if let Some(draw_rules) = component_draw_rules.get(&parent) {
194 drawable.as_ref().flattened_draw_rules.set(Some(draw_rules.clone()));
195 break;
196 }
197 }
198 }
199
200 self.sort_dependencies();
201
202 let root: Rc<dyn Core> = Rc::new(DrawTarget::default());
203 self.root.set(Some(Rc::clone(&root)));
204 let root = Object::new(&root);
205
206 for draw_target in objects_of::<DrawTarget>(self.objects.borrow().as_slice()) {
207 root.cast::<Component>().as_ref().push_dependent(draw_target.cast());
208
209 if let Some(dependent_rules) = draw_target
210 .as_ref()
211 .drawable()
212 .expect("DrawTarget has no Drawable set")
213 .as_ref()
214 .flattened_draw_rules
215 .get()
216 {
217 for dependent_target in objects_of::<DrawTarget>(self.objects.borrow().as_slice()) {
218 let dependent_target = dependent_target.cast::<Component>();
219 let dependent_target = dependent_target.as_ref();
220 if let Some(parent) = dependent_target.parent() {
221 if parent.ptr_eq(&dependent_rules) {
222 dependent_target.push_dependent(draw_target.cast());
223 }
224 }
225 }
226 }
227 }
228
229 let mut sorter = DependencySorter::default();
230 let mut draw_target_order = VecDeque::new();
231
232 sorter.sort(root, &mut draw_target_order);
233
234 self.draw_targets
235 .borrow_mut()
236 .extend(draw_target_order.into_iter().map(|component| component.cast()));
237
238 StatusCode::Ok
239 }
240
241 pub fn sort_draw_order(&self) {
242 for target in &*self.draw_targets.borrow() {
243 let target = target.as_ref();
244 target.first.set(None);
245 target.last.set(None);
246 }
247
248 self.first_drawable.set(None);
249 let mut last_drawable = None;
250
251 for drawable in &*self.drawables.borrow() {
252 let drawable_ref = drawable.as_ref();
253 if let Some(target) = drawable_ref
254 .flattened_draw_rules
255 .get()
256 .and_then(|rules| rules.as_ref().active_target())
257 {
258 let target = target.as_ref();
259 if let (Some(_), Some(last)) = (target.first.get(), target.last.get()) {
260 last.as_ref().next.set(Some(drawable.clone()));
261 drawable_ref.prev.set(Some(last));
262 target.last.set(Some(drawable.clone()));
263 } else {
264 target.first.set(Some(drawable.clone()));
265 target.last.set(Some(drawable.clone()));
266 drawable_ref.prev.set(None);
267 }
268 drawable_ref.next.set(None);
269 } else {
270 drawable_ref.prev.set(last_drawable.clone());
271 drawable_ref.next.set(None);
272
273 if let Some(ref last_drawable_ref) = last_drawable {
274 last_drawable_ref.as_ref().next.set(Some(drawable.clone()));
275 last_drawable = Some(drawable.clone());
276 } else {
277 last_drawable = Some(drawable.clone());
278 self.first_drawable.set(Some(drawable.clone()));
279 }
280 }
281 }
282
283 for rule in &*self.draw_targets.borrow() {
284 let rule = rule.as_ref();
285 if let (Some(ref rule_first), Some(ref rule_last)) = (rule.first.get(), rule.last.get())
286 {
287 let rule_last_ref = rule_last.as_ref();
288 if let Some(ref target_drawable) = rule.drawable() {
289 let target_drawable_ref = target_drawable.as_ref();
290 match rule.placement() {
291 DrawTargetPlacement::Before => {
292 if let Some(prev) = target_drawable_ref.prev.get() {
293 prev.as_ref().next.set(Some(rule_first.clone()));
294 rule_first.as_ref().prev.set(Some(prev));
295 }
296
297 if Some(target_drawable) == self.first_drawable.get().as_ref() {
298 self.first_drawable.set(Some(rule_first.clone()));
299 }
300
301 target_drawable_ref.prev.set(Some(rule_last.clone()));
302 rule_last_ref.next.set(Some(target_drawable.clone()));
303 }
304 DrawTargetPlacement::After => {
305 if let Some(next) = target_drawable_ref.next.get() {
306 next.as_ref().prev.set(Some(rule_last.clone()));
307 rule_last_ref.next.set(target_drawable_ref.next.get());
308 }
309
310 if Some(target_drawable) == last_drawable.as_ref() {
311 last_drawable = Some(rule_last.clone());
312 }
313
314 target_drawable_ref.next.set(Some(rule_first.clone()));
315 rule_last_ref.prev.set(Some(target_drawable.clone()));
316 }
317 }
318 }
319 }
320 }
321
322 self.first_drawable.set(last_drawable);
323 }
324
325 fn component(&self) -> Object<Component> {
326 self.objects.borrow()[0].try_cast().expect("first object in Artboard must be itself")
327 }
328
329 fn sort_dependencies(&self) {
330 let mut sorter = DependencySorter::default();
331
332 let component = self.component();
333 sorter.sort(component.clone(), &mut *self.dependency_order.borrow_mut());
334
335 for (component, graph_order) in self.dependency_order.borrow().iter().zip(0..) {
336 component.as_ref().graph_order.set(graph_order);
337 }
338
339 component.as_ref().dirt.set(component.as_ref().dirt.get() | ComponentDirt::COMPONENTS);
340 }
341
342 pub fn push_object(&self, object: Object) {
343 self.objects.borrow_mut().push(object);
344 }
345
346 pub fn push_animation(&self, animation: Object<LinearAnimation>) {
347 self.animations.borrow_mut().push(animation);
348 }
349
350 pub fn push_state_machine(&self, state_machine: Object<StateMachine>) {
351 self.state_machines.borrow_mut().push(state_machine);
352 }
353
354 pub fn on_component_dirty(&self, component: &Component) {
355 let this_component = self.component();
356 let this_component = this_component.as_ref();
357 this_component.dirt.set(this_component.dirt.get() | ComponentDirt::COMPONENTS);
358
359 self.dirt_depth.set(self.dirt_depth.get().min(component.graph_order.get()));
360 }
361
362 pub fn update_components(&self, component: ObjectRef<'_, Component>) -> bool {
363 let mut step = 0;
364 while component.has_dirt(ComponentDirt::COMPONENTS) && step < 100 {
365 for (i, component) in self.dependency_order.borrow().iter().enumerate() {
366 self.dirt_depth.set(i);
367
368 let component = component.as_ref();
369 let dirt = component.dirt.get();
370 if dirt.is_empty() {
371 continue;
372 }
373
374 component.dirt.set(ComponentDirt::empty());
375 component.update(dirt);
376
377 if self.dirt_depth.get() < i {
378 break;
379 }
380 }
381
382 step += 1;
383 }
384
385 false
386 }
387}
388
389#[derive(Debug, Default)]
390pub struct Artboard {
391 container_component: ContainerComponent,
392 shape_paint_container: ShapePaintContainer,
393 width: Property<f32>,
394 height: Property<f32>,
395 x: Property<f32>,
396 y: Property<f32>,
397 origin_x: Property<f32>,
398 origin_y: Property<f32>,
399 inner: ArtboardInner,
400}
401
402impl ObjectRef<'_, Artboard> {
403 pub fn width(&self) -> f32 {
404 self.width.get()
405 }
406
407 pub fn set_width(&self, width: f32) {
408 self.width.set(width);
409 }
410
411 pub fn height(&self) -> f32 {
412 self.height.get()
413 }
414
415 pub fn set_height(&self, height: f32) {
416 self.height.set(height);
417 }
418
419 pub fn x(&self) -> f32 {
420 self.x.get()
421 }
422
423 pub fn set_x(&self, x: f32) {
424 self.x.set(x);
425 }
426
427 pub fn y(&self) -> f32 {
428 self.y.get()
429 }
430
431 pub fn set_y(&self, y: f32) {
432 self.y.set(y);
433 }
434
435 pub fn origin_x(&self) -> f32 {
436 self.origin_x.get()
437 }
438
439 pub fn set_origin_x(&self, origin_x: f32) {
440 self.origin_x.set(origin_x);
441 }
442
443 pub fn origin_y(&self) -> f32 {
444 self.origin_y.get()
445 }
446
447 pub fn set_origin_y(&self, origin_y: f32) {
448 self.origin_y.set(origin_y);
449 }
450}
451
452impl ObjectRef<'_, Artboard> {
453 pub fn initialize(&self) -> StatusCode {
454 self.inner.initialize()
455 }
456
457 pub fn push_object(&self, object: Object) {
458 self.inner.push_object(object);
459 }
460
461 pub(crate) fn objects(&self) -> Ref<'_, [Object]> {
462 Ref::map(self.inner.objects.borrow(), |objects| objects.as_slice())
463 }
464
465 pub fn push_animation(&self, animation: Object<LinearAnimation>) {
466 self.inner.push_animation(animation);
467 }
468
469 pub fn push_state_machine(&self, state_machine: Object<StateMachine>) {
470 self.inner.push_state_machine(state_machine);
471 }
472
473 pub fn on_component_dirty(&self, component: &Component) {
474 self.inner.on_component_dirty(component);
475 }
476
477 fn as_component(&self) -> ObjectRef<'_, Component> {
478 self.cast()
479 }
480
481 pub fn on_dirty(&self, _dirt: ComponentDirt) {
482 let dirt = &self.as_component().dirt;
483 dirt.set(dirt.get() | ComponentDirt::COMPONENTS);
484 }
485
486 pub fn update(&self, value: ComponentDirt) {
487 if Component::value_has_dirt(value, ComponentDirt::DRAW_ORDER) {
488 self.inner.sort_draw_order();
489 }
490
491 if Component::value_has_dirt(value, ComponentDirt::PATH) {
492 let mut builder = CommandPathBuilder::new();
493
494 builder.rect(math::Vec::new(0.0, 0.0), math::Vec::new(self.width(), self.height()));
495
496 *self.inner.clip_path.borrow_mut() = Some(builder.build());
497
498 let mut builder = CommandPathBuilder::new();
499
500 builder.rect(
501 math::Vec::new(-self.width() * self.origin_x(), -self.height() * self.origin_y()),
502 math::Vec::new(self.width(), self.height()),
503 );
504
505 *self.inner.background_path.borrow_mut() = Some(builder.build());
506 }
507 }
508
509 pub fn update_components(&self) -> bool {
510 let component = self.as_component();
511 if component.has_dirt(ComponentDirt::COMPONENTS) {
512 return self.inner.update_components(component);
513 }
514
515 false
516 }
517
518 pub fn advance(&self, _elapsed_seconds: f32) -> bool {
519 self.update_components()
520 }
521
522 pub fn draw(&self, renderer: &mut impl Renderer, transform: Mat) {
523 let mut artboard_transform = Mat {
524 translate_x: self.width() * self.origin_x(),
525 translate_y: self.height() * self.origin_y(),
526 ..Default::default()
527 };
528
529 artboard_transform = artboard_transform * transform;
530
531 for shape_paint in self.cast::<ShapePaintContainer>().shape_paints() {
532 shape_paint.as_ref().draw(
533 renderer,
534 self.inner
535 .background_path
536 .borrow()
537 .as_ref()
538 .expect("background_path should already be set in Artboard"),
539 artboard_transform,
540 );
541 }
542
543 let drawables = iter::successors(self.inner.first_drawable.get(), |drawable| {
544 drawable.as_ref().prev.get()
545 });
546
547 for drawable in drawables {
548 drawable.as_ref().draw(renderer, artboard_transform);
549 }
550 }
551
552 pub fn bounds(&self) -> Aabb {
553 Aabb::new(0.0, 0.0, self.width(), self.height())
554 }
555
556 pub fn animations(&self) -> ObjectsIter<LinearAnimation> {
557 ObjectsIter::new(self.inner.animations.clone())
558 }
559
560 pub fn state_machines(&self) -> ObjectsIter<StateMachine> {
561 ObjectsIter::new(self.inner.state_machines.clone())
562 }
563}
564
565impl Core for Artboard {
566 parent_types![
567 (container_component, ContainerComponent),
568 (shape_paint_container, ShapePaintContainer),
569 ];
570
571 properties![
572 (7, width, set_width),
573 (8, height, set_height),
574 (9, x, set_x),
575 (10, y, set_y),
576 (11, origin_x, set_origin_x),
577 (12, origin_y, set_origin_y),
578 container_component,
579 ];
580}
581
582impl OnAdded for ObjectRef<'_, Artboard> {
583 on_added!(ContainerComponent);
584}
585
586impl CoreContext for ArtboardInner {
587 fn resolve(&self, id: usize) -> Option<Object> {
588 self.objects.borrow().get(id).cloned()
589 }
590}
591
592impl CoreContext for Artboard {
593 fn resolve(&self, id: usize) -> Option<Object> {
594 self.inner.resolve(id)
595 }
596}