use yog_formats::book::layout::{ICON_PX, LayoutPart, RecipeLayout};
use yog_gfx::image::{ImageSource, Stretch};
use yog_ids::{yui, yui_attr as attr};
#[derive(Debug, Clone, PartialEq)]
pub struct ScreenElement {
pub kind: &'static str,
pub attrs: Vec<(&'static str, String)>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ScreenArea {
pub elements: Vec<ScreenElement>,
pub places: Vec<(String, usize, usize)>,
pub result: Option<usize>,
pub next: usize,
}
const SLOT_BORDER: f32 = 1.0;
const LABEL_COLOR: &str = "#FF404040";
pub fn screen_area(layout: &RecipeLayout, first: usize) -> ScreenArea {
let mut out = ScreenArea {
next: first,
..ScreenArea::default()
};
for part in &layout.parts {
match part {
LayoutPart::Image { source, uv, at } => out.elements.push(picture(source, *uv, *at)),
LayoutPart::Slots { slot, at, .. } => {
for (i, p) in at.iter().enumerate() {
out.places.push((slot.clone(), i, out.next));
out.slot(*p);
}
}
LayoutPart::Result { at, .. } => {
out.result = Some(out.next);
out.slot(*at);
}
LayoutPart::Item { item, at } => out
.elements
.push(icon(ImageSource::Item(item.clone()), *at)),
LayoutPart::Block { block, at, .. } => {
let id = block
.split(yog_ids::sep::STATE_OPEN)
.next()
.unwrap_or(block);
out.elements
.push(icon(ImageSource::Block(id.to_string()), *at));
}
LayoutPart::Text { text, at } if !text.contains(VALUE_OPEN) => {
out.elements.push(label(text, *at))
}
LayoutPart::Text { .. } | LayoutPart::Count { .. } => {}
}
}
out
}
impl ScreenArea {
fn slot(&mut self, at: [f32; 2]) {
let mut attrs = vec![(attr::INDEX, self.next.to_string())];
attrs.extend(xy(at, SLOT_BORDER));
self.elements.push(ScreenElement {
kind: yui::SLOT,
attrs,
});
self.next += 1;
}
}
const VALUE_OPEN: char = '{';
fn xy(at: [f32; 2], d: f32) -> [(&'static str, String); 2] {
[
(attr::X, (at[0] - d).to_string()),
(attr::Y, (at[1] - d).to_string()),
]
}
fn icon(source: ImageSource, at: [f32; 2]) -> ScreenElement {
let mut attrs = vec![
(attr::SOURCE, source.to_string()),
(attr::W, ICON_PX.to_string()),
(attr::H, ICON_PX.to_string()),
];
attrs.extend(xy(at, 0.0));
ScreenElement {
kind: yui::IMAGE,
attrs,
}
}
fn picture(source: &str, uv: [f32; 4], at: [f32; 2]) -> ScreenElement {
let [u, v, w, h] = uv;
let mut attrs = vec![
(attr::SOURCE, source.to_string()),
(attr::W, w.to_string()),
(attr::H, h.to_string()),
(attr::STRETCH, Stretch::Fill.name().into()),
];
attrs.extend(xy(at, 0.0));
if !matches!(ImageSource::parse(source), Some(ImageSource::Sprite(_))) {
attrs.push((attr::UV, format!("{u} {v} {w} {h}")));
}
ScreenElement {
kind: yui::IMAGE,
attrs,
}
}
fn label(text: &str, at: [f32; 2]) -> ScreenElement {
let mut attrs = vec![
(attr::TEXT, text.to_string()),
(attr::COLOR, LABEL_COLOR.into()),
(attr::SHADOW, false.to_string()),
];
attrs.extend(xy(at, 0.0));
ScreenElement {
kind: yui::LABEL,
attrs,
}
}