Skip to main content

TileCamera

Struct TileCamera 

Source
pub struct TileCamera { /* private fields */ }
Expand description

The tile-map sibling of Camera.

Panning and clamping are paced in tiles rather than screen cells, and tile_rect/tile_surface project one tile to a zoom.width() x zoom.height() block of screen cells instead of Camera’s one-cell-to-one-cell picture.

Internally this owns a Camera counted in tiles instead of screen cells, so panning, clamping, and centering are exactly Camera’s own logic, applied to a tile grid; zoom only enters when projecting a tile to its screen-cell footprint.

§Examples

use retroglyph_core::grid::{Pos, Rect, Size};
use retroglyph_ui::camera::TileCamera;

// A 12x8 screen viewport onto a 20x20 tile world, at 3x2 screen cells per tile.
let mut cam = TileCamera::new(Rect::new(0, 0, 12, 8), Size::new(20, 20), Size::new(3, 2));
cam.center_on(Pos::new(10, 10));
assert_eq!(cam.tile_rect(Pos::new(10, 10)).width(), 3);

Implementations§

Source§

impl TileCamera

Source

pub fn cells(&self) -> impl Iterator<Item = (Pos, Pos)>

Iterate the visible tiles as (tile, screen) position pairs, in row-major order, where screen is the tile’s top-left screen cell. Only tiles that exist in the world are yielded, so the caller can fill the rest of the viewport with a background. The tile equivalent of Camera::cells: one entry per tile, not per screen cell, so cells().count() is a tile count even at a zoom where each tile covers several screen cells.

Source

pub fn screen_to_tile(&self, screen: Pos) -> Option<Pos>

Map a screen position back to a tile position, or None if it is outside the viewport or beyond the world (useful for mouse picking at a non-default zoom). The tile equivalent of Camera::screen_to_world: where that divides by 1, this divides by zoom, so it agrees with tile_rect about which tile a screen cell belongs to.

§Examples
use retroglyph_core::grid::{Pos, Rect, Size};
use retroglyph_ui::camera::TileCamera;

let cam = TileCamera::new(Rect::new(0, 0, 12, 8), Size::new(20, 20), Size::new(3, 2));
// Any screen cell inside tile (1, 0)'s 3x2 footprint maps back to (1, 0).
assert_eq!(cam.screen_to_tile(Pos::new(4, 1)), Some(Pos::new(1, 0)));
Source

pub fn tile_rect(&self, tile: Pos) -> Rect

The absolute screen rect a tile’s footprint covers at this camera’s zoom, clipped to the viewport. An empty Rect (zero width or height) means no part of the tile is visible.

tile_rect only clips to the viewport, not to world: a tile’s existence in the world is the caller’s own concern.

A tile straddling the viewport edge reports only the visible slice of its full, ideal-sized footprint, not the full footprint or an empty Rect, matching how Camera::surface clips a multi-cell draw that’s only partially on screen instead of dropping it entirely.

§Examples
use retroglyph_core::grid::{Pos, Rect, Size};
use retroglyph_ui::camera::TileCamera;

let mut cam = TileCamera::new(Rect::new(0, 0, 10, 10), Size::new(20, 20), Size::new(3, 2));

// tile (0, 0) is drawn at origin (0, 0) here, so its footprint covers a 3x2 block.
assert_eq!(cam.tile_rect(Pos::new(0, 0)), Rect::new(0, 0, 3, 2));

// A tile straddling the viewport's right edge is clipped to what's actually visible.
let cam = TileCamera::new(Rect::new(0, 0, 4, 4), Size::new(20, 20), Size::new(3, 3));
assert_eq!(cam.tile_rect(Pos::new(1, 0)), Rect::new(3, 0, 1, 3));
Source

pub fn tile_surface<'a>( &self, tile: Pos, surface: &'a mut Surface<'_>, ) -> Option<Surface<'a>>

A view of surface scoped to one tile’s footprint at this camera’s zoom, or None if none of that footprint is visible.

The returned surface’s own coordinate space is tile-local: (0, 0) is the tile’s own top-left corner, and put/print/the rest of Surface’s drawing methods take positions in 0..zoom.width() by 0..zoom.height(), the same way a small standalone Surface would for a zoom.width() x zoom.height() sprite. A tile straddling the viewport edge is still clipped automatically: only the on-screen slice of it accepts writes.

Calling this once per visible tile (for example every (tile, _) pair from cells) replaces hand-rolled tile-range-plus-offset math with one drawable region per tile.

§Examples
use retroglyph_core::color::Style;
use retroglyph_core::grid::{Grid, Pos, Rect, Size};
use retroglyph_core::surface::Surface;
use retroglyph_ui::camera::TileCamera;

let mut grid = Grid::new(10, 10);
let mut root = Surface::new(&mut grid, Rect::new(0, 0, 10, 10), 0);

let cam = TileCamera::new(Rect::new(0, 0, 10, 10), Size::new(20, 20), Size::new(3, 2));

// tile (1, 0)'s footprint covers screen cells (3, 0)..(6, 2); draw distinct glyphs at
// two corners of it in tile-local coordinates.
let mut tile = cam.tile_surface(Pos::new(1, 0), &mut root).expect("tile is visible");
tile.put(Pos::new(0, 0), '[', Style::default());
tile.put(Pos::new(2, 1), ']', Style::default());

