// Copyright (c) 2022 Marceline Cramer // SPDX-License-Identifier: Apache-2.0 use bitflags::bitflags; use bytemuck::{Pod, Zeroable}; pub use glam::Vec2; use num_derive::{FromPrimitive, ToPrimitive}; pub mod api; #[repr(C)] #[derive(Copy, Clone, Debug, Default, Pod, Zeroable)] pub struct Rect { pub bl: Vec2, pub tr: Vec2, } impl Rect { pub const NEG_INFINITY: Self = Self { bl: Vec2::splat(f32::INFINITY), tr: Vec2::splat(f32::NEG_INFINITY), }; pub fn from_xy_size(xy: Vec2, size: Vec2) -> Self { Self { bl: xy, tr: xy + size, } } pub fn from_circle_bounds(center: Vec2, radius: f32) -> Self { Self { bl: center - radius, tr: center + radius, } } pub fn from_triangle_bounds(tri: &ColoredTriangle) -> Self { Self { bl: tri.v1.min(tri.v2).min(tri.v3), tr: tri.v1.max(tri.v2).max(tri.v3), } } pub fn inset(&self, d: f32) -> Self { Self { bl: self.bl + d, tr: self.tr - d, } } pub fn tl(&self) -> Vec2 { Vec2::new(self.bl.x, self.tr.y) } pub fn br(&self) -> Vec2 { Vec2::new(self.tr.x, self.bl.y) } pub fn offset(&self, offset: Vec2) -> Self { Self { bl: self.bl + offset, tr: self.tr + offset, } } pub fn scale(&self, scale: f32) -> Self { Self { bl: self.bl * scale, tr: self.tr * scale, } } pub fn is_valid(&self) -> bool { self.bl.cmplt(self.tr).all() } pub fn intersects_rect(&self, other: &Self) -> bool { self.bl.cmple(other.tr).all() && self.tr.cmpge(other.bl).all() } pub fn intersection(&self, other: &Self) -> Option { let clipped = Self { bl: self.bl.max(other.bl), tr: self.tr.min(other.tr), }; if clipped.is_valid() { Some(clipped) } else { None } } pub fn contains_rect(&self, other: &Self) -> bool { self.bl.x < other.bl.x && self.bl.y < other.bl.y && self.tr.x > other.tr.x && self.tr.y > other.tr.y } pub fn contains_point(&self, xy: Vec2) -> bool { self.bl.x < xy.x && self.bl.y < xy.y && self.tr.x > xy.x && self.tr.y > xy.y } pub fn size(&self) -> Vec2 { self.tr - self.bl } pub fn width(&self) -> f32 { self.tr.x - self.bl.x } pub fn height(&self) -> f32 { self.tr.y - self.bl.y } } #[repr(C)] #[derive(Copy, Clone, Debug, Pod, Zeroable)] pub struct Color(pub u32); impl From for Color { fn from(other: glam::Vec4) -> Self { let map = |v: f32| (v * 255.0).floor() as u8; Self::new(map(other.x), map(other.y), map(other.z), map(other.w)) } } impl From for glam::Vec4 { fn from(other: Color) -> Self { let (r, g, b, a) = other.to_rgba_unmultiplied(); let map = |v: u8| (v as f32) / 255.0; Self::new(map(r), map(g), map(b), map(a)) } } impl Color { pub const WHITE: Self = Self(0xffffffff); pub const BLACK: Self = Self(0x000000ff); pub const TRANSPARENT: Self = Self(0); pub const RED: Self = Self(0xff0000ff); pub const GREEN: Self = Self(0x00ff00ff); pub const BLUE: Self = Self(0x0000ffff); pub const YELLOW: Self = Self(0xffff00ff); pub const MAGENTA: Self = Self(0xff00ffff); pub const CYAN: Self = Self(0x00ffffff); pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self { Color(((r as u32) << 24) | ((g as u32) << 16) | ((b as u32) << 8) | (a as u32)) } pub fn to_rgba_unmultiplied(&self) -> (u8, u8, u8, u8) { ( (self.0 >> 24) as u8, (self.0 >> 16) as u8, (self.0 >> 8) as u8, self.0 as u8, ) } pub fn alpha_multiply(&self, mul: u8) -> Self { let a = self.0 as u8 as u16; let multiplied = ((a * (mul as u16)) >> 8) as u8; self.with_alpha(multiplied) } pub fn with_alpha(&self, alpha: u8) -> Self { Self(self.0 & 0xffffff00 | alpha as u32) } } #[repr(C)] #[derive(Copy, Clone, Debug, Pod, Zeroable)] pub struct MeshVertex { pub position: Vec2, pub color: Color, } pub type MeshIndex = u32; #[derive(Copy, Clone, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)] pub enum CursorEventKind { Hover = 0, Select = 1, Drag = 2, Deselect = 3, } #[derive(Copy, Clone, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)] pub enum Corner { TopRight = 0, BottomRight = 1, BottomLeft = 2, TopLeft = 3, } bitflags! { pub struct CornerFlags: u8 { const TOP_RIGHT = 0x01; const BOTTOM_RIGHT = 0x02; const BOTTOM_LEFT = 0x04; const TOP_LEFT = 0x08; const TOP = 0x09; const RIGHT = 0x03; const BOTTOM = 0x06; const LEFT = 0x0C; const ALL = 0x0F; } } #[derive(Copy, Clone, Debug)] pub enum Side { Top, Right, Bottom, Left, } #[derive(Copy, Clone)] pub struct ColoredTriangle { pub v1: Vec2, pub v2: Vec2, pub v3: Vec2, pub color: Color, }