microcad_lang/render/
attribute.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Render attributes.
5
6use derive_more::Deref;
7use microcad_core::Color;
8
9use crate::model::{Attributes, Model};
10
11/// An attribute that can be used by any renderer.
12///
13/// *Note: Render color is the only supported attribute for now.*
14#[derive(Clone, Debug)]
15pub enum RenderAttribute {
16    /// Color attribute.
17    Color(Color),
18}
19
20impl RenderAttribute {
21    fn same_variant(&self, other: &Self) -> bool {
22        matches!(
23            (self, other),
24            (RenderAttribute::Color(_), RenderAttribute::Color(_))
25        )
26    }
27}
28
29/// A list of render attributes.
30///
31/// Each enum variant of [`RenderAttribute`] can only be present at most once in the attribute list.
32#[derive(Clone, Debug, Default, Deref)]
33pub struct RenderAttributes(Vec<RenderAttribute>);
34
35impl RenderAttributes {
36    /// Insert a render attribute and overwrite old attribute if present.
37    pub fn insert(&mut self, attr: RenderAttribute) {
38        // remove existing variant of the same type
39        self.0.retain(|a| !a.same_variant(&attr));
40        self.0.push(attr);
41    }
42
43    /// Get color from color attribute, if any.
44    pub fn get_color(&self) -> Option<&Color> {
45        self.0
46            .iter()
47            .map(|attr| match attr {
48                RenderAttribute::Color(color) => color,
49            })
50            .next()
51    }
52}
53
54impl From<&Attributes> for RenderAttributes {
55    fn from(attributes: &Attributes) -> Self {
56        use crate::model::Attribute;
57        let mut render_attributes = RenderAttributes::default();
58        attributes.iter().for_each(|attr| {
59            if let Attribute::Color(color) = attr {
60                render_attributes.insert(RenderAttribute::Color(*color))
61            }
62        });
63
64        render_attributes
65    }
66}
67
68impl From<&Model> for RenderAttributes {
69    fn from(model: &Model) -> Self {
70        let model_ = model.borrow();
71        let mut render_attributes: RenderAttributes = model_.attributes().into();
72
73        if render_attributes.is_empty() {
74            if let Some(child) = model_.children.single_model() {
75                render_attributes = child.borrow().attributes().into();
76            }
77        }
78
79        render_attributes
80    }
81}