Skip to main content

scenix_material/
line.rs

1use scenix_core::Color;
2
3use crate::{
4    AlphaMode, FEATURE_DASHED, FEATURE_WORLD_SPACE, Material, PipelineAlphaMode, PipelineKey,
5    ShaderKind,
6};
7
8/// Line material with optional dash pattern.
9#[derive(Clone, Copy, Debug, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct LineMaterial {
12    /// Line color in linear RGBA.
13    pub color: Color,
14    /// Line width in logical pixels unless `world_units` is true.
15    pub width: f32,
16    /// Dash length. `0.0` disables dashed rendering.
17    pub dash_size: f32,
18    /// Gap length between dashes.
19    pub gap_size: f32,
20    /// Interpret width in world units instead of logical pixels.
21    pub world_units: bool,
22    /// Alpha behavior.
23    pub alpha_mode: AlphaMode,
24}
25
26impl LineMaterial {
27    /// Creates a default one-pixel white line material.
28    #[inline]
29    pub const fn new() -> Self {
30        Self {
31            color: Color::WHITE,
32            width: 1.0,
33            dash_size: 0.0,
34            gap_size: 0.0,
35            world_units: false,
36            alpha_mode: AlphaMode::Opaque,
37        }
38    }
39
40    /// Returns this material with a dash pattern.
41    #[inline]
42    pub fn dashed(mut self, dash_size: f32, gap_size: f32) -> Self {
43        self.dash_size = dash_size.max(0.0);
44        self.gap_size = gap_size.max(0.0);
45        self
46    }
47}
48
49impl Default for LineMaterial {
50    #[inline]
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl Material for LineMaterial {
57    #[inline]
58    fn pipeline_key(&self) -> PipelineKey {
59        let mut bits = 0;
60        if self.dash_size > 0.0 && self.gap_size > 0.0 {
61            bits |= FEATURE_DASHED;
62        }
63        if self.world_units {
64            bits |= FEATURE_WORLD_SPACE;
65        }
66        let alpha = if self.color.a < 1.0 {
67            PipelineAlphaMode::Blend
68        } else {
69            self.alpha_mode.pipeline_alpha()
70        };
71        PipelineKey::new(ShaderKind::Line, alpha, bits)
72    }
73
74    #[inline]
75    fn is_transparent(&self) -> bool {
76        self.alpha_mode.is_transparent() || self.color.a < 1.0
77    }
78
79    #[inline]
80    fn double_sided(&self) -> bool {
81        true
82    }
83
84    #[inline]
85    fn alpha_cutoff(&self) -> Option<f32> {
86        self.alpha_mode.cutoff()
87    }
88}