ranim_core/core_item/
vitem.rs

1use color::{AlphaColor, Srgb};
2use glam::{Vec3, Vec4};
3
4use crate::{
5    Extract,
6    components::{rgba::Rgba, width::Width},
7    core_item::CoreItem,
8    traits::FillColor,
9};
10
11/// Default vitem stroke width
12pub const DEFAULT_STROKE_WIDTH: f32 = 0.02;
13
14/// Compute the normal vector from the first three points of a VItem.
15/// Falls back to Z axis if the first three points are collinear.
16pub fn vitem_normal_from_points(points: &[Vec4]) -> Vec3 {
17    if points.len() < 3 {
18        return Vec3::Z;
19    }
20    let p0 = Vec3::new(points[0].x, points[0].y, points[0].z);
21    let p1 = Vec3::new(points[1].x, points[1].y, points[1].z);
22    let p2 = Vec3::new(points[2].x, points[2].y, points[2].z);
23    let n = (p1 - p0).cross(p2 - p0);
24    if n.length_squared() < 1e-6 {
25        Vec3::Z
26    } else {
27        n.normalize()
28    }
29}
30
31#[derive(Debug, Clone, PartialEq)]
32/// A primitive for rendering a vitem.
33pub struct VItem {
34    /// The normal vector of the projection target plane.
35    /// If `None`, the normal will be computed from the first three points at render time.
36    pub normal: Option<Vec3>,
37    /// The points of the item in world space.
38    /// (x, y, z, is_closed)
39    pub points: Vec<Vec4>,
40    /// Fill rgbas, see [`Rgba`].
41    pub fill_rgbas: Vec<Rgba>,
42    /// Stroke rgbs, see [`Rgba`].
43    pub stroke_rgbas: Vec<Rgba>,
44    /// Stroke widths, see [`Width`].
45    pub stroke_widths: Vec<Width>,
46}
47
48impl Default for VItem {
49    fn default() -> Self {
50        Self {
51            normal: None,
52            points: vec![Vec4::ZERO; 3],
53            stroke_widths: vec![Width::default(); 2],
54            stroke_rgbas: vec![Rgba::default(); 2],
55            fill_rgbas: vec![Rgba::default(); 2],
56        }
57    }
58}
59
60impl Extract for VItem {
61    type Target = CoreItem;
62    fn extract_into(&self, buf: &mut Vec<Self::Target>) {
63        buf.push(CoreItem::VItem(self.clone()));
64    }
65}
66
67impl FillColor for VItem {
68    fn fill_color(&self) -> AlphaColor<Srgb> {
69        let Rgba(rgba) = self.fill_rgbas[0];
70        AlphaColor::new([rgba.x, rgba.y, rgba.z, rgba.w])
71    }
72    fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
73        self.fill_rgbas.fill(color.into());
74        self
75    }
76    fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
77        self.fill_rgbas
78            .iter_mut()
79            .for_each(|rgba| rgba.0.w = opacity);
80        self
81    }
82}