assert_eq!(grid[Pos::new(3, 0)].glyph(), '[');
assert_eq!(grid[Pos::new(5, 1)].glyph(), ']');

A tile straddling the viewport edge only accepts writes to its visible slice; the rest is silently dropped, like any other out-of-clip Surface write.

use retroglyph_core::color::Style;
use retroglyph_core::grid::{Grid, Pos, Rect, Size};
use retroglyph_core::surface::Surface;
use retroglyph_ui::camera::TileCamera;

let mut grid = Grid::new(10, 10);
let cam = TileCamera::new(Rect::new(0, 0, 4, 4), Size::new(20, 20), Size::new(3, 3));

// This tile's ideal footprint is (3, 0, 3, 3); only its leftmost column (3, 0)..(4, 3)
// is inside the 4-wide viewport.
{
    let mut root = Surface::new(&mut grid, Rect::new(0, 0, 10, 10), 0);
    let mut tile = cam.tile_surface(Pos::new(1, 0), &mut root).expect("tile is visible");
    tile.put(Pos::new(0, 0), 'L', Style::default()); // the tile's own visible column.
    tile.put(Pos::new(2, 0), 'R', Style::default()); // clipped off past the viewport edge.
}

assert_eq!(grid[Pos::new(3, 0)].glyph(), 'L');
assert_eq!(grid[Pos::new(5, 0)].glyph(), ' ');

// A tile entirely outside the viewport has nothing visible to draw into.
let mut root = Surface::new(&mut grid, Rect::new(0, 0, 10, 10), 0);
assert!(cam.tile_surface(Pos::new(10, 10), &mut root).is_none());
Source§

impl TileCamera

Source

pub fn new(viewport: Rect, world: Size, zoom: Size) -> Self

Create a tile camera drawing into viewport (screen cells) over a world of tiles, at zoom screen cells per tile. The initial origin is (0, 0); call center_on to follow a target.

A zero zoom axis clamps to 1, the same as set_zoom.

Source

pub const fn viewport(&self) -> Rect

The screen rectangle the world is drawn into.

Source

pub const fn world(&self) -> Size

The world dimensions, in tiles.

Source

pub const fn origin(&self) -> Pos

The tile shown at the viewport’s top-left corner.

Source

pub const fn zoom(&self) -> Size

How many screen cells one tile covers, per axis. (1, 1) by default: one tile to one screen cell, same as an un-zoomed Camera.

Source

pub fn set_zoom(&mut self, zoom: Size)

Set how many screen cells one tile covers, per axis, re-deriving the tile-unit viewport from the current screen viewport and re-clamping the origin so it stays in bounds for the new tile-count viewport.

A zero width or height clamps to 1: a zero-size tile has no meaningful footprint to draw into, so this refuses to create one rather than silently making every tile disappear.

§Examples
use retroglyph_core::grid::{Rect, Size};
use retroglyph_ui::camera::TileCamera;

let mut cam = TileCamera::new(Rect::new(0, 0, 10, 10), Size::new(20, 20), Size::new(1, 1));
cam.set_zoom(Size::new(3, 2));
assert_eq!(cam.zoom(), Size::new(3, 2));

// A zero axis clamps to 1 rather than producing an empty tile footprint.
cam.set_zoom(Size::new(0, 4));
assert_eq!(cam.zoom(), Size::new(1, 4));
Source

pub fn set_viewport(&mut self, viewport: Rect)

Replace the viewport (for example after a terminal resize), keeping the world and zoom unchanged and re-clamping the origin so it stays in bounds.

Source

pub fn set_world(&mut self, world: Size)

Replace the world dimensions, in tiles, keeping the viewport and zoom unchanged and re-clamping the origin so it stays in bounds.

Source

pub fn center_on(&mut self, target: Pos)

Center the view on target (a tile position), clamped to the world edges so the viewport never scrolls past [0, world) tiles. The tile equivalent of Camera::center_on.

Source

pub fn set_origin(&mut self, origin: Pos)

Set the top-left tile directly, clamped to the world edges like center_on. The tile equivalent of Camera::set_origin.

Source

pub fn scroll_by(&mut self, dx: i32, dy: i32)

Scroll the view by a signed tile delta, clamped to the world edges like set_origin. The tile equivalent of Camera::scroll_by.

Source

pub fn visible_bounds(&self) -> Rect

The tile rectangle currently visible, in tile coordinates, clamped to world bounds. The tile equivalent of Camera::visible_bounds.

Trait Implementations§

Source§

impl Clone for TileCamera

Source§

fn clone(&self) -> TileCamera

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for TileCamera

Source§

impl Debug for TileCamera

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for TileCamera

Source§

impl PartialEq for TileCamera

Source§

fn eq(&self, other: &TileCamera) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for TileCamera

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<C> WithAlpha for C
where C: Copy,

§

fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>

Wraps self with alpha, storing alpha before the color in memory (see [AlphaFirst]).
§

fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>

Wraps self with alpha, storing alpha after the color in memory (see [AlphaLast]).