#[allow(unused_imports)] use log::{debug, error, info, trace, warn}; use winit; use cgmath::{Vector3, Vector2}; //--Position struct--------------------------------------------------------------------------------- #[derive(Copy, Clone, Debug)] pub struct Position { pub x: i32, pub y: i32, } impl Position { pub fn origin() -> Self { Position { x: 0, y: 0, } } } impl From for Vector3 { fn from(pos: Position) -> Self { Self::new(pos.x as f32, pos.y as f32, 0.0) } } impl From for Vector2 { fn from(pos: Position) -> Self { Self::new(pos.x as f32, pos.y as f32) } } impl std::ops::Add for Position { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Position { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl std::ops::Mul for Position { type Output = Self; fn mul(self, rhs: f32) -> Self::Output { Position { x: ((self.x as f32) * rhs) as i32, y: ((self.y as f32) * rhs) as i32, } } } //--Size struct------------------------------------------------------------------------------------- #[derive(Copy, Clone)] pub struct Size { pub w: u32, pub h: u32, } impl From for winit::dpi::Size { fn from(size: Size) -> Self { winit::dpi::Size::Physical ( winit::dpi::PhysicalSize { width: size.w, height: size.h, }) } } impl From for wgpu::Extent3d { fn from(size: Size) -> Self { wgpu::Extent3d { width: size.w, height: size.h, depth_or_array_layers: 1, } } } impl From> for Size { fn from(size: winit::dpi::PhysicalSize) -> Self { Self { w: size.width, h: size.height, } } } impl From for Vector2 { fn from(size: Size) -> Self { Self::new(size.w as f32, size.h as f32) } } //--Pixel struct------------------------------------------------------------------------------------ #[repr(packed, C)] #[derive(Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] pub struct Pixel { pub r: u8, pub g: u8, pub b: u8, pub a: u8, } impl From for Pixel { fn from(value: Color) -> Self { value.into_pixel() } } impl Pixel { pub const fn from_hex(hex: u32) -> Self { let bytes = hex.to_be_bytes(); Self { r: bytes[0], g: bytes[1], b: bytes[2], a: bytes[3] } } } //--Color values------------------------------------------------------------------------------------ #[non_exhaustive] #[derive(Copy, Clone, PartialEq)] pub struct Color { r: f32, g: f32, b: f32, a: f32, } impl From for Color { fn from(value: Pixel) -> Self { Self { r: f32::from(value.r) / 255.0, g: f32::from(value.g) / 255.0, b: f32::from(value.b) / 255.0, a: f32::from(value.a) / 255.0, } } } impl Color { pub fn set_alpha(&mut self, a: u8) { self.a = f32::from(a) / 255.0; } pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { Pixel { r, g, b, a: 255 }.into() } pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { Pixel { r, g, b, a }.into() } pub fn from_hex(hex: u32) -> Self { Pixel::from_hex(hex).into() } pub fn into_pixel(self) -> Pixel { //unsafe block is used here for "to_int_unchecked" since the struct's invariant garentees //that the values are within [0.0, 1.0], meaning we won't ever overflow an u8 unsafe { Pixel { r: self.r.to_int_unchecked::() * 255, g: self.g.to_int_unchecked::() * 255, b: self.b.to_int_unchecked::() * 255, a: self.a.to_int_unchecked::() * 255, } } } pub fn into_wgpu_color(self) -> wgpu::Color { wgpu::Color { r: f64::from(self.r), g: f64::from(self.g), b: f64::from(self.b), a: f64::from(self.a), } } pub fn alpha_blend(&self, other: &Self) -> Self { //apply alpha compisting's "over" operator, see //[https://en.wikipedia.org/wiki/Alpha_compositing] for more detail let a = self.a + other.a * (1.0 - self.a); Self { r: (self.r * self.a + other.r * other.a * (1.0 - self.a)) / a, g: (self.g * self.a + other.g * other.a * (1.0 - self.a)) / a, b: (self.b * self.a + other.b * other.a * (1.0 - self.a)) / a, a, } } pub const NONE: Self = Self {r: 0.0, g: 0.0, b: 0.0, a: 0.0}; pub const WHITE: Self = Self {r: 1.0, g: 1.0, b: 1.0, a: 1.0}; pub const BLACK: Self = Self {r: 0.0, g: 0.0, b: 0.0, a: 1.0}; pub const RED: Self = Self {r: 1.0, g: 0.0, b: 0.0, a: 1.0}; pub const GREEN: Self = Self {r: 0.0, g: 1.0, b: 0.0, a: 1.0}; pub const BLUE: Self = Self {r: 0.0, g: 0.0, b: 1.0, a: 1.0}; }