2022-10-07 21:52:35 +00:00
|
|
|
// Copyright (c) 2022 Marceline Cramer
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
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 {
|
2022-11-05 21:00:51 +00:00
|
|
|
pub tl: Vec2,
|
|
|
|
pub br: Vec2,
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-24 07:26:57 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
impl Rect {
|
|
|
|
pub const NEG_INFINITY: Self = Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: Vec2::splat(f32::INFINITY),
|
|
|
|
br: Vec2::splat(f32::NEG_INFINITY),
|
2022-11-01 09:08:57 +00:00
|
|
|
};
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn from_xy_size(xy: Vec2, size: Vec2) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: xy,
|
|
|
|
br: xy + size,
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn from_circle_bounds(center: Vec2, radius: f32) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: center - radius,
|
|
|
|
br: center + radius,
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn from_triangle_bounds(tri: &ColoredTriangle) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: tri.v1.min(tri.v2).min(tri.v3),
|
|
|
|
br: tri.v1.max(tri.v2).max(tri.v3),
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-08-17 00:11:56 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn inset(&self, d: f32) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: self.tl + d,
|
|
|
|
br: self.br - d,
|
2022-08-17 00:11:56 +00:00
|
|
|
}
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-11-05 21:00:51 +00:00
|
|
|
|
|
|
|
pub fn bl(&self) -> Vec2 {
|
|
|
|
Vec2::new(self.tl.x, self.br.y)
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-05 21:00:51 +00:00
|
|
|
pub fn tr(&self) -> Vec2 {
|
|
|
|
Vec2::new(self.br.x, self.tl.y)
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn offset(&self, offset: Vec2) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: self.tl + offset,
|
|
|
|
br: self.br + offset,
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn scale(&self, scale: f32) -> Self {
|
|
|
|
Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: self.tl * scale,
|
|
|
|
br: self.br * scale,
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn is_valid(&self) -> bool {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.tl.cmplt(self.br).all()
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn intersects_rect(&self, other: &Self) -> bool {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.tl.cmple(other.br).all() && self.br.cmpge(other.tl).all()
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
2022-08-17 00:11:56 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn intersection(&self, other: &Self) -> Option<Self> {
|
|
|
|
let clipped = Self {
|
2022-11-05 21:00:51 +00:00
|
|
|
tl: self.tl.max(other.tl),
|
|
|
|
br: self.br.min(other.br),
|
2022-11-01 09:08:57 +00:00
|
|
|
};
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
if clipped.is_valid() {
|
|
|
|
Some(clipped)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-05 21:00:51 +00:00
|
|
|
pub fn union(&self, other: &Self) -> Self {
|
|
|
|
Self {
|
|
|
|
tl: self.tl.min(other.tl),
|
|
|
|
br: self.br.max(other.br),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn union_point(&self, point: Vec2) -> Self {
|
|
|
|
Self {
|
|
|
|
tl: self.tl.min(point),
|
|
|
|
br: self.br.max(point),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn contains_rect(&self, other: &Self) -> bool {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.tl.x < other.tl.x
|
|
|
|
&& self.tl.y < other.tl.y
|
|
|
|
&& self.br.x > other.br.x
|
|
|
|
&& self.br.y > other.br.y
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn contains_point(&self, xy: Vec2) -> bool {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.tl.x < xy.x && self.tl.y < xy.y && self.br.x > xy.x && self.br.y > xy.y
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-15 21:11:35 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn size(&self) -> Vec2 {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.br - self.tl
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn width(&self) -> f32 {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.br.x - self.tl.x
|
2022-07-18 22:54:05 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
pub fn height(&self) -> f32 {
|
2022-11-05 21:00:51 +00:00
|
|
|
self.br.y - self.tl.y
|
2022-07-18 23:51:33 +00:00
|
|
|
}
|
2022-11-01 09:08:57 +00:00
|
|
|
}
|
2022-07-18 23:51:33 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
|
|
|
pub struct Color(pub u32);
|
2022-07-18 22:54:05 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
impl From<glam::Vec4> 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))
|
|
|
|
}
|
|
|
|
}
|
2022-07-18 22:54:05 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
impl From<Color> 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))
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
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))
|
|
|
|
}
|
2022-07-19 03:24:39 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
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,
|
|
|
|
)
|
2022-07-19 03:24:39 +00:00
|
|
|
}
|
|
|
|
|
2022-11-18 19:43:10 +00:00
|
|
|
pub const fn alpha_multiply(&self, mul: u8) -> Self {
|
2022-11-01 09:08:57 +00:00
|
|
|
let a = self.0 as u8 as u16;
|
|
|
|
let multiplied = ((a * (mul as u16)) >> 8) as u8;
|
|
|
|
self.with_alpha(multiplied)
|
2022-07-18 23:44:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-18 19:43:10 +00:00
|
|
|
pub const fn with_alpha(&self, alpha: u8) -> Self {
|
2022-11-01 09:08:57 +00:00
|
|
|
Self(self.0 & 0xffffff00 | alpha as u32)
|
2022-07-18 23:44:42 +00:00
|
|
|
}
|
2022-11-05 20:25:59 +00:00
|
|
|
|
|
|
|
pub fn lerp(self, target: Self, blend: f32) -> Self {
|
|
|
|
let s: glam::Vec4 = self.into();
|
|
|
|
let o: glam::Vec4 = target.into();
|
|
|
|
(o * blend + s * (1.0 - blend)).into()
|
|
|
|
}
|
2022-07-18 23:44:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
|
|
|
pub struct MeshVertex {
|
|
|
|
pub position: Vec2,
|
|
|
|
pub color: Color,
|
2022-07-18 23:44:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
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,
|
2022-08-17 00:11:56 +00:00
|
|
|
}
|
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2022-07-19 03:24:39 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub enum Side {
|
|
|
|
Top,
|
|
|
|
Right,
|
|
|
|
Bottom,
|
|
|
|
Left,
|
|
|
|
}
|
2022-08-17 00:11:56 +00:00
|
|
|
|
2022-11-01 09:08:57 +00:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct ColoredTriangle {
|
|
|
|
pub v1: Vec2,
|
|
|
|
pub v2: Vec2,
|
|
|
|
pub v3: Vec2,
|
|
|
|
pub color: Color,
|
2022-07-15 21:11:35 +00:00
|
|
|
}
|