Early UI work.
This commit is contained in:
210
lib/ui/src/scene.rs
Normal file
210
lib/ui/src/scene.rs
Normal file
@@ -0,0 +1,210 @@
|
||||
//! Renderer-oriented scene snapshot types.
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
use crate::trace_targets;
|
||||
|
||||
pub type SceneVersion = u64;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Point {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct UiSize {
|
||||
pub width: f32,
|
||||
pub height: f32,
|
||||
}
|
||||
|
||||
impl UiSize {
|
||||
pub const fn new(width: f32, height: f32) -> Self {
|
||||
Self { width, height }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Rect {
|
||||
pub origin: Point,
|
||||
pub size: UiSize,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
|
||||
Self {
|
||||
origin: Point::new(x, y),
|
||||
size: UiSize::new(width, height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct Color {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
|
||||
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
||||
Self::rgba(r, g, b, 255)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Translation {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Translation {
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Quad {
|
||||
pub rect: Rect,
|
||||
pub color: Color,
|
||||
}
|
||||
|
||||
impl Quad {
|
||||
pub const fn new(rect: Rect, color: Color) -> Self {
|
||||
Self { rect, color }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GlyphInstance {
|
||||
pub glyph: String,
|
||||
pub position: Point,
|
||||
pub advance: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PreparedText {
|
||||
pub text: String,
|
||||
pub font_size: f32,
|
||||
pub color: Color,
|
||||
pub glyphs: Vec<GlyphInstance>,
|
||||
}
|
||||
|
||||
impl PreparedText {
|
||||
pub fn monospace(
|
||||
text: impl Into<String>,
|
||||
origin: Point,
|
||||
font_size: f32,
|
||||
advance: f32,
|
||||
color: Color,
|
||||
) -> Self {
|
||||
let text = text.into();
|
||||
let mut x = origin.x;
|
||||
let mut glyphs = Vec::with_capacity(text.chars().count());
|
||||
for ch in text.chars() {
|
||||
glyphs.push(GlyphInstance {
|
||||
glyph: ch.to_string(),
|
||||
position: Point::new(x, origin.y),
|
||||
advance,
|
||||
});
|
||||
x += advance;
|
||||
}
|
||||
|
||||
Self {
|
||||
text,
|
||||
font_size,
|
||||
color,
|
||||
glyphs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum DisplayItem {
|
||||
Quad(Quad),
|
||||
Text(PreparedText),
|
||||
PushClip(Rect),
|
||||
PopClip,
|
||||
PushTransform(Translation),
|
||||
PopTransform,
|
||||
LayerBegin { opacity: f32 },
|
||||
LayerEnd,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SceneSnapshot {
|
||||
pub version: SceneVersion,
|
||||
pub logical_size: UiSize,
|
||||
pub items: Vec<DisplayItem>,
|
||||
}
|
||||
|
||||
impl SceneSnapshot {
|
||||
pub fn new(version: SceneVersion, logical_size: UiSize) -> Self {
|
||||
debug!(
|
||||
target: trace_targets::SCENE,
|
||||
event = "create_scene",
|
||||
version,
|
||||
width = logical_size.width,
|
||||
height = logical_size.height,
|
||||
"creating scene snapshot"
|
||||
);
|
||||
Self {
|
||||
version,
|
||||
logical_size,
|
||||
items: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_count(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
pub fn push_item(&mut self, item: DisplayItem) -> &mut Self {
|
||||
self.items.push(item);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn push_quad(&mut self, rect: Rect, color: Color) -> &mut Self {
|
||||
self.push_item(DisplayItem::Quad(Quad::new(rect, color)))
|
||||
}
|
||||
|
||||
pub fn push_text(&mut self, text: PreparedText) -> &mut Self {
|
||||
self.push_item(DisplayItem::Text(text))
|
||||
}
|
||||
|
||||
pub fn push_clip(&mut self, rect: Rect) -> &mut Self {
|
||||
self.push_item(DisplayItem::PushClip(rect))
|
||||
}
|
||||
|
||||
pub fn pop_clip(&mut self) -> &mut Self {
|
||||
self.push_item(DisplayItem::PopClip)
|
||||
}
|
||||
|
||||
pub fn push_transform(&mut self, translation: Translation) -> &mut Self {
|
||||
self.push_item(DisplayItem::PushTransform(translation))
|
||||
}
|
||||
|
||||
pub fn pop_transform(&mut self) -> &mut Self {
|
||||
self.push_item(DisplayItem::PopTransform)
|
||||
}
|
||||
|
||||
pub fn begin_layer(&mut self, opacity: f32) -> &mut Self {
|
||||
self.push_item(DisplayItem::LayerBegin { opacity })
|
||||
}
|
||||
|
||||
pub fn end_layer(&mut self) -> &mut Self {
|
||||
self.push_item(DisplayItem::LayerEnd)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user