spitfire_draw/
utils.rs

1use crate::context::DrawContext;
2use bytemuck::{Pod, Zeroable};
3use fontdue::Font;
4use spitfire_fontdue::TextVertex;
5use spitfire_glow::{
6    graphics::{Graphics, Shader, Texture},
7    renderer::{GlowVertexAttrib, GlowVertexAttribs},
8};
9use std::borrow::Cow;
10use vek::Rgba;
11
12#[derive(Debug, Copy, Clone, Pod, Zeroable)]
13#[repr(C)]
14pub struct Vertex {
15    pub position: [f32; 2],
16    pub uv: [f32; 3],
17    pub color: [f32; 4],
18}
19
20impl Default for Vertex {
21    fn default() -> Self {
22        Self {
23            position: Default::default(),
24            uv: Default::default(),
25            color: [1.0, 1.0, 1.0, 1.0],
26        }
27    }
28}
29
30impl GlowVertexAttribs for Vertex {
31    const ATTRIBS: &'static [(&'static str, GlowVertexAttrib)] = &[
32        (
33            "a_position",
34            GlowVertexAttrib::Float {
35                channels: 2,
36                normalized: false,
37            },
38        ),
39        (
40            "a_uv",
41            GlowVertexAttrib::Float {
42                channels: 3,
43                normalized: false,
44            },
45        ),
46        (
47            "a_color",
48            GlowVertexAttrib::Float {
49                channels: 4,
50                normalized: false,
51            },
52        ),
53    ];
54}
55
56impl TextVertex<Rgba<f32>> for Vertex {
57    fn apply(&mut self, position: [f32; 2], tex_coord: [f32; 3], user_data: Rgba<f32>) {
58        self.position = position;
59        self.uv = tex_coord;
60        self.color = user_data.into_array();
61    }
62}
63
64pub trait Drawable {
65    fn draw(&self, context: &mut DrawContext, graphics: &mut Graphics<Vertex>);
66}
67
68#[derive(Debug, Clone)]
69pub enum ResourceRef<T> {
70    Name(Cow<'static, str>),
71    Object(T),
72}
73
74impl<T> ResourceRef<T> {
75    pub fn name(value: impl Into<Cow<'static, str>>) -> Self {
76        Self::Name(value.into())
77    }
78
79    pub fn object(value: T) -> Self {
80        Self::Object(value)
81    }
82}
83
84impl<T> From<&'static str> for ResourceRef<T> {
85    fn from(value: &'static str) -> Self {
86        Self::name(value)
87    }
88}
89
90pub type ShaderRef = ResourceRef<Shader>;
91pub type TextureRef = ResourceRef<Texture>;
92
93#[derive(Debug, Default, Clone)]
94pub struct FontMap {
95    keys: Vec<Cow<'static, str>>,
96    values: Vec<Font>,
97}
98
99impl FontMap {
100    pub fn insert(&mut self, name: impl Into<Cow<'static, str>>, font: Font) {
101        let name = name.into();
102        if let Some(index) = self.index_of(&name) {
103            self.values[index] = font;
104        } else {
105            self.keys.push(name);
106            self.values.push(font);
107        }
108    }
109
110    pub fn remove(&mut self, name: &str) -> Option<Font> {
111        if let Some(index) = self.index_of(name) {
112            self.keys.remove(index);
113            Some(self.values.remove(index))
114        } else {
115            None
116        }
117    }
118
119    pub fn index_of(&self, name: &str) -> Option<usize> {
120        self.keys.iter().position(|key| key == name)
121    }
122
123    pub fn get(&self, name: &str) -> Option<&Font> {
124        if let Some(index) = self.index_of(name) {
125            self.values.get(index)
126        } else {
127            None
128        }
129    }
130
131    pub fn keys(&self) -> &[Cow<'static, str>] {
132        &self.keys
133    }
134
135    pub fn values(&self) -> &[Font] {
136        &self.values
137    }
138
139    pub fn iter(&self) -> impl Iterator<Item = (&Cow<'static, str>, &Font)> {
140        self.keys.iter().zip(self.values.iter())
141    }
142}