diff options
author | Griffin Smith <root@gws.fyi> | 2019-07-07T16·41-0400 |
---|---|---|
committer | Griffin Smith <root@gws.fyi> | 2019-07-07T16·41-0400 |
commit | c643ee1dfcb8d44b8cd198c768f31dd7659f2ff9 (patch) | |
tree | 8178c613e55c00944a6417a85ad304cf2af05587 /src/display/viewport.rs | |
parent | 78a52142d191d25a74cb2124d5cca8a69d51ba7f (diff) |
Add messages, with global lookup map
Add support for messages, along with a global lookup map and random choice of messages.
Diffstat (limited to 'src/display/viewport.rs')
-rw-r--r-- | src/display/viewport.rs | 107 |
1 files changed, 71 insertions, 36 deletions
diff --git a/src/display/viewport.rs b/src/display/viewport.rs index bd2fac07146f..24cc5272cb8e 100644 --- a/src/display/viewport.rs +++ b/src/display/viewport.rs @@ -1,5 +1,8 @@ +use super::BoxStyle; use super::Draw; -use super::{make_box, BoxStyle}; +use crate::display::draw_box::draw_box; +use crate::display::utils::clone_times; +use crate::display::utils::times; use crate::types::{BoundingBox, Position, Positioned}; use std::fmt::{self, Debug}; use std::io::{self, Write}; @@ -10,36 +13,47 @@ pub struct Viewport<W> { /// Generally the size of the terminal, and positioned at 0, 0 pub outer: BoundingBox, + /// The box describing the game part of the viewport. + pub game: BoundingBox, + /// The box describing the inner part of the viewport /// - /// Its position is relative to `outer.inner()`, and its size should generally not - /// be smaller than outer + /// Its position is relative to `outer.inner()`, and its size should + /// generally not be smaller than outer pub inner: BoundingBox, /// The actual screen that the viewport writes to pub out: W, } - -impl<W> Debug for Viewport<W> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Viewport {{ outer: {:?}, inner: {:?}, out: <OUT> }}", - self.outer, self.inner - ) +impl<W> Viewport<W> { + pub fn new(outer: BoundingBox, inner: BoundingBox, out: W) -> Self { + Viewport { + outer, + inner, + out, + game: outer.move_tr_corner(Position { x: 0, y: 1 }), + } } -} -impl<W> Viewport<W> { /// Returns true if the (inner-relative) position of the given entity is /// visible within this viewport - fn visible<E: Positioned>(&self, ent: &E) -> bool { - self.on_screen(ent.position()).within(self.outer.inner()) + pub fn visible<E: Positioned>(&self, ent: &E) -> bool { + self.on_screen(ent.position()).within(self.game.inner()) } /// Convert the given inner-relative position to one on the actual screen fn on_screen(&self, pos: Position) -> Position { - pos + self.inner.position + self.outer.inner().position + pos + self.inner.position + self.game.inner().position + } +} + +impl<W> Debug for Viewport<W> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "Viewport {{ outer: {:?}, inner: {:?}, out: <OUT> }}", + self.outer, self.inner + ) } } @@ -49,25 +63,46 @@ impl<W: Write> Viewport<W> { if !self.visible(entity) { return Ok(()); } - write!( - self, - "{}", - (entity.position() - + self.inner.position - + self.outer.inner().position) - .cursor_goto() - )?; + self.cursor_goto(entity.position())?; entity.do_draw(self) } - /// Clear whatever is drawn at the given inner-relative position, if visible + /// Move the cursor to the given inner-relative position + pub fn cursor_goto(&mut self, pos: Position) -> io::Result<()> { + write!(self, "{}", self.on_screen(pos).cursor_goto()) + } + + /// Clear whatever single character is drawn at the given inner-relative + /// position, if visible pub fn clear(&mut self, pos: Position) -> io::Result<()> { write!(self, "{} ", self.on_screen(pos).cursor_goto(),) } /// Initialize this viewport by drawing its outer box to the screen pub fn init(&mut self) -> io::Result<()> { - write!(self, "{}", make_box(BoxStyle::Thin, self.outer.dimensions)) + draw_box(self, self.game, BoxStyle::Thin) + } + + /// Write a message to the message area on the screen + /// + /// Will overwrite any message already present, and if the given message is + /// longer than the screen will truncate. This means callers should handle + /// message buffering and ellipsisization + pub fn write_message(&mut self, msg: &str) -> io::Result<()> { + write!( + self, + "{}{}{}", + self.outer.position.cursor_goto(), + if msg.len() <= self.outer.dimensions.w as usize { + msg + } else { + &msg[0..self.outer.dimensions.w as usize] + }, + clone_times::<_, String>( + " ".to_string(), + self.outer.dimensions.w - msg.len() as u16 + ), + ) } } @@ -99,24 +134,24 @@ mod tests { #[test] fn test_visible() { - assert!(Viewport { - outer: BoundingBox::at_origin(Dimensions { w: 10, h: 10 }), - inner: BoundingBox { + assert!(Viewport::new( + BoundingBox::at_origin(Dimensions { w: 10, h: 10 }), + BoundingBox { position: Position { x: -10, y: -10 }, dimensions: Dimensions { w: 15, h: 15 }, }, - out: (), - } + () + ) .visible(&Position { x: 13, y: 13 })); - assert!(!Viewport { - outer: BoundingBox::at_origin(Dimensions { w: 10, h: 10 }), - inner: BoundingBox { + assert!(!Viewport::new( + BoundingBox::at_origin(Dimensions { w: 10, h: 10 }), + BoundingBox { position: Position { x: -10, y: -10 }, dimensions: Dimensions { w: 15, h: 15 }, }, - out: (), - } + (), + ) .visible(&Position { x: 1, y: 1 })); } |