use crate::{ frame::Frame, helpers::{pixel::Pixel, vector::Vec2}, }; use std::ops::{Index, IndexMut}; pub struct View { pub frame: T, pub offset: Vec2, pub size: Vec2, } impl View { pub fn new(frame: T, offset: Vec2, size: Vec2) -> Self { Self { frame, offset, size, } } pub fn area(&self) -> isize { self.size.x * self.size.y } pub fn center(&self) -> Vec2 { self.offset + self.size.downscale(2) } } impl View<&mut T> { pub fn split_mut_unsafe(&mut self) -> [Self; 2] { let vert = self.size.x > self.size.y; [ Self { frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) }, offset: self.offset, size: if vert { Vec2 { x: self.size.x / 2, y: self.size.y, } } else { Vec2 { x: self.size.x, y: self.size.y / 2, } }, }, Self { frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) }, offset: if vert { Vec2 { x: self.offset.x + self.size.x / 2, y: self.offset.y, } } else { Vec2 { x: self.offset.x, y: self.offset.y + self.size.y / 2, } }, size: if vert { Vec2 { x: self.size.x - self.size.x / 2, y: self.size.y, } } else { Vec2 { x: self.size.x, y: self.size.y - self.size.y / 2, } }, }, ] } } impl View { pub fn offset(&self, offset: Vec2) -> Self { Self { frame: self.frame, offset: self.offset + offset, size: self.size, } } pub fn split(&self) -> [Self; 2] { let vert = self.size.x > self.size.y; [ Self { frame: self.frame, offset: self.offset, size: if vert { Vec2 { x: self.size.x / 2, y: self.size.y, } } else { Vec2 { x: self.size.x, y: self.size.y / 2, } }, }, Self { frame: self.frame, offset: if vert { Vec2 { x: self.offset.x + self.size.x / 2, y: self.offset.y, } } else { Vec2 { x: self.offset.x, y: self.offset.y + self.size.y / 2, } }, size: if vert { Vec2 { x: self.size.x - self.size.x / 2, y: self.size.y, } } else { Vec2 { x: self.size.x, y: self.size.y - self.size.y / 2, } }, }, ] } } impl, Output = Pixel>> View<&T> { pub fn diff(va: &Self, vb: &Self) -> f64 { assert_eq!(va.size, vb.size); let mut acc = 0; for x in 0..va.size.x { for y in 0..va.size.y { let a = va[(x, y)]; let b = vb[(x, y)]; acc += Pixel::distance(a, b); } } acc as f64 } pub fn pixels(&self) -> Vec { let mut v = vec![]; for x in 0..self.size.x { for y in 0..self.size.y { v.push(self[(x, y)]); } } v } } impl View<&mut Frame> { pub fn copy_from(&mut self, other: &View<&Frame>) { for x in 0..self.size.x { for y in 0..self.size.y { self[(x, y)] = other[(x, y)]; } } } pub fn set_pixels(&mut self, pixels: &Vec) { for x in 0..self.size.x { for y in 0..self.size.y { self[(x, y)] = pixels[(x * self.size.y + y) as usize] } } } } impl, Output = Pixel>> Index> for View<&T> { type Output = Pixel; #[inline] fn index(&self, p: Vec2) -> &Self::Output { &self.frame[self.offset + p] } } impl, Output = Pixel>> Index> for View<&mut T> { type Output = Pixel; #[inline] fn index(&self, p: Vec2) -> &Self::Output { &self.frame[self.offset + p] } } impl, Output = Pixel>> IndexMut> for View<&mut T> { #[inline] fn index_mut(&mut self, p: Vec2) -> &mut Self::Output { &mut self.frame[self.offset + p] } } impl, Output = Pixel>> Index<(isize, isize)> for View<&T> { type Output = Pixel; #[inline] fn index(&self, (x, y): (isize, isize)) -> &Self::Output { &self[Vec2 { x, y }] } } impl, Output = Pixel>> Index<(isize, isize)> for View<&mut T> { type Output = Pixel; #[inline] fn index(&self, (x, y): (isize, isize)) -> &Self::Output { &self[Vec2 { x, y }] } } impl, Output = Pixel>> IndexMut<(isize, isize)> for View<&mut T> { #[inline] fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output { &mut self[Vec2 { x, y }] } }