use glam::{vec2, Mat2, Vec2, Vec2Swizzles, Vec4, Vec4Swizzles};
use crate::render::Color;
use super::Transform2d;
pub trait IntoRawInstance {
fn into_raw(self, texture_size: Vec2) -> super::Instance;
}
#[derive(Debug, Clone)]
pub struct Instance2d {
pub transform: Transform2d,
pub color: Color,
pub sprite_rect: Option<SpriteRect>,
pub sprite_scaling: SpriteScaling,
}
impl Default for Instance2d {
fn default() -> Self {
Instance2d {
transform: Transform2d::IDENTITY,
color: Color::WHITE,
sprite_rect: None,
sprite_scaling: SpriteScaling::Sprite,
}
}
}
impl IntoRawInstance for Instance2d {
fn into_raw(mut self, texture_size: Vec2) -> super::Instance {
let sprite_rect = match self.sprite_rect {
Some(rect) => rect.into_coords(texture_size),
None => Vec4::new(0.0, 0.0, 1.0, 1.0),
};
if matches!(self.sprite_scaling, SpriteScaling::Sprite) {
let scale = match self.sprite_rect {
Some(rect) => rect.0.zw(),
None => texture_size,
};
self.transform.scale *= scale;
}
let affine = self.transform.compute_affine();
super::Instance {
matrix2: affine.matrix2.to_cols_array(),
translation: affine.translation,
sprite_rect,
color: self.color.0,
_padding: Default::default(),
}
}
}
#[derive(Debug, Clone)]
pub struct Line2d {
pub start: Vec2,
pub end: Vec2,
pub width: f32,
pub color: Color,
}
impl Default for Line2d {
fn default() -> Self {
Line2d {
start: Vec2::ZERO,
end: Vec2::ZERO,
width: 1.0,
color: Color::WHITE,
}
}
}
impl Line2d {
pub fn new(start: Vec2, end: Vec2, width: f32, color: Color) -> Self {
Line2d {
start,
end,
width,
color,
}
}
}
impl IntoRawInstance for Line2d {
#[allow(unused)]
fn into_raw(mut self, texture_size: Vec2) -> super::Instance {
let pos = (self.start + self.end) * 0.5;
let diff = self.end - self.start;
let d = diff.length();
let dir = diff.normalize_or(Vec2::X);
let rotation = Mat2::from_cols(vec2(dir.x, dir.y), vec2(-dir.y, dir.x));
Instance2d {
transform: Transform2d::from_translation(pos)
.with_rotation(rotation)
.with_scale(vec2(d, self.width)),
color: self.color,
..Default::default()
}
.into_raw(texture_size)
}
}
#[derive(Debug, Default, Clone, Copy)]
pub enum SpriteScaling {
#[default]
Sprite,
Mesh,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SpriteRect(pub Vec4);
impl SpriteRect {
pub const fn new(x: u32, y: u32, w: u32, h: u32) -> Self {
SpriteRect(Vec4::new(x as f32, y as f32, w as f32, h as f32))
}
pub fn into_coords(self, size: Vec2) -> Vec4 {
self.0 / size.xyxy()
}
}