scene.rs

  1use crate::{text::GlyphId, FontId};
  2
  3use super::{Bounds, Hsla, Pixels, Point};
  4use bytemuck::{Pod, Zeroable};
  5use plane_split::BspSplitter;
  6
  7pub struct Scene {
  8    opaque_primitives: PrimitiveBatch,
  9    transparent_primitives: slotmap::SlotMap<slotmap::DefaultKey, Primitive>,
 10    splitter: BspSplitter<slotmap::DefaultKey>,
 11}
 12
 13impl Scene {
 14    pub fn new() -> Scene {
 15        Scene {
 16            opaque_primitives: PrimitiveBatch::default(),
 17            transparent_primitives: slotmap::SlotMap::new(),
 18            splitter: BspSplitter::new(),
 19        }
 20    }
 21
 22    pub fn insert(&mut self, primitive: impl Into<Primitive>, is_transparent: bool) {
 23        if is_transparent {
 24            self.transparent_primitives.insert(primitive.into());
 25        } else {
 26            match primitive.into() {
 27                Primitive::Quad(quad) => self.opaque_primitives.quads.push(quad),
 28                Primitive::Glyph(glyph) => self.opaque_primitives.glyphs.push(glyph),
 29                Primitive::Underline(underline) => {
 30                    self.opaque_primitives.underlines.push(underline)
 31                }
 32            }
 33        }
 34    }
 35
 36    pub fn opaque_primitives(&self) -> &PrimitiveBatch {
 37        &self.opaque_primitives
 38    }
 39}
 40
 41#[derive(Clone, Debug)]
 42pub enum Primitive {
 43    Quad(Quad),
 44    Glyph(RenderedGlyph),
 45    Underline(Underline),
 46}
 47
 48impl Primitive {
 49    pub fn is_transparent(&self) -> bool {
 50        match self {
 51            Primitive::Quad(quad) => {
 52                quad.background.is_transparent() && quad.border_color.is_transparent()
 53            }
 54            Primitive::Glyph(glyph) => glyph.color.is_transparent(),
 55            Primitive::Underline(underline) => underline.color.is_transparent(),
 56        }
 57    }
 58}
 59
 60#[derive(Default)]
 61pub struct PrimitiveBatch {
 62    pub quads: Vec<Quad>,
 63    pub glyphs: Vec<RenderedGlyph>,
 64    pub underlines: Vec<Underline>,
 65}
 66
 67#[derive(Debug, Clone, Copy)]
 68#[repr(C)]
 69pub struct Quad {
 70    pub order: f32,
 71    pub bounds: Bounds<Pixels>,
 72    pub background: Hsla,
 73    pub border_color: Hsla,
 74    pub corner_radius: Pixels,
 75    pub border_left: Pixels,
 76    pub border_right: Pixels,
 77    pub border_top: Pixels,
 78    pub border_bottom: Pixels,
 79}
 80
 81impl Quad {
 82    pub fn vertices(&self) -> impl Iterator<Item = Point<Pixels>> {
 83        let x1 = self.bounds.origin.x;
 84        let y1 = self.bounds.origin.y;
 85        let x2 = x1 + self.bounds.size.width;
 86        let y2 = y1 + self.bounds.size.height;
 87        [
 88            Point::new(x1, y1),
 89            Point::new(x2, y1),
 90            Point::new(x2, y2),
 91            Point::new(x1, y2),
 92        ]
 93        .into_iter()
 94    }
 95}
 96
 97unsafe impl Zeroable for Quad {}
 98
 99unsafe impl Pod for Quad {}
100
101impl From<Quad> for Primitive {
102    fn from(quad: Quad) -> Self {
103        Primitive::Quad(quad)
104    }
105}
106
107#[derive(Debug, Clone, Copy)]
108#[repr(C)]
109pub struct RenderedGlyph {
110    pub font_id: FontId,
111    pub font_size: f32,
112    pub id: GlyphId,
113    pub origin: Point<Pixels>,
114    pub color: Hsla,
115}
116
117impl From<RenderedGlyph> for Primitive {
118    fn from(glyph: RenderedGlyph) -> Self {
119        Primitive::Glyph(glyph)
120    }
121}
122
123#[derive(Copy, Clone, Default, Debug)]
124#[repr(C)]
125pub struct Underline {
126    pub origin: Point<Pixels>,
127    pub width: Pixels,
128    pub thickness: Pixels,
129    pub color: Hsla,
130    pub squiggly: bool,
131}
132
133unsafe impl Zeroable for Underline {}
134
135unsafe impl Pod for Underline {}
136
137impl From<Underline> for Primitive {
138    fn from(underline: Underline) -> Self {
139        Primitive::Underline(underline)
140    }
141}