canary-rs/crates/script/src/lib.rs

228 lines
5.2 KiB
Rust

// 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};
use num_traits::FromPrimitive;
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<Self> {
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<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))
}
}
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))
}
}
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,
}