gridit 0.1.0

2D grid library utilizing the fun of iterators
Documentation
use ggez::graphics::{
    BlendMode, Color, DrawMode, DrawParam, Drawable, FillOptions, Image, Mesh, Rect,
};
use ggez::mint::Point2;
use ggez::{Context, GameResult};

use crate::piece::*;

const BACKGROUND: Color = Color::new(160. / 255., 121. / 255., 61. / 255., 1.0);

pub struct PickerItem {
    item: Box<dyn Piece>,
    name: Name,
    pcolor: PColor,
    rect: Rect,
}

impl PickerItem {
    fn new(ctx: &mut Context, name: Name, pcolor: PColor) -> Self {
        Self {
            item: new_piece(ctx, name, pcolor),
            rect: Rect::default(),
            name,
            pcolor,
        }
    }

    fn set_rect(&mut self, rect: Rect) {
        self.rect = rect;
    }

    pub fn img_scale(&self) -> [f32; 2] {
        let img_w = self.item.image().width() as f32;
        let img_h = self.item.image().width() as f32;
        let scale_w = self.rect.w / img_w;
        let scale_h = self.rect.h / img_h;
        [scale_w, scale_h]
    }
}

impl Drawable for PickerItem {
    fn draw(&self, ctx: &mut Context, _param: DrawParam) -> GameResult<()> {
        self.item.image().draw(
            ctx,
            DrawParam::new()
                .dest(self.rect.point())
                .scale(self.img_scale()),
        )
    }

    fn blend_mode(&self) -> Option<BlendMode> {
        None
    }

    fn dimensions(&self, _ctx: &mut Context) -> Option<Rect> {
        Some(self.rect)
    }

    fn set_blend_mode(&mut self, _mode: Option<BlendMode>) {}
}

pub struct Picker {
    rect: Rect,
    items: Vec<PickerItem>,
}

impl Picker {
    pub fn new(ctx: &mut Context, rect: Rect) -> Self {
        let mut items = Vec::new();
        items.push(PickerItem::new(ctx, Name::PAWN, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::PAWN, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::ROOK, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::ROOK, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::BISHOP, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::BISHOP, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::KNIGHT, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::KNIGHT, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::QUEEN, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::QUEEN, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::KING, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::KING, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::BLOCKER, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::BLOCKER, PColor::WHITE));
        items.push(PickerItem::new(ctx, Name::GIRAFFE, PColor::BLACK));
        items.push(PickerItem::new(ctx, Name::GIRAFFE, PColor::WHITE));

        let mut picker = Self { items, rect };
        picker.update_items_rects();
        picker
    }

    fn update_items_rects(&mut self) {
        let Rect { x, y, w, .. } = self.rect;
        let mut wdif = -0.;
        for (i, item) in self.items.iter_mut().enumerate() {
            let padding = w / 20.;
            let size = w / 2. - (padding * 3.);
            let m = (i % 2) as f32;
            let ix = x + padding + (m * (size + padding * 3.));
            let iy = y + padding + (wdif * (size + padding));
            wdif += m;

            let rect = Rect::new(ix, iy, size, size);
            item.set_rect(rect);
        }
    }

    pub fn set_rect(&mut self, rect: Rect) {
        self.rect = rect;
        self.update_items_rects();
    }

    pub fn contains_point(&self, point: Point2<f32>) -> bool {
        self.rect.contains(point)
    }

    pub fn on_dragable(&self, point: Point2<f32>) -> bool {
        self.items
            .iter()
            .filter(|i| i.rect.contains(point))
            .next()
            .is_some()
    }

    pub fn get_item_at(&self, at: Point2<f32>) -> (Image, Name, PColor, [f32; 2]) {
        let item = self
            .items
            .iter()
            .filter(|i| i.rect.contains(at))
            .next()
            .unwrap();
        (
            item.item.image().clone(),
            item.name,
            item.pcolor,
            item.img_scale(),
        )
    }
}

impl Drawable for Picker {
    fn draw(&self, ctx: &mut Context, _param: DrawParam) -> GameResult<()> {
        let mrect = Mesh::new_rectangle(
            ctx,
            DrawMode::Fill(FillOptions::default()),
            self.rect,
            BACKGROUND,
        )?;

        mrect.draw(ctx, DrawParam::default())?;

        for item in self.items.iter() {
            item.draw(ctx, DrawParam::default())?;
        }

        Ok(())
    }

    fn blend_mode(&self) -> Option<BlendMode> {
        None
    }

    fn dimensions(&self, _ctx: &mut Context) -> Option<Rect> {
        Some(self.rect)
    }

    fn set_blend_mode(&mut self, _mode: Option<BlendMode>) {}
}