extern crate interleave;
use std::fmt;
use super::{TileView, TileSet};
#[derive(Clone)]
pub struct TileNet<T> {
map: Vec<T>,
cols: usize,
}
impl<T: fmt::Debug> fmt::Debug for TileNet<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let biggest = self.map.iter().map(|x| format!("{:?}", x).len()).max();
for (index, tile) in self.map.iter().enumerate() {
if index % self.cols == 0 && index != 0 {
try!(formatter.write_str("\n"));
}
let mut current = format!("{:?}", tile);
let length = current.len();
if let Some(biggest) = biggest {
(0..biggest - length).map(|_| current.push(' ')).count();
}
try!(write!(formatter, "{} ", current));
}
Ok(())
}
}
impl TileNet<usize> {
pub fn sample() -> TileNet<usize> {
TileNet::from_iter(10, (1..101).map(|x| if x > 50 { x } else { 0 }))
}
}
pub struct TileNetProxy<'a, T: 'a> {
tilenet: &'a mut TileNet<T>,
min_x: usize,
max_x: usize,
min_y: usize,
max_y: usize,
}
pub type Span = (usize, usize, usize, usize);
impl<'a, T> TileNetProxy<'a, T>
where T: Clone
{
pub fn get_span(&self) -> Span {
(self.min_x, self.min_y, self.max_x, self.max_y)
}
pub fn set_box(&mut self, value: &T, start: (usize, usize), stop: (usize, usize)) -> Span {
self.tilenet.set_box(value, start, stop);
if start.0 < self.min_x {
self.min_x = start.0;
}
if start.1 < self.min_y {
self.min_y = start.1;
}
if stop.0 > self.max_x {
self.max_x = stop.0;
}
if stop.1 > self.max_y && stop.1 < self.tilenet.get_size().1 {
self.max_y = stop.1;
}
self.get_span()
}
pub fn set_row(&mut self, value: &T, row: usize) -> Span {
self.tilenet.set_row(value, row);
self.min_x = 0;
self.max_x = self.tilenet.get_size().0;
if row < self.min_y {
self.min_y = row;
}
if row > self.max_y && row < self.tilenet.get_size().1 {
self.max_y = row;
}
self.get_span()
}
pub fn set_col(&mut self, value: &T, col: usize) -> Span {
self.tilenet.set_col(value, col);
self.min_y = 0;
self.max_y = self.tilenet.get_size().1;
if col < self.min_x {
self.min_x = col;
}
if col > self.max_x && col < self.tilenet.get_size().0 {
self.max_x = col;
}
self.get_span()
}
pub fn set(&mut self, value: &T, p: (usize, usize)) -> Span {
self.tilenet.set(value, p);
if p.0 < self.min_x {
self.min_x = p.0;
}
if p.1 < self.min_y {
self.min_y = p.1;
}
if p.0 > self.max_x && p.0 < self.tilenet.get_size().0 {
self.max_x = p.0;
}
if p.1 > self.max_y && p.1 < self.tilenet.get_size().1 {
self.max_y = p.1;
}
self.get_span()
}
}
impl<T> TileNet<T>
where T: Clone
{
pub fn prepare(&mut self) -> TileNetProxy<T> {
let size = self.get_size();
TileNetProxy {
tilenet: self,
min_x: size.0,
max_x: 0,
min_y: size.1,
max_y: 0,
}
}
pub fn get_raw(&self) -> &[T] {
self.map.as_slice()
}
pub fn set_box(&mut self, value: &T, start: (usize, usize), stop: (usize, usize)) {
for i in start.1..stop.1 {
for j in start.0..stop.0 {
self.set(value, (j, i));
}
}
for j in start.0..stop.0 {
self.set(value, (j, stop.1));
}
for i in start.1..stop.1 {
self.set(value, (stop.0, i));
}
self.set(value, (stop.0, stop.1));
}
pub fn set_row(&mut self, value: &T, row: usize) {
for i in 0..self.col_count() {
self.set(value, (i, row));
}
}
pub fn set_col(&mut self, value: &T, col: usize) {
for i in 0..self.row_count() {
self.set(value, (col, i));
}
}
pub fn set(&mut self, value: &T, p: (usize, usize)) {
if let Some(old) = self.get_mut(p) {
*old = value.clone();
}
}
}
impl<T> TileNet<T>
where T: Clone + Default
{
pub fn new(x: usize, y: usize) -> TileNet<T> {
TileNet {
map: vec![T::default(); x * y],
cols: x,
}
}
pub fn resize(&mut self, m: (usize, usize)) {
let mut new_map: Vec<T> = vec![T::default(); m.0*m.1];
let new_cols = m.1;
let new_rows = new_map.len() / new_cols;
self.map
.iter()
.enumerate()
.map(|x| (x.0 % self.cols, x.0 / self.cols, x.1))
.filter(|x| x.0 < new_cols && x.1 < new_rows)
.inspect(|x| new_map[x.0 + x.1 * new_cols] = x.2.clone())
.count();
self.map = new_map;
self.cols = new_cols;
}
}
impl<T> TileNet<T>
where T: Default
{
pub fn from_iter<I>(columns: usize, iter: I) -> TileNet<T>
where I: Iterator<Item = T>
{
let mut tilenet = TileNet {
map: vec![],
cols: columns,
};
tilenet.map.extend(iter);
let remainder = tilenet.map.len() % tilenet.cols;
if remainder != 0 {
for _ in 0..tilenet.cols - remainder {
tilenet.map.push(T::default());
}
}
tilenet
}
}
impl<T> TileNet<T> {
pub fn row_count(&self) -> usize {
self.map.len() / self.cols
}
pub fn col_count(&self) -> usize {
self.cols
}
pub fn get(&self, p: (usize, usize)) -> Option<&T> {
if p.0 >= self.cols {
None
} else {
self.map.get(p.0 + p.1 * self.cols)
}
}
pub fn get_size(&self) -> (usize, usize) {
(self.cols, self.row_count())
}
pub fn view_all(&self) -> TileView<T> {
TileView::new(self, (0, self.cols, 0, self.map.len() / self.cols))
}
pub fn view_center_f32(&self, position: (f32, f32), span: (usize, usize)) -> TileView<T> {
let position = (position.0.max(0.0) as usize, position.1.max(0.0) as usize);
self.view_center(position, span)
}
pub fn view_center(&self, position: (usize, usize), span: (usize, usize)) -> TileView<T> {
let left = position.0.checked_sub(span.0).unwrap_or(0);
let top = position.1.checked_sub(span.1).unwrap_or(0);
let right = position.0 + span.0;
let bottom = position.1 + span.1;
TileView::new(self, (left, right, top, bottom))
}
pub fn view_box(&self, rectangle: (usize, usize, usize, usize)) -> TileView<T> {
TileView::new(self, rectangle)
}
pub fn get_mut(&mut self, p: (usize, usize)) -> Option<&mut T> {
if p.0 >= self.cols {
None
} else {
self.map.get_mut(p.0 + p.1 * self.cols)
}
}
pub fn collide_set<I>(&self, list: I) -> TileSet<T, I>
where I: Iterator<Item = (i32, i32)>
{
TileSet {
tilenet: self,
points: list,
last_coord: (0, 0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_proxy() {
let mut net: TileNet<usize> = TileNet::new(15, 10);
let mut net = net.prepare();
net.set_box(&1, (2, 2), (4, 6));
let span = net.set_box(&2, (3, 3), (14, 6));
assert_eq![span, (2, 2, 14, 6)];
}
}