Skip to main content

lotus_shared/
graphics.rs

1//! Farben und Typen zum Zeichnen auf Script-Texturen.
2//!
3//! Colors and script texture drawing types.
4
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "internal")]
8use crate::content::ContentId;
9
10/// Eine Farbe im RGBA-Format.
11///
12/// A color in the RGBA format.
13#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
14pub struct Color {
15    /// Rotkanal, 0–255.
16    ///
17    /// Red channel, 0–255.
18    pub r: u8,
19    /// Grünkanal, 0–255.
20    ///
21    /// Green channel, 0–255.
22    pub g: u8,
23    /// Blaukanal, 0–255.
24    ///
25    /// Blue channel, 0–255.
26    pub b: u8,
27    /// Alphakanal, 0–255.
28    ///
29    /// Alpha channel, 0–255.
30    pub a: u8,
31}
32
33impl Color {
34    /// Deckendes Weiß.
35    ///
36    /// Opaque white.
37    pub const WHITE: Self = Self::rgb(255, 255, 255);
38    /// Deckendes Schwarz.
39    ///
40    /// Opaque black.
41    pub const BLACK: Self = Self::rgb(0, 0, 0);
42    /// Deckendes Rot.
43    ///
44    /// Opaque red.
45    pub const RED: Self = Self::rgb(255, 0, 0);
46    /// Deckendes Grün.
47    ///
48    /// Opaque green.
49    pub const GREEN: Self = Self::rgb(0, 255, 0);
50    /// Deckendes Blau.
51    ///
52    /// Opaque blue.
53    pub const BLUE: Self = Self::rgb(0, 0, 255);
54    /// Deckendes Gelb.
55    ///
56    /// Opaque yellow.
57    pub const YELLOW: Self = Self::rgb(255, 255, 0);
58    /// Deckendes Cyan.
59    ///
60    /// Opaque cyan.
61    pub const CYAN: Self = Self::rgb(0, 255, 255);
62    /// Deckendes Magenta.
63    ///
64    /// Opaque magenta.
65    pub const MAGENTA: Self = Self::rgb(255, 0, 255);
66
67    /// Erstellt eine deckende RGB-Farbe.
68    ///
69    /// Creates an opaque RGB color.
70    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
71        Self::rgba(r, g, b, 255)
72    }
73
74    /// Erstellt eine RGBA-Farbe.
75    ///
76    /// Creates an RGBA color.
77    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
78        Self { r, g, b, a }
79    }
80}
81
82impl From<u32> for Color {
83    fn from(value: u32) -> Self {
84        let r = ((value >> 24) & 0xFF) as u8;
85        let g = ((value >> 16) & 0xFF) as u8;
86        let b = ((value >> 8) & 0xFF) as u8;
87        let a = (value & 0xFF) as u8;
88
89        Color::rgba(r, g, b, a)
90    }
91}
92
93impl From<Color> for u32 {
94    fn from(value: Color) -> Self {
95        let r = value.r as u32;
96        let g = value.g as u32;
97        let b = value.b as u32;
98        let a = value.a as u32;
99
100        (r << 24) | (g << 16) | (b << 8) | a
101    }
102}
103
104#[cfg(feature = "bevy")]
105mod _bevy {
106    use super::*;
107
108    impl From<bevy::color::Color> for Color {
109        fn from(value: bevy::color::Color) -> Self {
110            let value = value.to_srgba();
111
112            Self::rgba(
113                (value.red * 255.0) as u8,
114                (value.green * 255.0) as u8,
115                (value.blue * 255.0) as u8,
116                (value.alpha * 255.0) as u8,
117            )
118        }
119    }
120
121    impl From<Color> for bevy::color::Color {
122        fn from(value: Color) -> Self {
123            bevy::color::Color::srgba(
124                value.r as f32 / 255.0,
125                value.g as f32 / 255.0,
126                value.b as f32 / 255.0,
127                value.a as f32 / 255.0,
128            )
129        }
130    }
131}
132
133#[cfg(feature = "image")]
134mod _image {
135    use super::*;
136
137    impl From<image::Rgba<u8>> for Color {
138        fn from(value: image::Rgba<u8>) -> Self {
139            Self::rgba(value[0], value[1], value[2], value[3])
140        }
141    }
142
143    impl From<Color> for image::Rgba<u8> {
144        fn from(value: Color) -> Self {
145            [value.r, value.g, value.b, value.a].into()
146        }
147    }
148}
149
150/// Erstellung und Zeichenbefehle für Script-Texturen.
151///
152/// Script texture creation and drawing commands.
153pub mod textures {
154    use std::borrow::Cow;
155
156    use glam::IVec2;
157    use serde::{Deserialize, Serialize};
158
159    use crate::{
160        content::ContentId,
161        math::{Rectangle, UVec2},
162    };
163
164    use super::Color;
165
166    /// Optionen zum Erstellen einer Textur.
167    ///
168    /// Options for creating a texture.
169    #[derive(Clone, Serialize, Deserialize)]
170    pub struct TextureCreationOptions<'a> {
171        /// Breite der Textur.
172        ///
173        /// The width of the texture.
174        pub width: u32,
175        /// Höhe der Textur.
176        ///
177        /// The height of the texture.
178        pub height: u32,
179        /// Texturdaten; derzeit Platzhalter für künftige Verwendung.
180        ///
181        /// The data of the texture. This is currently a placeholder for future use.
182        pub data: Option<Cow<'a, [u8]>>,
183        /// Ob für die Textur Mipmaps erzeugt werden sollen.
184        ///
185        /// Whether to generate mipmaps for the texture.
186        pub mipmaps: bool,
187    }
188
189    impl From<(u32, u32)> for TextureCreationOptions<'_> {
190        fn from((width, height): (u32, u32)) -> Self {
191            Self {
192                width,
193                height,
194                data: None,
195                mipmaps: false,
196            }
197        }
198    }
199
200    /// Handle auf eine Textur.
201    ///
202    /// A handle to a texture.
203    #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
204    #[serde(transparent)]
205    pub struct TextureHandle(u32);
206
207    impl TextureHandle {
208        /// Erstellt einen neuen Textur-Handle.
209        ///
210        /// Create a new texture handle.
211        pub fn new(value: u32) -> Self {
212            Self(value)
213        }
214
215        /// Gibt die ID des Textur-Handles zurück.
216        ///
217        /// Get the ID of the texture handle.
218        pub fn id(&self) -> u32 {
219            self.0
220        }
221    }
222
223    /// Aktion, die auf einer Textur ausgeführt wird.
224    ///
225    /// An action to perform on a texture.
226    #[derive(Clone, Serialize, Deserialize)]
227    pub enum TextureAction {
228        /// Füllt die Textur mit einer Farbe.
229        ///
230        /// Clear the texture with a color.
231        Clear(Color),
232        /// Zeichnet Pixel auf die Textur.
233        ///
234        /// Draw pixels on the texture.
235        DrawPixels(Box<[DrawPixel]>),
236        /// Zeichnet ein Rechteck auf die Textur.
237        ///
238        /// Draw a rectangle on the texture.
239        DrawRect {
240            /// Obere linke Ecke des Rechtecks.
241            ///
242            /// Top-left corner of the rectangle.
243            start: UVec2,
244            /// Untere rechte Ecke des Rechtecks.
245            ///
246            /// Bottom-right corner of the rectangle.
247            end: UVec2,
248            /// Füllfarbe des Rechtecks.
249            ///
250            /// Fill color of the rectangle.
251            color: Color,
252        },
253        /// Zeichnet Text auf die Textur.
254        ///
255        /// Draw text on the texture.
256        DrawText {
257            /// Schrift zum Rendern des Textes.
258            ///
259            /// Font used to render the text.
260            font: ContentId,
261            /// Zu zeichnender Text.
262            ///
263            /// Text string to draw.
264            text: String,
265            /// Obere linke Textposition in Pixeln.
266            ///
267            /// Top-left position of the text in pixels.
268            top_left: IVec2,
269            /// Zusätzlicher Buchstabenabstand in Pixeln.
270            ///
271            /// Additional spacing between letters in pixels.
272            letter_spacing: u32,
273            /// Optionale Überschreibungsfarbe für den gesamten Text.
274            ///
275            /// Optional override color for the entire text.
276            full_color: Option<Color>,
277            /// Alpha-Mischmodus für den Text.
278            ///
279            /// Alpha blending mode for the text.
280            alpha_mode: AlphaMode,
281            /// Optionales Ziel-/Clip-Rechteck für den Text.
282            ///
283            /// Optional clipping/target rectangle for the text.
284            target_rect: Option<Rectangle>,
285        },
286        // DrawTexture {
287        //     texture: ContentId,
288        //     options: DrawTextureOpts,
289        // },
290        /// Zeichnet eine Script-Textur auf die Textur.
291        ///
292        /// Draw a script texture on the texture.
293        DrawScriptTexture {
294            /// Handle der Quell-Script-Textur.
295            ///
296            /// Handle of the source script texture.
297            handle: TextureHandle,
298            /// Zeichenoptionen wie Quell- und Zielrechteck.
299            ///
300            /// Drawing options such as source and target rectangles.
301            options: DrawTextureOpts,
302        },
303    }
304
305    /// Steuert die Alpha-Behandlung beim Zeichnen.
306    ///
307    /// Controls how alpha (transparency) is handled when drawing.
308    #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
309    pub enum AlphaMode {
310        /// Textur wird deckend gezeichnet; Alphawerte werden ignoriert.
311        /// Gezeichnete Pixel ersetzen vorhandene Pixel vollständig.
312        ///
313        /// The texture is drawn completely opaque, ignoring alpha values.
314        /// Any pixels drawn will completely replace the existing pixels.
315        #[default]
316        Opaque,
317        /// Alphawerte unter dem Schwellwert gelten als vollständig transparent,
318        /// Werte ab dem Schwellwert als vollständig deckend.
319        /// Der Schwellwert sollte zwischen 0.0 und 1.0 liegen.
320        ///
321        /// Alpha values below the threshold are considered fully transparent,
322        /// while values above or equal to the threshold are considered fully opaque.
323        /// The threshold should be between 0.0 and 1.0.
324        Mask(f32),
325        /// Alphawerte werden zum Mischen mit vorhandenen Pixeln verwendet.
326        /// Der Alphakanal bestimmt die Deckkraft jedes gezeichneten Pixels.
327        ///
328        /// Alpha values are used to blend the new pixels with existing pixels.
329        /// The alpha channel determines the opacity of each pixel being drawn.
330        Blend,
331    }
332
333    /// Optionen zum Zeichnen einer Textur.
334    ///
335    /// Options for drawing a texture.
336    #[derive(Default, Clone, Copy, Serialize, Deserialize)]
337    pub struct DrawTextureOpts {
338        /// Quellrechteck des zu zeichnenden Texturausschnitts.
339        ///
340        /// The source rectangle of the texture to draw.
341        pub source_rect: Option<Rectangle>,
342        /// Zielrechteck auf der Zieltextur.
343        ///
344        /// The target rectangle of the texture to draw to.
345        pub target_rect: Option<Rectangle>,
346    }
347
348    /// Ein Pixel, der auf eine Textur gezeichnet wird.
349    ///
350    /// A pixel to draw on a texture.
351    #[derive(Clone, Copy, Serialize, Deserialize)]
352    pub struct DrawPixel {
353        /// Position des Pixels.
354        ///
355        /// The position of the pixel.
356        pub pos: UVec2,
357        /// Farbe des Pixels.
358        ///
359        /// The color of the pixel.
360        pub color: Color,
361    }
362
363    impl From<(UVec2, Color)> for DrawPixel {
364        fn from((position, color): (UVec2, Color)) -> Self {
365            Self {
366                pos: position,
367                color,
368            }
369        }
370    }
371
372    impl From<(u32, u32, Color)> for DrawPixel {
373        fn from((x, y, color): (u32, u32, Color)) -> Self {
374            Self {
375                pos: UVec2 { x, y },
376                color,
377            }
378        }
379    }
380}
381
382/// Eigenschaften eines zeichenbaren Textur-Slots, der an Script-Variablen gebunden ist.
383///
384/// Properties of a drawable game texture slot bound to script variables.
385#[cfg(feature = "internal")]
386#[derive(Debug, Clone, Serialize, Deserialize)]
387pub struct DrawableTextureProperties {
388    /// Texturbreite in Pixeln.
389    ///
390    /// Texture width in pixels.
391    pub width: u32,
392    /// Texturhöhe in Pixeln.
393    ///
394    /// Texture height in pixels.
395    pub height: u32,
396    /// Variablenname für die Textur-ID bzw. den Handle.
397    ///
398    /// Variable name holding the texture content id or handle.
399    pub texture_variable_id: String,
400    /// Schrift zum Zeichnen von Text auf die Textur.
401    ///
402    /// Font used when drawing text onto the texture.
403    pub font: ContentId,
404    /// Variablenname für den zu zeichnenden Text.
405    ///
406    /// Variable name holding the text to draw.
407    pub text_variable_id: String,
408    /// Ob eine benutzerdefinierte Textfarbe verwendet werden soll.
409    ///
410    /// Whether a custom text color should be applied.
411    pub set_color: bool,
412    /// Textfarbe, wenn [`set_color`](Self::set_color) aktiv ist.
413    ///
414    /// Text color when [`set_color`](Self::set_color) is true.
415    pub color: Color,
416    /// Horizontale Textausrichtung.
417    ///
418    /// Horizontal text alignment.
419    pub horizontal_alignment: TextHorizontalAlignment,
420    /// Vertikale Textausrichtung.
421    ///
422    /// Vertical text alignment.
423    pub vertical_alignment: TextVerticalAlignment,
424    /// Auflösung des Ausrichtungsrasters im Content-Tool.
425    ///
426    /// Alignment grid resolution used by the content tool.
427    pub alignment_resolution: u8,
428}
429
430/// Horizontale Textausrichtung auf zeichenbaren Texturen.
431///
432/// Horizontal alignment of text on drawable textures.
433#[cfg(feature = "internal")]
434#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
435pub enum TextHorizontalAlignment {
436    /// Horizontal zentriert.
437    ///
438    /// Centered horizontally.
439    #[default]
440    Center,
441    /// Am linken Rand ausgerichtet.
442    ///
443    /// Aligned to the left edge.
444    Left,
445    /// Am rechten Rand ausgerichtet.
446    ///
447    /// Aligned to the right edge.
448    Right,
449    /// Ganzzahlig zentriert mit Tendenz nach links.
450    ///
451    /// Integer-centered with bias to the left.
452    IntCenterLeft,
453    /// Ganzzahlig zentriert mit Tendenz nach rechts.
454    ///
455    /// Integer-centered with bias to the right.
456    IntCenterRight,
457}
458
459/// Vertikale Textausrichtung auf zeichenbaren Texturen.
460///
461/// Vertical alignment of text on drawable textures.
462#[cfg(feature = "internal")]
463#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
464pub enum TextVerticalAlignment {
465    /// Vertikal zentriert.
466    ///
467    /// Centered vertically.
468    #[default]
469    Center,
470    /// Am oberen Rand ausgerichtet.
471    ///
472    /// Aligned to the top edge.
473    Top,
474    /// Am unteren Rand ausgerichtet.
475    ///
476    /// Aligned to the bottom edge.
477    Bottom,
478}