🔥 Refactor Tile::draw, wip Blink structure

main
Shad Amethyst 2 years ago
parent 7d97cc354c
commit c264001ee0
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -1,4 +1,5 @@
use super::*; use super::*;
use std::time::Duration;
use veccell::{VecRef, VecRefMut}; use veccell::{VecRef, VecRefMut};
/** Provides an interface between a [`Tile`] and its parent [`Pane`] during [`Tile::update`]. /** Provides an interface between a [`Tile`] and its parent [`Pane`] during [`Tile::update`].
@ -483,8 +484,8 @@ impl UpdateCommit {
pub struct InitContext<'a> { pub struct InitContext<'a> {
pub world: &'a World, pub world: &'a World,
pub pane: &'a Pane, pub pane: &'a Pane,
pub world_coordinates: (i32, i32), pub world_coords: (i32, i32),
pub pane_coordinates: (String, usize, usize), pub pane_coords: (String, usize, usize),
} }
impl<'a> InitContext<'a> { impl<'a> InitContext<'a> {
@ -495,11 +496,52 @@ impl<'a> InitContext<'a> {
Some(InitContext { Some(InitContext {
world, world,
pane, pane,
world_coordinates: ( world_coords: (
position.0 + coordinates.1 as i32, position.0 + coordinates.1 as i32,
position.1 + coordinates.2 as i32, position.1 + coordinates.2 as i32,
), ),
pane_coordinates: coordinates, pane_coords: coordinates,
})
}
}
#[derive(Clone)]
#[non_exhaustive]
pub struct DrawContext<'a> {
pub state: State,
pub pane: &'a Pane,
pub world_coords: (i32, i32),
pub pane_coords: (usize, usize),
pub surface_coords: (i32, i32),
pub blink: Blink,
}
impl<'a> DrawContext<'a> {
pub fn new(
pane: &'a Pane,
pane_coords: (usize, usize),
visual_shift: (i32, i32),
blink: Blink,
) -> Option<Self> {
let tile = pane.get(pane_coords)?;
let pane_position = pane.position();
let world_coords = (
pane_position.0 + pane_coords.0 as i32,
pane_position.1 + pane_coords.1 as i32,
);
Some(DrawContext {
state: tile.state(),
pane,
world_coords,
pane_coords,
surface_coords: (
world_coords.0 + visual_shift.0,
world_coords.1 + visual_shift.1,
),
blink,
}) })
} }
} }

@ -39,7 +39,7 @@ pub mod prelude {
pub use crate::text::{TextChar, TextSurface}; pub use crate::text::{TextChar, TextSurface};
pub use crate::context::{InitContext, UpdateContext}; pub use crate::context::{DrawContext, InitContext, UpdateContext};
pub use crate::signal::{Signal, Value}; pub use crate::signal::{Signal, Value};
pub use crate::tile::Tile; pub use crate::tile::Tile;
pub use crate::utils::*; pub use crate::utils::*;

@ -523,12 +523,12 @@ impl Pane {
/// Draws the Pane at `(dx + self.position.0, dy + self.position.1)` on a [`TextSurface`]. /// Draws the Pane at `(dx + self.position.0, dy + self.position.1)` on a [`TextSurface`].
/// Empty tiles will leave the `TextSurface` untouched, but tiles are free to modify the characters around them. /// Empty tiles will leave the `TextSurface` untouched, but tiles are free to modify the characters around them.
pub fn draw(&self, dx: i32, dy: i32, surface: &mut TextSurface) { pub fn draw(&self, dx: i32, dy: i32, surface: &mut TextSurface, blink: Blink) {
for (x, y, tile) in self.tiles_iter() { for (x, y, tile) in self.tiles_iter() {
let x = x as i32 + dx + self.position.0 as i32; let ctx = DrawContext::new(self, (x, y), (dx, dy), blink.clone())
let y = y as i32 + dy + self.position.1 as i32; .unwrap_or_else(|| unreachable!());
tile.draw(x, y, surface); tile.draw(surface, ctx);
} }
} }
} }
@ -561,7 +561,7 @@ mod test {
); );
test_set_signal!(pane, (0, 0), Direction::Right); test_set_signal!(pane, (0, 0), Direction::Right);
pane.draw(0, 0, &mut surface); pane.draw(0, 0, &mut surface, Blink::default());
assert_eq!(surface.get(0, 0).unwrap().ch, '-'); assert_eq!(surface.get(0, 0).unwrap().ch, '-');
assert_eq!(surface.get(1, 0).unwrap().ch, '|'); assert_eq!(surface.get(1, 0).unwrap().ch, '|');
@ -574,7 +574,7 @@ mod test {
// With offset (1, 0) // With offset (1, 0)
let mut surface = TextSurface::new(3, 3); let mut surface = TextSurface::new(3, 3);
pane.draw(1, 0, &mut surface); pane.draw(1, 0, &mut surface, Blink::default());
assert_eq!(surface.get(1, 0).unwrap().ch, '-'); assert_eq!(surface.get(1, 0).unwrap().ch, '-');
assert_eq!(surface.get(2, 0).unwrap().ch, '|'); assert_eq!(surface.get(2, 0).unwrap().ch, '|');
@ -587,7 +587,7 @@ mod test {
// With offset (0, 1) // With offset (0, 1)
let mut surface = TextSurface::new(3, 3); let mut surface = TextSurface::new(3, 3);
pane.draw(0, 1, &mut surface); pane.draw(0, 1, &mut surface, Blink::default());
assert_eq!(surface.get(0, 1).unwrap().ch, '-'); assert_eq!(surface.get(0, 1).unwrap().ch, '-');
assert_eq!(surface.get(1, 1).unwrap().ch, '|'); assert_eq!(surface.get(1, 1).unwrap().ch, '|');
@ -600,7 +600,7 @@ mod test {
// Draw outside of bounds with offset (2, 2) // Draw outside of bounds with offset (2, 2)
let mut surface = TextSurface::new(3, 3); let mut surface = TextSurface::new(3, 3);
pane.draw(2, 2, &mut surface); pane.draw(2, 2, &mut surface, Blink::default());
assert_eq!(surface.get(2, 2).unwrap().ch, '-'); assert_eq!(surface.get(2, 2).unwrap().ch, '-');
for y in 0..3 { for y in 0..3 {
@ -632,7 +632,7 @@ mod test {
let mut surface = TextSurface::new(9, 9); let mut surface = TextSurface::new(9, 9);
pane.draw(5, 3, &mut surface); pane.draw(5, 3, &mut surface, Blink::default());
assert_eq!(surface.get(5 + 2, 3 + 1).unwrap().ch, '-'); assert_eq!(surface.get(5 + 2, 3 + 1).unwrap().ch, '-');
assert_eq!(surface.get(5 + 3, 3 + 1).unwrap().ch, '|'); assert_eq!(surface.get(5 + 3, 3 + 1).unwrap().ch, '|');

@ -94,9 +94,9 @@ impl FullTile {
/// Draws itself on a [`TextSurface`] at `(x, y)`. /// Draws itself on a [`TextSurface`] at `(x, y)`.
/// If the tile is empty, does nothing /// If the tile is empty, does nothing
pub fn draw(&self, x: i32, y: i32, surface: &mut TextSurface) { pub fn draw<'b>(&'b self, surface: &mut TextSurface, ctx: DrawContext<'b>) {
if let Some(cell) = &self.cell { if let Some(cell) = &self.cell {
cell.draw(x, y, self.state, surface); cell.draw(surface, ctx);
} }
} }
} }

@ -169,9 +169,12 @@ pub trait Tile: std::clone::Clone + std::fmt::Debug + Serialize + for<'d> Deseri
// TODO: Use a 2d slice type // TODO: Use a 2d slice type
#[inline] #[inline]
#[allow(unused_variables)] #[allow(unused_variables)]
fn draw(&self, x: i32, y: i32, state: State, surface: &mut TextSurface) { fn draw<'b>(&'b self, surface: &mut TextSurface, ctx: DrawContext<'b>) {
if let (Ok(x), Ok(y)) = (x.try_into(), y.try_into()) { if let (Ok(x), Ok(y)) = (
surface.set(x, y, self.draw_simple(state)); ctx.surface_coords.0.try_into(),
ctx.surface_coords.1.try_into(),
) {
surface.set(x, y, self.draw_simple(ctx.state));
} }
} }

@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration;
/// Represents one or many undirected orientation(s), since we are in a 2D grid, /// Represents one or many undirected orientation(s), since we are in a 2D grid,
/// this may either be [Horizontal](Orientation::Horizontal), [Vertical](Orientation::Vertical) or both ([Any](Orientation::Any)) /// this may either be [Horizontal](Orientation::Horizontal), [Vertical](Orientation::Vertical) or both ([Any](Orientation::Any))
@ -125,6 +126,25 @@ impl Default for State {
} }
} }
/// Stores information for blinking
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub struct Blink {
pub elapsed: Duration,
pub blink_speed: Duration,
}
impl Blink {
pub fn new(elapsed: Duration, blink_speed: Duration) -> Self {
Self {
elapsed,
blink_speed,
}
}
// TODO: methods for blinking text
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

@ -1,17 +1,27 @@
use super::*; use super::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::time::{Duration, Instant};
use veccell::VecRef; use veccell::VecRef;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct World { pub struct World {
panes: HashMap<String, Pane>, panes: HashMap<String, Pane>,
#[serde(default = "Instant::now")]
#[serde(skip)]
blink_start: Instant,
#[serde(default)]
blink_speed: Duration,
} }
impl World { impl World {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
panes: HashMap::new(), panes: HashMap::new(),
blink_start: Instant::now(),
blink_speed: Duration::default(),
} }
} }
@ -149,8 +159,9 @@ impl World {
} }
pub fn draw(&self, dx: i32, dy: i32, surface: &mut TextSurface) { pub fn draw(&self, dx: i32, dy: i32, surface: &mut TextSurface) {
let blink = Blink::new(Instant::now() - self.blink_start, self.blink_speed);
for pane in self.panes.values() { for pane in self.panes.values() {
pane.draw(dx, dy, surface); pane.draw(dx, dy, surface, blink.clone());
} }
} }
@ -177,9 +188,10 @@ impl std::fmt::Display for World {
let height = (bounds.3 - bounds.2) as usize; let height = (bounds.3 - bounds.2) as usize;
let mut surface = TextSurface::new(width, height); let mut surface = TextSurface::new(width, height);
let blink = Blink::new(Instant::now() - self.blink_start, self.blink_speed);
for pane in self.panes.values() { for pane in self.panes.values() {
pane.draw(bounds.0, bounds.2, &mut surface); pane.draw(bounds.0, bounds.2, &mut surface, blink.clone());
} }
<TextSurface as std::fmt::Display>::fmt(&surface, f) <TextSurface as std::fmt::Display>::fmt(&surface, f)

@ -134,7 +134,7 @@ impl Sender {
impl Tile for Sender { impl Tile for Sender {
fn init<'b>(&'b mut self, context: InitContext<'b>) { fn init<'b>(&'b mut self, context: InitContext<'b>) {
self.calculate_path(context.world_coordinates, context.world) self.calculate_path(context.world_coords, context.world)
} }
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) { fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
@ -168,11 +168,11 @@ impl Tile for Sender {
// TODO: read self.signals to determine the state of each char // TODO: read self.signals to determine the state of each char
// TODO: automated test // TODO: automated test
fn draw(&self, x: i32, y: i32, _state: State, surface: &mut TextSurface) { fn draw(&self, surface: &mut TextSurface, ctx: DrawContext) {
let (x, y) = if self.path.len() > 0 { let (x, y) = if self.path.len() > 0 {
(x - self.path[0].0, y - self.path[0].1) (ctx.surface_coords.0 - self.path[0].0, ctx.surface_coords.1 - self.path[0].1)
} else { } else {
(x, y) (ctx.surface_coords.0, ctx.surface_coords.1)
}; };
let mut count = 0; let mut count = 0;

Loading…
Cancel
Save