From e7ad87c7301f266dece36e7558c0f212e370aac6 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sun, 14 Jul 2019 14:29:55 -0400 Subject: Add (statically-included) entity raws Add a system for statically-included entity raws (which necessitated making a deserializable existential Color struct) and test it out by initializing the game (for now) with a single on-screen gormlak. --- src/display/color.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/display/mod.rs | 5 +- 2 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/display/color.rs (limited to 'src/display') diff --git a/src/display/color.rs b/src/display/color.rs new file mode 100644 index 000000000000..7de1f124b704 --- /dev/null +++ b/src/display/color.rs @@ -0,0 +1,149 @@ +use serde::de::{self, Unexpected, Visitor}; +use std::fmt; +use std::marker::PhantomData; +use termion::color; + +#[derive(Debug)] +pub struct Color(Box); + +unsafe impl Sync for Color {} +unsafe impl Send for Color {} + +impl Color { + pub fn new(c: C) -> Self { + Color(Box::new(c)) + } +} + +impl color::Color for Color { + fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.write_fg(f) + } + + fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.write_bg(f) + } +} + +impl<'a> color::Color for &'a Color { + fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.write_fg(f) + } + + fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.write_bg(f) + } +} + +pub struct ColorVisitor { + marker: PhantomData Color>, +} + +impl ColorVisitor { + fn new() -> Self { + ColorVisitor { + marker: PhantomData, + } + } +} + +impl<'de> Visitor<'de> for ColorVisitor { + type Value = Color; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("A color") + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + match v.to_lowercase().as_ref() { + "black" => Ok(Color(Box::new(color::Black))), + "blue" => Ok(Color(Box::new(color::Blue))), + "cyan" => Ok(Color(Box::new(color::Cyan))), + "green" => Ok(Color(Box::new(color::Green))), + "light black" | "light_black" => { + Ok(Color(Box::new(color::LightBlack))) + } + "light blue" | "light_blue" => { + Ok(Color(Box::new(color::LightBlue))) + } + "light cyan" | "light_cyan" => { + Ok(Color(Box::new(color::LightCyan))) + } + "light green" | "light_green" => { + Ok(Color(Box::new(color::LightGreen))) + } + "light magenta" | "light_magenta" => { + Ok(Color(Box::new(color::LightMagenta))) + } + "light red" | "light_red" => Ok(Color(Box::new(color::LightRed))), + "light white" | "light_white" => { + Ok(Color(Box::new(color::LightWhite))) + } + "light yellow" | "light_yellow" => { + Ok(Color(Box::new(color::LightYellow))) + } + "magenta" => Ok(Color(Box::new(color::Magenta))), + "magenta" => Ok(Color(Box::new(color::Magenta))), + "red" => Ok(Color(Box::new(color::Red))), + "white" => Ok(Color(Box::new(color::White))), + "yellow" => Ok(Color(Box::new(color::Yellow))), + _ => Err(de::Error::invalid_value( + Unexpected::Str(v), + &"a valid color", + )), + } + } + + fn visit_map(self, mut map: A) -> Result + where + A: de::MapAccess<'de>, + { + let mut red = None; + let mut green = None; + let mut blue = None; + while let Some((k, v)) = map.next_entry()? { + match k { + "red" => { + red = Some(v); + } + "green" => { + green = Some(v); + } + "blue" => { + blue = Some(v); + } + _ => { + return Err(de::Error::unknown_field( + k, + &["red", "green", "blue"], + )); + } + } + } + + match (red, green, blue) { + (Some(r), Some(g), Some(b)) => { + Ok(Color(Box::new(color::Rgb(r, g, b)))) + } + (None, _, _) => Err(de::Error::missing_field("red")), + (_, None, _) => Err(de::Error::missing_field("green")), + (_, _, None) => Err(de::Error::missing_field("blue")), + } + } + + fn visit_u8(self, v: u8) -> Result { + Ok(Color(Box::new(color::AnsiValue(v)))) + } +} + +impl<'de> serde::Deserialize<'de> for Color { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_any(ColorVisitor::new()) + } +} diff --git a/src/display/mod.rs b/src/display/mod.rs index 9e15a0d97d62..3e30200ac723 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,3 +1,4 @@ +pub mod color; pub mod draw_box; pub mod utils; pub mod viewport; @@ -17,13 +18,13 @@ pub trait Draw: Positioned { fn do_draw(&self, out: &mut Write) -> io::Result<()>; } -impl Draw for &T { +impl Draw for &T { fn do_draw(&self, out: &mut Write) -> io::Result<()> { (**self).do_draw(out) } } -impl Draw for Box { +impl Draw for Box { fn do_draw(&self, out: &mut Write) -> io::Result<()> { (**self).do_draw(out) } -- cgit 1.4.1