mirror of https://git.sr.ht/~garritfra/midgard
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.9 KiB
132 lines
3.9 KiB
use crate::traits::Render; |
|
use crate::State; |
|
use rltk::prelude::*; |
|
use rltk::DrawBatch; |
|
use rltk::Rltk; |
|
use std::fmt::Display; |
|
|
|
pub type Inventory = Vec<Item>; |
|
|
|
#[derive(Clone)] |
|
pub struct InventoryView { |
|
pub inv: Inventory, |
|
pub selected_item: usize, |
|
detail_menu: Option<Vec<Action>>, |
|
detail_selected_item: usize, |
|
} |
|
|
|
impl InventoryView { |
|
pub fn new(inv: Inventory) -> Self { |
|
Self { |
|
inv, |
|
detail_menu: None, |
|
detail_selected_item: 0, |
|
selected_item: 0, |
|
} |
|
} |
|
|
|
/// If possible, decreases the current position of the item or action |
|
pub fn selection_up(&mut self) { |
|
match &self.detail_menu { |
|
Some(_) => match self.detail_selected_item { |
|
0 => {} |
|
_ => self.detail_selected_item -= 1, |
|
}, |
|
None => match self.selected_item { |
|
0 => {} |
|
_ => self.selected_item -= 1, |
|
}, |
|
} |
|
} |
|
|
|
/// If possible, increases the current position of the item or action |
|
pub fn selection_down(&mut self) { |
|
match &self.detail_menu { |
|
Some(menu) => match self.detail_selected_item { |
|
n if n >= menu.len() => {} |
|
_ => self.detail_selected_item += 1, |
|
}, |
|
None => match self.selected_item { |
|
n if n >= self.inv.len() => {} |
|
_ => self.selected_item += 1, |
|
}, |
|
} |
|
} |
|
|
|
pub fn select(&mut self) { |
|
let item = &self.inv[self.selected_item]; |
|
let mut menu = Vec::new(); |
|
|
|
// TODO: cloning here might lead to problems later. |
|
// We should probably use a lifetime instead |
|
menu.push(Action::EquipLeft(item.clone())); |
|
menu.push(Action::EquipRight(item.clone())); |
|
menu.push(Action::ThrowAway(item.clone())); |
|
self.detail_menu = Some(menu); |
|
} |
|
} |
|
|
|
#[derive(Clone)] |
|
enum Action { |
|
EquipRight(Item), |
|
EquipLeft(Item), |
|
ThrowAway(Item), |
|
} |
|
|
|
impl Display for Action { |
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { |
|
match self { |
|
Self::EquipLeft(_) => f.write_str("Equip left"), |
|
Self::EquipRight(_) => f.write_str("Equip right"), |
|
Self::ThrowAway(_) => f.write_str("Drop"), |
|
} |
|
} |
|
} |
|
|
|
#[derive(Clone)] |
|
pub struct Item { |
|
pub name: String, |
|
} |
|
|
|
impl Render for InventoryView { |
|
fn render(&mut self, _gs: &mut State, ctx: &mut Rltk) { |
|
let mut draw_batch = DrawBatch::new(); |
|
|
|
ctx.cls(); |
|
|
|
for (i, item) in self.inv.iter().enumerate() { |
|
// Set color, based on if the item is selected |
|
let color = match self.selected_item { |
|
// CLEANUP: self.detail_menu.is_none gets checked twice in this method |
|
j if j == i && self.detail_menu.is_none() => { |
|
ColorPair::new(rltk::BLACK, rltk::WHITE) |
|
} |
|
_ => ColorPair::new(rltk::WHITE, rltk::BLACK), |
|
}; |
|
draw_batch.print_color(Point::new(4, i * 2 + 1), &item.name, color); |
|
|
|
if self.selected_item == i && self.detail_menu.is_none() { |
|
draw_batch.print_color( |
|
Point::new(1, i * 2 + 1), |
|
"->", |
|
ColorPair::new(rltk::WHITE, rltk::BLACK), |
|
); |
|
} |
|
} |
|
|
|
if let Some(menu) = &self.detail_menu { |
|
for (i, action) in menu.iter().enumerate() { |
|
// Set color, based on if the item is selected |
|
let color = match self.detail_selected_item { |
|
j if j == i => ColorPair::new(rltk::BLACK, rltk::WHITE), |
|
_ => ColorPair::new(rltk::WHITE, rltk::BLACK), |
|
}; |
|
|
|
draw_batch.print_color(Point::new(50, i * 2 + 1), action, color); |
|
} |
|
} |
|
|
|
draw_batch.submit(0).expect("Batch error"); |
|
render_draw_buffer(ctx).expect("Render error"); |
|
} |
|
}
|
|
|