🔥 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 std::time::Duration;
use veccell::{VecRef, VecRefMut};
/** Provides an interface between a [`Tile`] and its parent [`Pane`] during [`Tile::update`].
@ -483,8 +484,8 @@ impl UpdateCommit {
pub struct InitContext<'a> {
pub world: &'a World,
pub pane: &'a Pane,
pub world_coordinates: (i32, i32),
pub pane_coordinates: (String, usize, usize),
pub world_coords: (i32, i32),
pub pane_coords: (String, usize, usize),
}
impl<'a> InitContext<'a> {
@ -495,11 +496,52 @@ impl<'a> InitContext<'a> {
Some(InitContext {
world,
pane,
world_coordinates: (
world_coords: (
position.0 + coordinates.1 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::context::{InitContext, UpdateContext};
pub use crate::context::{DrawContext, InitContext, UpdateContext};
pub use crate::signal::{Signal, Value};
pub use crate::tile::Tile;
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`].
/// 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() {
let x = x as i32 + dx + self.position.0 as i32;
let y = y as i32 + dy + self.position.1 as i32;
let ctx = DrawContext::new(self, (x, y), (dx, dy), blink.clone())
.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);
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(1, 0).unwrap().ch, '|');
@ -574,7 +574,7 @@ mod test {
// With offset (1, 0)
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(2, 0).unwrap().ch, '|');
@ -587,7 +587,7 @@ mod test {
// With offset (0, 1)
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(1, 1).unwrap().ch, '|');
@ -600,7 +600,7 @@ mod test {
// Draw outside of bounds with offset (2, 2)
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, '-');
for y in 0..3 {
@ -632,7 +632,7 @@ mod test {
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 + 3, 3 + 1).unwrap().ch, '|');

@ -94,9 +94,9 @@ impl FullTile {
/// Draws itself on a [`TextSurface`] at `(x, y)`.
/// 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 {
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
#[inline]
#[allow(unused_variables)]
fn draw(&self, x: i32, y: i32, state: State, surface: &mut TextSurface) {
if let (Ok(x), Ok(y)) = (x.try_into(), y.try_into()) {
surface.set(x, y, self.draw_simple(state));
fn draw<'b>(&'b self, surface: &mut TextSurface, ctx: DrawContext<'b>) {
if let (Ok(x), Ok(y)) = (
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 std::time::Duration;
/// 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))
@ -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)]
mod test {
use super::*;

@ -1,17 +1,27 @@
use super::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{Duration, Instant};
use veccell::VecRef;
#[derive(Debug, Serialize, Deserialize)]
pub struct World {
panes: HashMap<String, Pane>,
#[serde(default = "Instant::now")]
#[serde(skip)]
blink_start: Instant,
#[serde(default)]
blink_speed: Duration,
}
impl World {
pub fn new() -> Self {
Self {
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) {
let blink = Blink::new(Instant::now() - self.blink_start, self.blink_speed);
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 mut surface = TextSurface::new(width, height);
let blink = Blink::new(Instant::now() - self.blink_start, self.blink_speed);
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)

@ -134,7 +134,7 @@ impl Sender {
impl Tile for Sender {
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>) {
@ -168,11 +168,11 @@ impl Tile for Sender {
// TODO: read self.signals to determine the state of each char
// 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 {
(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 {
(x, y)
(ctx.surface_coords.0, ctx.surface_coords.1)
};
let mut count = 0;

Loading…
Cancel
Save