moho 0.0.9

Barebones Rust Game Library
use glm;

pub fn wrap_rects(original: glm::IVec4, max: glm::UVec2) -> [Option<glm::IVec4>; 4] {
    let max = glm::to_ivec2(max);
    let left = (original.x + max.x) % max.x;
    let top = (original.y + max.y) % max.y;
    let original = glm::ivec4(left, top, original.z, original.w);

    let side = side_wrap(left, top, original, max);
    let vert = vert_wrap(left, top, original, max);
    let side_vert = match (side, vert) {
        (Some(side_center), Some(vert_center)) => {
            Some(glm::ivec4(side_center.x, vert_center.y, original.z, original.w))
        }
        _ => None,
    };

    [Some(original), side, vert, side_vert]
}

fn side_wrap(left: i32, top: i32, original: glm::IVec4, max: glm::IVec2) -> Option<glm::IVec4> {
    let right = left + original.z;
    if left < 0 {
        Some(glm::ivec4(left + max.x, top, original.z, original.w))
    } else if right > max.x {
        Some(glm::ivec4((right % max.x) - original.z, top, original.z, original.w))
    } else {
        None
    }
}

fn vert_wrap(left: i32, top: i32, original: glm::IVec4, max: glm::IVec2) -> Option<glm::IVec4> {
    let bottom = top + original.w;
    if top < 0 {
        Some(glm::ivec4(left, top + max.y, original.z, original.w))
    } else if bottom > max.y {
        Some(glm::ivec4(left, bottom % max.y - original.w, original.z, original.w))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn no_wrapping() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(25, 15, 10, 7);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 1);
        assert_eq!(rect, rects[0]);
    }

    #[test]
    fn wrapping_left() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(-2, 16, 10, 8);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 2);
        assert_eq!(rect, rects[1]);
        assert_eq!(glm::ivec4(38, 16, 10, 8), rects[0]);
    }

    #[test]
    fn wrapping_right() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(34, 16, 10, 13);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 2);
        assert_eq!(rect, rects[0]);
        assert_eq!(glm::ivec4(-6, 16, 10, 13), rects[1]);
    }

    #[test]
    fn wrapping_bottom() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(27, 21, 6, 10);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 2);
        assert_eq!(rect, rects[0]);
        assert_eq!(glm::ivec4(27, -9, 6, 10), rects[1]);
    }

    #[test]
    fn wrapping_top() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(27, -3, 6, 10);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 2);
        assert_eq!(rect, rects[1]);
        assert_eq!(glm::ivec4(27, 27, 6, 10), rects[0]);
    }

    #[test]
    fn wrapping_corner() {
        let max_coords = glm::uvec2(40, 30);
        let rect = glm::ivec4(-2, -3, 10, 10);
        let rects: Vec<_> = wrap_rects(rect, max_coords)
            .iter()
            .filter_map(|&x| x)
            .collect();
        assert_eq!(rects.len(), 4);
        assert_eq!(rect, rects[3]);
        assert_eq!(glm::ivec4(38, -3, 10, 10), rects[2]);
        assert_eq!(glm::ivec4(-2, 27, 10, 10), rects[1]);
        assert_eq!(glm::ivec4(38, 27, 10, 10), rects[0]);
    }
}