use crossterm::event::{read, Event, KeyCode}; use tui::{backend::Backend, Frame}; use crate::{world::Terrain, game::Game, entity::Location}; use super::{controls::Controls, DefaultLayout, status_line::StatusLine, AppStatus, guest_selection::GuestSelectionView}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum DebugTab { Creatures, Items, Map, } struct CreatureItem{ id: u32, name: String, profession: String, loc: Location } struct ItemItem{ id: u32, name: String, item_type: String, owner: String, } pub struct DebugView { list: Vec, // Vec, list_state: tui::widgets::ListState, item_list: Vec, // Vec, item_list_state: tui::widgets::ListState, selected: DebugTab, map_scroll: (u16, u16), } impl DebugView { pub fn new(game: &Game) -> DebugView { let mut list = vec![]; let mut item_list = vec![]; for (id, creature) in game.state.creatures.iter() { list.push(CreatureItem { id: id.1, name: creature.name.clone(), profession: format!("{}", creature.profession), loc: creature.loc, }); // list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", // id.1, creature.name, // creature.profession, // creature.loc, // ))); } for (id, item) in game.state.items.iter() { item_list.push(ItemItem { id: id.1, name: item.name.clone(), item_type: format!("{}", item.item_type), owner: format!("{}", item.owner), }); // item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", // id.1, item.name, // item.item_type, // item.owner, // ))); } let mut view = DebugView { list, list_state: tui::widgets::ListState::default(), item_list, item_list_state: tui::widgets::ListState::default(), selected: DebugTab::Creatures, map_scroll: (0, 0), }; view.list_state.select(Some(0)); view.item_list_state.select(Some(0)); view } pub fn control(&mut self, game: &mut Game) -> (bool, Option) { match read() { Ok(Event::Key(event)) => { match event.code { KeyCode::Esc => { return (true, Some(AppStatus::GuestSelection(GuestSelectionView::new(game)))); }, KeyCode::Up => { if self.selected == DebugTab::Map { let (x, y) = self.map_scroll; self.map_scroll = (x.saturating_sub(4), y); } else { let ref mut state = match self.selected { DebugTab::Creatures => &mut self.list_state, DebugTab::Items => &mut self.item_list_state, _ => &mut self.list_state, }; let selected = state.selected().unwrap(); if selected > 0 { state.select(Some(selected - 1)); } } }, KeyCode::Down => { if self.selected == DebugTab::Map { let (x, y) = self.map_scroll; self.map_scroll = (x + 4, y); } else { let mut max = 0; let ref mut state = match self.selected { DebugTab::Creatures => { max = self.list.len() - 1; &mut self.list_state }, DebugTab::Items => { max = self.item_list.len() - 1; &mut self.item_list_state }, _ => { max = self.list.len() - 1; &mut self.list_state }, }; let selected = state.selected().unwrap(); if selected < max { state.select(Some(selected + 1)); } } }, KeyCode::Left => { if self.selected == DebugTab::Map { let (x, y) = self.map_scroll; self.map_scroll = (x, y.saturating_sub(4)); } }, KeyCode::Right => { if self.selected == DebugTab::Map { let (x, y) = self.map_scroll; self.map_scroll = (x, y + 4); } }, KeyCode::Char('i') => { self.selected = DebugTab::Items; }, KeyCode::Char('c') => { self.selected = DebugTab::Creatures; }, KeyCode::Char('m') => { self.selected = DebugTab::Map; }, _ => {} } }, _ => {} } return (true, None) } pub fn draw(&mut self, f: &mut Frame, game: &Game) { let chunks = DefaultLayout::default(f.size()); let data = self; match data.selected { DebugTab::Creatures => { let main_window = tui::widgets::List::new(data.list.iter().map(|c| { tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", c.id, c.name, c.profession, c.loc, )) }).collect::>()) .block(tui::widgets::Block::default().title("Guests").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) .highlight_symbol(">>"); f.render_stateful_widget(main_window, chunks.main, &mut data.list_state); }, DebugTab::Items => { let main_window = tui::widgets::List::new(data.item_list.iter().map(|i| { tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", i.id, i.name, i.item_type, i.owner, )) }).collect::>()) .block(tui::widgets::Block::default().title("Items").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) .highlight_symbol(">>"); f.render_stateful_widget(main_window, chunks.main, &mut data.item_list_state); }, DebugTab::Map => { let mut rows = Vec::new(); for row in game.state.world.map.iter() { rows.push(tui::text::Spans::from( row.iter().map(|tile| { match tile.terrain { Terrain::Void => tui::text::Span::styled(" ", tui::style::Style::default().bg(tui::style::Color::Rgb(0, 0, 0)).fg(tui::style::Color::Rgb(0, 0, 0))), Terrain::DeepOcean => tui::text::Span::styled("~", tui::style::Style::default().bg(tui::style::Color::Rgb(0, 0, 128)).fg(tui::style::Color::Rgb(32, 32, 128))), Terrain::Ocean => tui::text::Span::styled("~", tui::style::Style::default().bg(tui::style::Color::Rgb(32, 32, 128)).fg(tui::style::Color::Rgb(128, 128, 128))), Terrain::Beach => tui::text::Span::styled("-", tui::style::Style::default().bg(tui::style::Color::Rgb(200, 200, 10)).fg(tui::style::Color::Rgb(100, 100, 10))), Terrain::Flats => tui::text::Span::styled("-", tui::style::Style::default().bg(tui::style::Color::Rgb(30, 150, 30)).fg(tui::style::Color::Rgb(30, 200, 30))), Terrain::Hills => tui::text::Span::styled("~", tui::style::Style::default().bg(tui::style::Color::Rgb(120, 150, 30)).fg(tui::style::Color::Rgb(120, 150, 30))), Terrain::Mountains => tui::text::Span::styled("A", tui::style::Style::default().bg(tui::style::Color::Rgb(120,120,120)).fg(tui::style::Color::Rgb(120,120,120))), Terrain::HighMountains => tui::text::Span::styled("A", tui::style::Style::default().bg(tui::style::Color::Rgb(200,200,200)).fg(tui::style::Color::Rgb(200,200,200))), } }).collect::>() )); } let main_window = tui::widgets::Paragraph::new( tui::text::Text::from(rows) ) .block(tui::widgets::Block::default().title("Map").borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .scroll(data.map_scroll); f.render_widget(main_window, chunks.main); }, } StatusLine::draw(f, chunks.status, game); let mut binding = Controls::new(); let controls = binding .add("↑↓".to_owned(), "select guest".to_owned()) .add("c".to_owned(), "Creatures".to_owned()) .add("i".to_owned(), "Items".to_owned()) .add("m".to_owned(), "Map".to_owned()) .add("Esc".to_owned(), "back".to_owned()) .render(); f.render_widget(controls, chunks.controls); } }