summaryrefslogtreecommitdiffstats
path: root/core/src/runtime.rs
blob: bfb31fa7454e0ee14d2b886c8916cb81ce4ab683 (plain)
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
use super::complex_shapes::{ComplexShape, Drawable, DynDrawable};
use super::rendering::Renderer;
use super::solving::{Constrainable, SolverContext};

const RECURSION_LIMIT: u64 = 10_000;

pub struct Runtime<'a> {
    solver_ctx: Box<dyn SolverContext + 'a>,
    renderer: Box<dyn Renderer>,
    drawables: Vec<DynDrawable>,
}

impl<'a> Runtime<'a> {
    pub fn new(solver_ctx: Box<dyn SolverContext + 'a>, renderer: Box<dyn Renderer>) -> Self {
        Self {
            solver_ctx,
            renderer,
            drawables: Vec::new(),
        }
    }

    pub fn add_drawable<T: ComplexShape + 'static>(&mut self, drawable: Drawable<T>) {
        self.drawables.push(drawable.into())
    }

    pub fn solver_ctx(&mut self) -> &mut (dyn SolverContext + 'a) {
        &mut *self.solver_ctx
    }

    // TODO: preserve ordering of shapes
    pub fn render(mut self) {
        let mut drawables = self.drawables;
        let mut waited_on_variables = Vec::new();
        let mut core_shapes = Vec::new();

        /*
        for drawable in &self.shapes {
            let bounds = &drawable.bounds;
            let shape = &drawable.shape;

            if let Some(core_shape) = shape.to_render() {
                drawables.push((*drawable).clone());
                continue;
            }

            let mut result = shape.draw(bounds);
            drawables.append(&mut result.subshapes);
            waited_on_variables.append(&mut result.waiting_on);
        }
        */

        let mut recursion_count = 0;

        while !drawables.is_empty() {
            recursion_count += 1;

            if recursion_count > RECURSION_LIMIT {
                panic!("Recursion limit reached");
            }

            let mut tmp_drawables = Vec::new();

            for drawable in drawables.drain(..) {
                let shape_ctx = &drawable.context;
                let shape = &drawable.shape;

                if let Some(core_shape) = shape.as_core_shape() {
                    core_shape.constrain(shape_ctx, &mut *self.solver_ctx, &*self.renderer);
                    core_shapes.push((shape.dyn_clone(), shape_ctx.clone())); // Better to Arc? Cow?
                    continue;
                }

                let mut result = shape.draw(shape_ctx, &mut *self.solver_ctx);
                tmp_drawables.append(&mut result.subshapes);
                waited_on_variables.append(&mut result.waiting_on);
            }

            drawables = tmp_drawables;
        }

        let model = self.solver_ctx.solve();

        // Delay rendering core shapes until later to have all the constraints
        for (core_shape, shape_ctx) in core_shapes {
            let core_shape = core_shape.as_core_shape().unwrap();

            match (core_shape.to_render(&*model), shape_ctx.fixate(&*model)) {
                (Some(defined_shape), Some(shape_ctx)) => {
                    defined_shape.render(shape_ctx, &mut *self.renderer)
                }
                _ => panic!("Failed to fixate core shape"),
            }
        }
    }
}