repame_view2d/sprite.rs
1//! Sprite data: one row per drawn quad, its blend, and its tint.
2//!
3//! [`SpriteInstance`] is the input to the instanced batch in [`batch`](crate::batch)
4//! and the output type of the sim-side particle steppers, so both ends of the
5//! snapshot speak it.
6
7use glam::Vec2;
8use repose_core::Color;
9
10/// Blend mode per sprite. Additive uses `SrcAlpha + One`.
11/// Sorted into ranges (alpha, then multiply, then additive): push order
12/// across blend modes is NOT preserved, see the batch module docs.
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
14pub enum SpriteBlend {
15 #[default]
16 Alpha,
17 Additive,
18 Multiply,
19}
20
21/// One batched sprite. `uv` is in atlas texels normalized to 0..1.
22#[derive(Clone, Copy, Debug)]
23pub struct SpriteInstance {
24 /// World-space center, rotation radians, size in world units.
25 pub center: Vec2,
26 pub rotation: f32,
27 pub size: Vec2,
28 /// Normalized anchor: `[0.5, 0.5]` centers the quad on `center`,
29 /// `[0, 0]` pins the top-left corner. Y-down.
30 pub anchor: Vec2,
31 /// Mirror about the anchor axes. Canvas fills are flip-invariant;
32 /// the GPU batch mirrors geometry (UVs untouched).
33 pub flip_x: bool,
34 pub flip_y: bool,
35 pub uv_min: Vec2,
36 pub uv_max: Vec2,
37 /// RGBA tint, `(c * 255) as u8` per channel.
38 pub color: [f32; 4],
39 /// Atlas page index for multi-texture batches.
40 pub page: u32,
41 /// Draw key within one blend range; higher draws on top. Default 0.
42 /// Stable-sorted by `z` inside the range, but blend ranges draw
43 /// alpha-then-multiply-then-additive regardless of `z` (see
44 /// [`SpriteBlend`]).
45 pub z: f32,
46 pub blend: SpriteBlend,
47}
48
49impl Default for SpriteInstance {
50 fn default() -> Self {
51 Self {
52 center: Vec2::ZERO,
53 rotation: 0.0,
54 size: Vec2::ONE,
55 anchor: Vec2::new(0.5, 0.5),
56 flip_x: false,
57 flip_y: false,
58 uv_min: Vec2::ZERO,
59 uv_max: Vec2::ONE,
60 color: [1.0, 1.0, 1.0, 1.0],
61 page: 0,
62 z: 0.0,
63 blend: SpriteBlend::Alpha,
64 }
65 }
66}
67
68/// World-anchored text floater (damage numbers, `+25`).
69#[derive(Clone, Debug, Default)]
70pub struct WorldText {
71 pub text: String,
72 /// World-space anchor.
73 pub pos: Vec2,
74 /// RGBA, `(c * 255) as u8` per channel.
75 pub color: [f32; 4],
76 /// Font size in world units.
77 pub size: f32,
78 /// Font family name to resolve, or `None` (default) for the stack the
79 /// text engine picks itself. The name must already be known to the
80 /// engine; an unresolved name falls back to the default stack.
81 pub font_family: Option<&'static str>,
82}
83
84pub fn rgba8(c: [f32; 4]) -> Color {
85 Color::from_rgba(
86 (c[0].clamp(0.0, 1.0) * 255.0) as u8,
87 (c[1].clamp(0.0, 1.0) * 255.0) as u8,
88 (c[2].clamp(0.0, 1.0) * 255.0) as u8,
89 (c[3].clamp(0.0, 1.0) * 255.0) as u8,
90 )
91}