lotus_shared/
graphics.rs

1use serde::{Deserialize, Serialize};
2
3/// A color in the RGBA format.
4#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
5pub struct Color {
6    pub r: u8,
7    pub g: u8,
8    pub b: u8,
9    pub a: u8,
10}
11
12impl Color {
13    pub const WHITE: Self = Self::rgb(255, 255, 255);
14    pub const BLACK: Self = Self::rgb(0, 0, 0);
15    pub const RED: Self = Self::rgb(255, 0, 0);
16    pub const GREEN: Self = Self::rgb(0, 255, 0);
17    pub const BLUE: Self = Self::rgb(0, 0, 255);
18    pub const YELLOW: Self = Self::rgb(255, 255, 0);
19    pub const CYAN: Self = Self::rgb(0, 255, 255);
20    pub const MAGENTA: Self = Self::rgb(255, 0, 255);
21
22    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
23        Self::rgba(r, g, b, 255)
24    }
25
26    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
27        Self { r, g, b, a }
28    }
29}
30
31impl From<u32> for Color {
32    fn from(value: u32) -> Self {
33        let r = ((value >> 24) & 0xFF) as u8;
34        let g = ((value >> 16) & 0xFF) as u8;
35        let b = ((value >> 8) & 0xFF) as u8;
36        let a = (value & 0xFF) as u8;
37
38        Color::rgba(r, g, b, a)
39    }
40}
41
42impl From<Color> for u32 {
43    fn from(value: Color) -> Self {
44        let r = value.r as u32;
45        let g = value.g as u32;
46        let b = value.b as u32;
47        let a = value.a as u32;
48
49        (r << 24) | (g << 16) | (b << 8) | a
50    }
51}
52
53#[cfg(feature = "bevy")]
54mod _bevy {
55    use super::*;
56
57    impl From<bevy::color::Color> for Color {
58        fn from(value: bevy::color::Color) -> Self {
59            let value = value.to_srgba();
60
61            Self::rgba(
62                (value.red * 255.0) as u8,
63                (value.green * 255.0) as u8,
64                (value.blue * 255.0) as u8,
65                (value.alpha * 255.0) as u8,
66            )
67        }
68    }
69
70    impl From<Color> for bevy::color::Color {
71        fn from(value: Color) -> Self {
72            bevy::color::Color::srgba(
73                value.r as f32 / 255.0,
74                value.g as f32 / 255.0,
75                value.b as f32 / 255.0,
76                value.a as f32 / 255.0,
77            )
78        }
79    }
80}
81
82#[cfg(feature = "image")]
83mod _image {
84    use super::*;
85
86    impl From<image::Rgba<u8>> for Color {
87        fn from(value: image::Rgba<u8>) -> Self {
88            Self::rgba(value[0], value[1], value[2], value[3])
89        }
90    }
91
92    impl From<Color> for image::Rgba<u8> {
93        fn from(value: Color) -> Self {
94            [value.r, value.g, value.b, value.a].into()
95        }
96    }
97}
98
99pub mod textures {
100    use std::borrow::Cow;
101
102    use serde::{Deserialize, Serialize};
103
104    use crate::{
105        content::ContentId,
106        math::{Rectangle, UVec2},
107    };
108
109    use super::Color;
110
111    /// Options for creating a texture.
112    #[derive(Clone, Serialize, Deserialize)]
113    pub struct TextureCreationOptions<'a> {
114        /// The width of the texture.
115        pub width: u32,
116        /// The height of the texture.
117        pub height: u32,
118        /// The data of the texture. This is currently a placeholder for future use.
119        pub data: Option<Cow<'a, [u8]>>,
120    }
121
122    /// A handle to a texture.
123    #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
124    #[serde(transparent)]
125    pub struct TextureHandle(u32);
126
127    #[cfg(feature = "internal")]
128    impl TextureHandle {
129        /// Create a new texture handle.
130        pub fn new(value: u32) -> Self {
131            Self(value)
132        }
133
134        /// Get the ID of the texture handle.
135        pub fn id(&self) -> u32 {
136            self.0
137        }
138    }
139
140    /// An action to perform on a texture.
141    #[derive(Clone, Serialize, Deserialize)]
142    pub enum TextureAction {
143        /// Clear the texture with a color.
144        Clear(Color),
145        /// Draw pixels on the texture.
146        DrawPixels(Box<[DrawPixel]>),
147        /// Draw a rectangle on the texture.
148        DrawRect {
149            start: UVec2,
150            end: UVec2,
151            color: Color,
152        },
153        /// Draw text on the texture.
154        DrawText {
155            font: ContentId,
156            text: String,
157            top_left: UVec2,
158            letter_spacing: u32,
159            full_color: Option<Color>,
160            alpha_mode: AlphaMode,
161        },
162        // DrawTexture {
163        //     texture: ContentId,
164        //     options: DrawTextureOpts,
165        // },
166        /// Draw a script texture on the texture.
167        DrawScriptTexture {
168            handle: TextureHandle,
169            options: DrawTextureOpts,
170        },
171    }
172
173    /// Controls how alpha (transparency) is handled when drawing.
174    #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
175    pub enum AlphaMode {
176        /// The texture is drawn completely opaque, ignoring alpha values.
177        /// Any pixels drawn will completely replace the existing pixels.
178        #[default]
179        Opaque,
180        /// Alpha values below the threshold are considered fully transparent,
181        /// while values above or equal to the threshold are considered fully opaque.
182        /// The threshold should be between 0.0 and 1.0.
183        Mask(f32),
184        /// Alpha values are used to blend the new pixels with existing pixels.
185        /// The alpha channel determines the opacity of each pixel being drawn.
186        Blend,
187    }
188
189    /// Options for drawing a texture.
190    #[derive(Default, Clone, Copy, Serialize, Deserialize)]
191    pub struct DrawTextureOpts {
192        /// The source rectangle of the texture to draw.
193        pub source_rect: Option<Rectangle>,
194        /// The target rectangle of the texture to draw to.
195        pub target_rect: Option<Rectangle>,
196    }
197
198    /// A pixel to draw on a texture.
199    #[derive(Clone, Copy, Serialize, Deserialize)]
200    pub struct DrawPixel {
201        /// The position of the pixel.
202        pub pos: UVec2,
203        /// The color of the pixel.
204        pub color: Color,
205    }
206
207    impl From<(UVec2, Color)> for DrawPixel {
208        fn from((position, color): (UVec2, Color)) -> Self {
209            Self {
210                pos: position,
211                color,
212            }
213        }
214    }
215
216    impl From<(u32, u32, Color)> for DrawPixel {
217        fn from((x, y, color): (u32, u32, Color)) -> Self {
218            Self {
219                pos: UVec2 { x, y },
220                color,
221            }
222        }
223    }
224}