mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 15:56:57 +02:00
fixes and refactors
- use macros for the evals - move some space stuff into submodules - partial update to doctests
This commit is contained in:
parent
b44dc02f33
commit
e074712459
9 changed files with 464 additions and 380 deletions
247
src/space.rs
247
src/space.rs
|
|
@ -1,144 +1,14 @@
|
|||
use crate::{*, draw::*};
|
||||
#[cfg(test)] use proptest_derive::Arbitrary;
|
||||
|
||||
/// Point with size.
|
||||
///
|
||||
/// ```
|
||||
/// let xywh = tengri::XYWH(0u16, 0, 0, 0);
|
||||
/// assert_eq!(tengri::XYWH(10u16, 10, 20, 20).center(), tengri::XY(20, 20));
|
||||
/// ```
|
||||
///
|
||||
/// * [ ] TODO: origin field (determines at which corner/side is X0 Y0)
|
||||
///
|
||||
#[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct XYWH<N: Coord>(pub N, pub N, pub N, pub N);
|
||||
impl From<&ratatui::prelude::Rect> for XYWH<u16> {
|
||||
fn from (rect: &ratatui::prelude::Rect) -> Self {
|
||||
Self(rect.x, rect.y, rect.width, rect.height)
|
||||
}
|
||||
}
|
||||
impl<N: Coord> X<N> for XYWH<N> { fn x (&self) -> N { self.0 } fn w (&self) -> N { self.2 } }
|
||||
impl<N: Coord> Y<N> for XYWH<N> { fn y (&self) -> N { self.0 } fn h (&self) -> N { self.2 } }
|
||||
impl<N: Coord> XYWH<N> {
|
||||
pub fn zero () -> Self {
|
||||
Self(0.into(), 0.into(), 0.into(), 0.into())
|
||||
}
|
||||
pub fn center (&self) -> (N, N) {
|
||||
let Self(x, y, w, h) = *self;
|
||||
(x.plus(w/2.into()), y.plus(h/2.into()))
|
||||
}
|
||||
pub fn centered (&self) -> (N, N) {
|
||||
let Self(x, y, w, h) = *self;
|
||||
(x.minus(w/2.into()), y.minus(h/2.into()))
|
||||
}
|
||||
pub fn centered_x (&self, n: N) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = (x.plus(w / 2.into())).minus(n / 2.into());
|
||||
let y_center = y.plus(h / 2.into());
|
||||
XYWH(x_center, y_center, n, 1.into())
|
||||
}
|
||||
pub fn centered_y (&self, n: N) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = x.plus(w / 2.into());
|
||||
let y_corner = (y.plus(h / 2.into())).minus(n / 2.into());
|
||||
XYWH(x_center, y_corner, 1.into(), n)
|
||||
}
|
||||
pub fn centered_xy (&self, [n, m]: [N;2]) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = (x.plus(w / 2.into())).minus(n / 2.into());
|
||||
let y_corner = (y.plus(h / 2.into())).minus(m / 2.into());
|
||||
XYWH(x_center, y_corner, n, m)
|
||||
}
|
||||
pub fn split_half (&self, direction: &Split) -> (Self, Self) {
|
||||
use Split::*;
|
||||
let XYWH(x, y, w, h) = self.xywh();
|
||||
match direction {
|
||||
South => (XYWH(x, y, w, h - h / 2.into()), XYWH(x, y + h / 2.into(), w, h / 2.into())),
|
||||
East => (XYWH(x, y, w - w / 2.into(), h), XYWH(x + w / 2.into(), y, w / 2.into(), h)),
|
||||
North => (XYWH(x, y + h / 2.into(), w, h - h / 2.into()), XYWH(x, y, w, h / 2.into())),
|
||||
West => (XYWH(x + w / 2.into(), y, w - w / 2.into(), h), XYWH(x, y, w / 2.into(), h)),
|
||||
Above | Below => (XYWH(x, y, w, h), XYWH(x, y, w, h))
|
||||
}
|
||||
}
|
||||
}
|
||||
mod xywh;
|
||||
pub use self::xywh::*;
|
||||
|
||||
/// Something that has `[0, 0]` at a particular point.
|
||||
pub trait HasOrigin { fn origin (&self) -> Origin;
|
||||
}
|
||||
impl<T: AsRef<Origin>> HasOrigin for T { fn origin (&self) -> Origin { *self.as_ref() } }
|
||||
pub struct Anchor<T>(Origin, T);
|
||||
impl<T> AsRef<Origin> for Anchor<T> {
|
||||
fn as_ref (&self) -> &Origin {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl<T: Screen, U: Draw<T>> Draw<T> for Anchor<U> {
|
||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
mod origin;
|
||||
pub use self::origin::*;
|
||||
|
||||
pub const fn origin_c <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::C, a)
|
||||
}
|
||||
pub const fn origin_x <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::X, a)
|
||||
}
|
||||
pub const fn origin_y <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::Y, a)
|
||||
}
|
||||
pub const fn origin_nw <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::NW, a)
|
||||
}
|
||||
pub const fn origin_n <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::N, a)
|
||||
}
|
||||
pub const fn origin_ne <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::NE, a)
|
||||
}
|
||||
pub const fn origin_w <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::W, a)
|
||||
}
|
||||
pub const fn origin_e <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::E, a)
|
||||
}
|
||||
pub const fn origin_sw <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::SW, a)
|
||||
}
|
||||
pub const fn origin_s <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::S, a)
|
||||
}
|
||||
pub const fn origin_se <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
Anchor(Origin::SE, a)
|
||||
}
|
||||
|
||||
/// Where is [0, 0] located?
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::draw::Origin;
|
||||
/// let _ = Origin::NW.align(())
|
||||
/// ```
|
||||
#[cfg_attr(test, derive(Arbitrary))]
|
||||
#[derive(Debug, Copy, Clone, Default)] pub enum Origin {
|
||||
#[default] C, X, Y, NW, N, NE, E, SE, S, SW, W
|
||||
}
|
||||
impl Origin {
|
||||
pub fn align <T: Screen> (&self, a: impl Draw<T>) -> impl Draw<T> {
|
||||
align(*self, a)
|
||||
}
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// use tengri::draw::{align, Origin::*};
|
||||
/// let _ = align(NW, "test");
|
||||
/// let _ = align(SE, "test");
|
||||
/// ```
|
||||
pub fn align <T: Screen> (origin: Origin, a: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T| { todo!() })
|
||||
}
|
||||
pub fn align_n <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||
align(Origin::N, a)
|
||||
}
|
||||
mod split;
|
||||
pub use self::split::*;
|
||||
|
||||
/// A numeric type that can be used as coordinate.
|
||||
///
|
||||
|
|
@ -174,88 +44,6 @@ pub trait Coord: Send + Sync + Copy
|
|||
fn atomic (self) -> AtomicUsize { AtomicUsize::new(self.into()) }
|
||||
}
|
||||
|
||||
/// A cardinal direction.
|
||||
#[cfg_attr(test, derive(Arbitrary))]
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Default)] pub enum Split {
|
||||
North, South, East, West, Above, #[default] Below
|
||||
}
|
||||
|
||||
pub const fn east <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::East.half(a, b)
|
||||
}
|
||||
pub const fn north <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::North.half(a, b)
|
||||
}
|
||||
pub const fn west <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::West.half(a, b)
|
||||
}
|
||||
pub const fn south <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::South.half(a, b)
|
||||
}
|
||||
pub const fn above <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::Above.half(a, b)
|
||||
}
|
||||
pub const fn below <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::Below.half(a, b)
|
||||
}
|
||||
impl Split {
|
||||
/// ```
|
||||
/// use tengri::draw::Split::*;
|
||||
/// let _ = Above.bsp((), ());
|
||||
/// let _ = Below.bsp((), ());
|
||||
/// let _ = North.bsp((), ());
|
||||
/// let _ = South.bsp((), ());
|
||||
/// let _ = East.bsp((), ());
|
||||
/// let _ = West.bsp((), ());
|
||||
/// ```
|
||||
pub const fn half <T: Screen> (&self, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T|{
|
||||
let (area_a, area_b) = to.xywh().split_half(self);
|
||||
let (origin_a, origin_b) = self.origins();
|
||||
let a = origin_a.align(a);
|
||||
let b = origin_b.align(b);
|
||||
match self {
|
||||
Self::Below => {
|
||||
to.place_at(area_b, &b);
|
||||
to.place_at(area_b, &a);
|
||||
},
|
||||
_ => {
|
||||
to.place_at(area_a, &a);
|
||||
to.place_at(area_a, &b);
|
||||
}
|
||||
}
|
||||
Ok(to.xywh()) // FIXME: compute and return actually used area
|
||||
})
|
||||
}
|
||||
/// Newly split areas begin at the center of the split
|
||||
/// to maintain centeredness in the user's field of view.
|
||||
///
|
||||
/// Use [align] to override that and always start
|
||||
/// at the top, bottom, etc.
|
||||
///
|
||||
/// ```
|
||||
/// /*
|
||||
///
|
||||
/// Split east: Split south:
|
||||
/// | | | | A |
|
||||
/// | <-A|B-> | |---------|
|
||||
/// | | | | B |
|
||||
///
|
||||
/// */
|
||||
/// ```
|
||||
const fn origins (&self) -> (Origin, Origin) {
|
||||
use Origin::*;
|
||||
match self {
|
||||
Self::South => (S, N),
|
||||
Self::East => (E, W),
|
||||
Self::North => (N, S),
|
||||
Self::West => (W, E),
|
||||
Self::Above => (C, C),
|
||||
Self::Below => (C, C),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Horizontal axis.
|
||||
pub trait X<N: Coord> {
|
||||
fn x (&self) -> N;
|
||||
|
|
@ -426,29 +214,6 @@ pub const fn wh_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
|||
pub const fn w_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||
pub const fn h_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||
|
||||
#[macro_export] macro_rules! north {
|
||||
($head:expr $(,)?) => { $head };
|
||||
($head:expr, $($tail:expr),* $(,)?) => { north($head, north!($($tail,)*)) };
|
||||
}
|
||||
#[macro_export] macro_rules! south {
|
||||
($head:expr $(,)?) => { $head };
|
||||
($head:expr, $($tail:expr),* $(,)?) => { south($head, south!($($tail,)*)) };
|
||||
}
|
||||
#[macro_export] macro_rules! east {
|
||||
($head:expr $(,)?) => { $head };
|
||||
($head:expr, $($tail:expr),* $(,)?) => { east($head, east!($($tail,)*)) };
|
||||
}
|
||||
#[macro_export] macro_rules! west {
|
||||
($head:expr $(, $tail:expr)* $(,)?) => { west($head, west!($($tail,)*)) };
|
||||
}
|
||||
#[macro_export] macro_rules! above {
|
||||
($head:expr $(, $tail:expr)* $(,)?) => { above($head, above!($($tail,)*)) };
|
||||
}
|
||||
#[macro_export] macro_rules! below {
|
||||
($head:expr $(,)?) => { $head };
|
||||
($head:expr, $($tail:expr),* $(,)?) => { below($head, below!($($tail,)*)) };
|
||||
}
|
||||
|
||||
/// Iterate over a collection of renderables:
|
||||
///
|
||||
/// ```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue