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}