use yog_gfx::{Color, GfxContext, Rect, Vec2};
use super::geometry::{
BLOCK_PITCH, ENTITY_TURN, ENTITY_YAW, MULTIBLOCK_SWAY, MULTIBLOCK_YAW, SLOT_YAW,
};
use super::{CRAFTING_SHEET, recipe::normalize_item_id};
#[derive(Clone, PartialEq)]
pub(crate) enum SpriteSheet {
Book,
Crafting,
Image(String),
}
#[derive(Clone)]
pub(crate) struct BgSprite {
pub sheet: SpriteSheet,
pub src: Rect,
pub dst: Rect,
}
pub type PageDrawer<'a> = &'a mut dyn FnMut(&GfxContext, &str, &yog_data::Value, [f32; 4]);
#[derive(Clone)]
pub(crate) enum OverlayCmd {
Drawn {
drawer: String,
data: yog_data::Value,
at: Rect,
},
McItems { items: Vec<String>, at: Rect },
Blocks {
blocks: Vec<((i32, i32, i32), String)>,
at: Rect,
turning: bool,
},
Entity { entity: String, at: Rect },
McText {
text: String,
at: Vec2,
color: Color,
},
McItem { item_id: String, at: Rect },
McTexture { path: String, at: Rect },
}
impl OverlayCmd {
pub(crate) fn icon(icon: &str, at: Rect) -> OverlayCmd {
if icon.ends_with(yog_ids::res::PNG) {
OverlayCmd::McTexture {
path: icon.to_string(),
at,
}
} else {
OverlayCmd::McItem {
item_id: icon.to_string(),
at,
}
}
}
pub(crate) fn animated(&self) -> bool {
match self {
OverlayCmd::Entity { .. } | OverlayCmd::Blocks { .. } => true,
OverlayCmd::McItems { items, .. } => items.iter().filter(|i| !is_tag(i)).count() > 1,
_ => false,
}
}
}
fn is_tag(item: &str) -> bool {
item.starts_with(yog_ids::sep::TAG_SHOWN)
}
pub(crate) fn draw_sprites(ctx: &GfxContext, sprites: &[BgSprite], book_sheet: &str) {
let d2 = ctx.draw2d();
for spr in sprites {
let sheet = match &spr.sheet {
SpriteSheet::Book => book_sheet,
SpriteSheet::Crafting => CRAFTING_SHEET,
SpriteSheet::Image(source) => source.as_str(),
};
d2.image_region(sheet, spr.dst, Some(spr.src), Color::WHITE);
}
}
pub(crate) fn draw_scenes(
ctx: &GfxContext,
overlays: &[OverlayCmd],
t: f32,
draw: super::PageDrawer<'_>,
) {
let d2 = ctx.draw2d();
for ov in overlays {
match ov {
OverlayCmd::Drawn { drawer, data, at } => {
draw(ctx, drawer, data, [at.x, at.y, at.w, at.h])
}
OverlayCmd::Entity { entity, at } => {
d2.entity(entity, *at, ENTITY_YAW + t * ENTITY_TURN, 0.0)
}
OverlayCmd::Blocks {
blocks,
at,
turning,
} => {
let list: Vec<((i32, i32, i32), &str)> =
blocks.iter().map(|(p, b)| (*p, b.as_str())).collect();
let yaw = if *turning {
MULTIBLOCK_YAW + t * MULTIBLOCK_SWAY
} else {
SLOT_YAW
};
d2.blocks(&list, *at, yaw, BLOCK_PITCH);
}
_ => {}
}
}
}
pub(crate) fn draw_items(ctx: &GfxContext, overlays: &[OverlayCmd], second: usize) {
let d2 = ctx.draw2d();
for ov in overlays {
match ov {
OverlayCmd::McItems { items, at } => {
let shown: Vec<&String> = items.iter().filter(|i| !is_tag(i)).collect();
if !shown.is_empty() {
let item = shown[second % shown.len()];
d2.item(
&normalize_item_id(item),
Vec2::new(at.x, at.y),
at.w.min(at.h),
);
}
}
OverlayCmd::McItem { item_id, at } => d2.item(
&normalize_item_id(item_id),
Vec2::new(at.x, at.y),
at.w.min(at.h),
),
OverlayCmd::McText { text, at, color } => d2.text(text, *at, *color, false),
OverlayCmd::McTexture { path, at } => d2.image(path, *at),
_ => {}
}
}
}