Log panel

This commit is contained in:
2026-06-03 22:46:54 -05:00
parent de1870432f
commit 0187162e85
6 changed files with 262 additions and 53 deletions
+15 -4
View File
@@ -1,3 +1,4 @@
use crate::log::LogLine;
use color::Rgba8;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -35,7 +36,7 @@ impl Hash for Glyph {
}
impl Glyph {
/// Returns the glyph used to render the player: tile 64 (`@`) in light blue on black.
/// Returns the glyph used to render the player: tile 64 (`@`) in white on dark blue.
///
/// This is the only hardcoded glyph; all other glyphs come from the map
/// file palette. It will be removed once the player becomes a scripted
@@ -43,8 +44,8 @@ impl Glyph {
pub const fn player() -> Self {
Self {
tile: 64,
fg: Rgba8 { r: 173, g: 216, b: 230, a: 255 }, // light blue
bg: Rgba8 { r: 0, g: 0, b: 0, a: 255 }, // black
fg: Rgba8 { r: 255, g: 255, b: 255, a: 255 }, // white
bg: Rgba8 { r: 0, g: 0, b: 200, a: 255 }, // dark blue
}
}
}
@@ -394,12 +395,22 @@ impl Board {
pub struct GameState {
/// The currently active board.
pub board: Board,
/// The in-game message log, oldest first (newest pushed at the end).
pub log: Vec<LogLine>,
}
impl GameState {
/// Creates a `GameState` from a pre-loaded [`Board`].
pub fn new(board: Board) -> Self {
Self { board }
Self {
board,
log: Vec::new(),
}
}
/// Appends a styled message to the log.
pub fn log(&mut self, line: LogLine) {
self.log.push(line);
}
/// Attempts to move the player by `(dx, dy)` cells.
+2
View File
@@ -1,4 +1,6 @@
/// Core game types: [`game::Board`], [`game::Glyph`], [`game::Archetype`], etc.
pub mod game;
/// Styled log messages ([`log::LogLine`]) for the in-game message feed.
pub mod log;
/// Map file loading and saving (`.toml` format).
pub mod map_file;
+63
View File
@@ -0,0 +1,63 @@
//! Styled log messages for the in-game message feed.
//!
//! A [`LogLine`] is one message in the game's log; it is a sequence of
//! [`LogSpan`]s so a single message can mix colors (e.g. a rainbow status
//! badge). Colors are stored as UI-agnostic [`Rgba8`] values — kiln-core does
//! not depend on any front-end — and each front-end converts a `LogLine` into
//! its own styled-text type at render time.
use color::Rgba8;
/// One run of text within a [`LogLine`], with optional foreground/background
/// colors. `None` for a color means "use the terminal/front-end default".
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LogSpan {
/// The text of this run.
pub text: String,
/// Foreground color, or `None` to inherit the default.
pub fg: Option<Rgba8>,
/// Background color, or `None` to inherit the default.
pub bg: Option<Rgba8>,
}
/// A single, possibly multi-colored log message: an ordered list of [`LogSpan`]s.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct LogLine {
/// The styled runs that make up the message, in display order.
pub spans: Vec<LogSpan>,
}
impl LogLine {
/// Creates an empty line, to be filled with [`LogLine::push`].
pub fn new() -> Self {
Self { spans: Vec::new() }
}
/// Creates a line with a single default-colored span.
pub fn raw(text: impl Into<String>) -> Self {
Self {
spans: vec![LogSpan {
text: text.into(),
fg: None,
bg: None,
}],
}
}
/// Appends a styled span and returns `self`, so calls can be chained when
/// building a multi-color line.
pub fn push(mut self, text: impl Into<String>, fg: Option<Rgba8>, bg: Option<Rgba8>) -> Self {
self.spans.push(LogSpan {
text: text.into(),
fg,
bg,
});
self
}
/// Add a whole other LogLine, all its spans, on to the end of this one.
pub fn append(mut self, mut other: LogLine) -> Self {
self.spans.append(&mut other.spans);
self
}
}