From c3e51d7b06e221182c072b1bbad4ed507afc2c9e Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 1 Feb 2022 09:21:06 -0500 Subject: [PATCH] Refactor game log to allow coloring of messages --- src/game_log.rs | 40 +++++++++++-------------- src/game_log/builder.rs | 63 ++++++++++++++++++++++++++++++++++++++++ src/game_log/logstore.rs | 35 ++++++++++++++++++++++ src/gui.rs | 19 ++++-------- 4 files changed, 120 insertions(+), 37 deletions(-) create mode 100644 src/game_log/builder.rs create mode 100644 src/game_log/logstore.rs diff --git a/src/game_log.rs b/src/game_log.rs index 771ebe7..e397824 100644 --- a/src/game_log.rs +++ b/src/game_log.rs @@ -1,24 +1,18 @@ -/// A struct to hold the player's game log. -#[derive(Default)] -pub struct GameLog { - pub entries: Vec, -} - -impl GameLog { - /// Convenience constructor that adds the first - /// entry to the game log. - pub fn new(first_entry: S) -> Self { - let mut log = GameLog::default(); - log.append(first_entry); - - log - } - - /// Convenience method for adding an entry to the game log. - /// Generic on the [`ToString`] trait so that [`&str`], [`String`], - /// and `&String` types, all work without more type juggling - /// at the call site. - pub fn append(&mut self, s: S) { - self.entries.push(s.to_string()); - } +//! Game Log +//! +//! Where the exploits of the current game are recorded +mod builder; +mod logstore; + +use ::rltk::RGB; +pub use builder::*; +use logstore::*; +pub use logstore::{clear_log, log_display}; + +/// A section of colored text for the game log +pub struct LogFragment { + /// The color of the text + pub color: RGB, + /// The text fragment + pub text: String, } diff --git a/src/game_log/builder.rs b/src/game_log/builder.rs new file mode 100644 index 0000000..69c28d3 --- /dev/null +++ b/src/game_log/builder.rs @@ -0,0 +1,63 @@ +use ::rltk::prelude::*; + +use super::{append_entry, LogFragment}; +use crate::colors; + +/// The game log builder - builds one line at a time +pub struct Logger { + current_color: RGB, + fragments: Vec, +} + +/// Convenience method to create a new [`Logger`] and +/// immediately append text +pub fn line(text: T) -> Logger { + Logger::new().append(text) +} + +impl Logger { + pub fn new() -> Self { + Logger { + current_color: colors::WHITE, + fragments: Vec::new(), + } + } + + /// Sets the color of text to be added to the current line + pub fn color(mut self, color: RGB) -> Self { + self.current_color = color; + + self + } + + /// The original [`color`](Logger::color) method, using [`rltk`] color constants + #[allow(dead_code)] + pub fn rltk_color(mut self, color: (u8, u8, u8)) -> Self { + self.current_color = RGB::named(color); + + self + } + + /// Appends text to the current line of the game log. + /// Generic on the [`ToString`] trait so that [`&str`], [`String`], + /// and `&String` types, all work without more type juggling + /// at the call site. + pub fn append(mut self, text: T) -> Self { + self.fragments.push(LogFragment { + color: self.current_color, + text: text.to_string(), + }); + + self + } + + /// Convenience method to append text with a new color + pub fn append_color(mut self, color: RGB, text: T) -> Self { + self.color(color).append(text) + } + + /// Append the current line to the log output + pub fn log(self) { + append_entry(self.fragments); + } +} diff --git a/src/game_log/logstore.rs b/src/game_log/logstore.rs new file mode 100644 index 0000000..d700be9 --- /dev/null +++ b/src/game_log/logstore.rs @@ -0,0 +1,35 @@ +use std::sync::Mutex; + +use ::rltk::prelude::*; + +use super::LogFragment; + +lazy_static! { + static ref LOG: Mutex>> = Mutex::new(Vec::new()); +} + +pub fn append_fragment(fragment: LogFragment) { + LOG.lock().unwrap().push(vec![fragment]); +} + +pub fn append_entry(fragments: Vec) { + LOG.lock().unwrap().push(fragments); +} + +pub fn clear_log() { + LOG.lock().unwrap().clear(); +} + +pub fn log_display() -> TextBuilder { + let mut buf = TextBuilder::empty(); + + LOG.lock().unwrap().iter().rev().take(12).for_each(|log| { + log.iter().for_each(|frag| { + buf.fg(frag.color); + buf.line_wrap(&frag.text); + }); + buf.ln(); + }); + + buf +} diff --git a/src/gui.rs b/src/gui.rs index 991ede2..c94f65c 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -4,6 +4,7 @@ mod tooltip; use std::cmp::Ordering; +use ::rltk::prelude::*; use ::rltk::{Point, Rltk, RGB}; use ::specs::prelude::*; pub use enums::*; @@ -15,8 +16,7 @@ use crate::components::{ InBackpack, KnownSpells, MagicItem, MagicItemClass, Name, ObfuscatedName, Pools, StatusEffect, Viewshed, Weapon, }; -use crate::game_log::GameLog; -use crate::{camera, colors, Map, MasterDungeonMap, State}; +use crate::{camera, colors, game_log, Map, MasterDungeonMap, State}; pub fn get_item_color(ecs: &World, item: Entity) -> RGB { let dm = ecs.fetch::(); @@ -77,8 +77,6 @@ pub fn draw_hollow_box( fg: RGB, bg: RGB, ) { - use rltk::to_cp437; - console.set(sx, sy, fg, bg, to_cp437('┌')); console.set(sx + width, sy, fg, bg, to_cp437('┐')); console.set(sx, sy + height, fg, bg, to_cp437('└')); @@ -95,8 +93,6 @@ pub fn draw_hollow_box( } pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { - use rltk::to_cp437; - draw_hollow_box(ctx, 0, 0, 79, 59, colors::BOX_GRAY, colors::BLACK); // Overall box draw_hollow_box(ctx, 0, 0, 49, 45, colors::BOX_GRAY, colors::BLACK); // Map box draw_hollow_box(ctx, 0, 45, 79, 14, colors::BOX_GRAY, colors::BLACK); // Log box @@ -329,14 +325,9 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { } // Draw the log - let log = ecs.fetch::(); - let mut y = 46; - for s in log.entries.iter().rev() { - if y < 59 { - ctx.print(2, y, s); - } - y += 1; - } + let mut block = TextBlock::new(1, 46, 79, 58); + block.print(&game_log::log_display()); + block.render(&mut ::rltk::BACKEND_INTERNAL.lock().consoles[0].console); draw_tooltips(ecs, ctx); }