use crate::graphics::{Color, Rect};
use cgmath::Matrix;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Transform {
Values {
dest: mint::Point2<f32>,
rotation: f32,
scale: mint::Vector2<f32>,
offset: mint::Point2<f32>,
},
Matrix(mint::ColumnMatrix4<f32>),
}
impl Default for Transform {
fn default() -> Self {
Transform::Values {
dest: mint::Point2 { x: 0.0, y: 0.0 },
rotation: 0.0,
scale: mint::Vector2 { x: 1.0, y: 1.0 },
offset: mint::Point2 { x: 0.0, y: 0.0 },
}
}
}
impl Transform {
pub fn to_matrix(self) -> Self {
Transform::Matrix(self.to_bare_matrix())
}
pub fn to_bare_matrix(self) -> mint::ColumnMatrix4<f32> {
match self {
Transform::Matrix(m) => m,
Transform::Values {
dest,
rotation,
scale,
offset,
} => {
let (sinr, cosr) = rotation.sin_cos();
let m00 = cosr * scale.x;
let m01 = -sinr * scale.y;
let m10 = sinr * scale.x;
let m11 = cosr * scale.y;
let m03 = offset.x * (-m00) - offset.y * m01 + dest.x;
let m13 = offset.y * (-m11) - offset.x * m10 + dest.y;
cgmath::Matrix4::new(
m00, m01, 0.0, m03, m10, m11, 0.0, m13, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, )
.transpose()
.into()
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct DrawParam {
pub src: Rect,
pub color: Color,
pub trans: Transform,
}
impl Default for DrawParam {
fn default() -> Self {
DrawParam {
src: Rect::one(),
color: Color::WHITE,
trans: Transform::default(),
}
}
}
impl DrawParam {
pub fn new() -> Self {
Self::default()
}
pub fn src(mut self, src: Rect) -> Self {
self.src = src;
self
}
pub fn dest<P>(mut self, dest_: P) -> Self
where
P: Into<mint::Point2<f32>>,
{
if let Transform::Values { ref mut dest, .. } = self.trans {
let p: mint::Point2<f32> = dest_.into();
*dest = p;
self
} else {
panic!("Cannot set values for a DrawParam matrix")
}
}
pub fn color(mut self, color: Color) -> Self {
self.color = color;
self
}
pub fn rotation(mut self, rot: f32) -> Self {
if let Transform::Values {
ref mut rotation, ..
} = self.trans
{
*rotation = rot;
self
} else {
panic!("Cannot set values for a DrawParam matrix")
}
}
pub fn scale<V>(mut self, scale_: V) -> Self
where
V: Into<mint::Vector2<f32>>,
{
if let Transform::Values { ref mut scale, .. } = self.trans {
let p: mint::Vector2<f32> = scale_.into();
*scale = p;
self
} else {
panic!("Cannot set values for a DrawParam matrix")
}
}
pub fn offset<P>(mut self, offset_: P) -> Self
where
P: Into<mint::Point2<f32>>,
{
if let Transform::Values { ref mut offset, .. } = self.trans {
let p: mint::Point2<f32> = offset_.into();
*offset = p;
self
} else {
panic!("Cannot set values for a DrawParam matrix")
}
}
pub fn transform<M>(mut self, transform: M) -> Self
where
M: Into<mint::ColumnMatrix4<f32>>,
{
self.trans = Transform::Matrix(transform.into());
self
}
}
impl<P> From<(P,)> for DrawParam
where
P: Into<mint::Point2<f32>>,
{
fn from(location: (P,)) -> Self {
DrawParam::new().dest(location.0)
}
}
impl<P> From<(P, Color)> for DrawParam
where
P: Into<mint::Point2<f32>>,
{
fn from((location, color): (P, Color)) -> Self {
DrawParam::new().dest(location).color(color)
}
}
impl<P> From<(P, f32, Color)> for DrawParam
where
P: Into<mint::Point2<f32>>,
{
fn from((location, rotation, color): (P, f32, Color)) -> Self {
DrawParam::new()
.dest(location)
.rotation(rotation)
.color(color)
}
}
impl<P> From<(P, f32, P, Color)> for DrawParam
where
P: Into<mint::Point2<f32>>,
{
fn from((location, rotation, offset, color): (P, f32, P, Color)) -> Self {
DrawParam::new()
.dest(location)
.rotation(rotation)
.offset(offset)
.color(color)
}
}
impl<P, V> From<(P, f32, P, V, Color)> for DrawParam
where
P: Into<mint::Point2<f32>>,
V: Into<mint::Vector2<f32>>,
{
fn from((location, rotation, offset, scale, color): (P, f32, P, V, Color)) -> Self {
DrawParam::new()
.dest(location)
.rotation(rotation)
.offset(offset)
.scale(scale)
.color(color)
}
}