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
use crate::{
    component::{
        CompositeRenderDepth, CompositeRenderable, CompositeRenderableStroke, CompositeTransform,
    },
    composite_renderer::{Command, CompositeRenderer, Rectangle, Renderable, Transformation},
};
use core::{
    assets::database::AssetsDatabase,
    ecs::{Entities, Join, Read, ReadStorage, System, Write},
};
use std::marker::PhantomData;

pub struct CompositeRendererSystem<CR>
where
    CR: CompositeRenderer,
{
    _phantom: PhantomData<CR>,
}

impl<CR> Default for CompositeRendererSystem<CR>
where
    CR: CompositeRenderer,
{
    fn default() -> Self {
        Self {
            _phantom: PhantomData,
        }
    }
}

impl<'s, CR> System<'s> for CompositeRendererSystem<CR>
where
    CR: CompositeRenderer + Send + Sync + 'static,
{
    type SystemData = (
        Option<Write<'s, CR>>,
        Entities<'s>,
        Option<Read<'s, AssetsDatabase>>,
        ReadStorage<'s, CompositeRenderable>,
        ReadStorage<'s, CompositeTransform>,
        ReadStorage<'s, CompositeRenderDepth>,
        ReadStorage<'s, CompositeRenderableStroke>,
    );

    fn run(
        &mut self,
        (renderer, entities, assets, renderables, transforms, depths, strokes): Self::SystemData,
    ) {
        if renderer.is_none() {
            return;
        }

        let renderer: &mut CR = &mut renderer.unwrap();
        if let Some(assets) = &assets {
            renderer.update_cache(assets);
        }
        renderer.update_state();
        let viewport = renderer.viewport();
        let mut sorted = (&entities, &renderables, &transforms)
            .join()
            .map(|(entity, renderable, transform)| {
                let depth = if let Some(depth) = depths.get(entity) {
                    depth.0
                } else {
                    0.0
                };
                (depth, renderable, transform, entity)
            })
            .collect::<Vec<_>>();
        sorted.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
        let commands = std::iter::once(if let Some(color) = renderer.state().clear_color {
            Command::Draw(Renderable::Rectangle(Rectangle {
                color,
                rect: viewport,
            }))
        } else {
            Command::None
        })
        .chain(
            sorted
                .iter()
                .flat_map(|(_, renderable, transform, entity)| {
                    let renderable = if let Some(stroke) = strokes.get(*entity) {
                        Command::Stroke(stroke.0, renderable.0.clone())
                    } else {
                        Command::Draw(renderable.0.clone())
                    };
                    vec![
                        Command::Store,
                        Command::Transform(Transformation::Translate(transform.translation)),
                        Command::Transform(Transformation::Rotate(transform.rotation)),
                        Command::Transform(Transformation::Scale(transform.scale)),
                        renderable,
                        Command::Restore,
                    ]
                }),
        );

        drop(renderer.execute(commands));
    }
}