reorganize, add Azimuth

This commit is contained in:
facile pop culture reference 2026-07-06 20:40:52 +03:00
parent bf16288884
commit 1f60b43f61
26 changed files with 677 additions and 594 deletions

View file

@ -1,265 +0,0 @@
use super::*;
use Origin::*;
use Split::*;
/// 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
}
/// 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 trait Xy<N: Coord> {
fn x (&self) -> N;
fn y (&self) -> N;
}
pub trait Wh<N: Coord>: Wide<N> + Tall<N> {
fn wh (&self) -> [N;2];
}
pub trait Xywh<N: Coord>: Xy<N> + Wh<N> {
fn xywh (&self) -> XYWH<N> {
XYWH(self.x(), self.y(), self.w(), self.h())
}
}
pub trait Wide<N: Coord>: Xy<N> {
fn w (&self) -> N { N::zero() }
fn w_min (&self) -> N { self.w() }
fn w_max (&self) -> N { self.w() }
}
pub trait Tall<N: Coord> {
fn h (&self) -> N { N::zero() }
fn h_min (&self) -> N { self.h() }
fn h_max (&self) -> N { self.h() }
}
/// Point with size.
///
/// ```
/// use tengri::space::{XY, XYWH};
/// let xywh = XYWH(0u16, 0, 0, 0);
/// assert_eq!(XYWH(10u16, 10, 20, 20).center(), 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<N: Coord> Xy<N> for XYWH<N> {
fn x (&self) -> N { self.0 }
fn y (&self) -> N { self.1 }
}
impl<N: Coord> Wide<N> for XYWH<N> { fn w (&self) -> N { self.2 } }
impl<N: Coord> Tall<N> for XYWH<N> { fn h (&self) -> N { self.3 } }
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) {
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))
}
}
}
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, T: Wide<N> + Tall<N>> Wh<N> for T {
fn wh (&self) -> [N;2] {
[self.w(), self.h()]
}
}
impl<N: Coord, T: Xy<N> + Wh<N>> Xywh<N> for T {}
/// Shrink drawing area symmetrically.
///
/// ```
/// let padded = tengri::wh_pad("Hello");
/// ```
pub const fn wh_pad <T: Screen> (w: T::Unit, h: T::Unit, it: impl Draw<T>)
-> impl Draw<T>
{
thunk(move|to: &mut T|it.draw(todo!()))
}
/// Only draw content if area is above a certain size.
///
/// ```
/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5
/// ```
pub const fn wh_min <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, it: impl Draw<T>)
-> impl Draw<T>
{
thunk(move|to: &mut T|it.draw(todo!()))
}
/// Set the maximum width and/or height of the content.
///
/// ```
/// let max = tengri::wh_max(Some(3), Some(5), "Hello");
/// ```
pub const fn wh_max <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, it: impl Draw<T>)
-> impl Draw<T>
{
thunk(move|_to: &mut T|it.draw(todo!()))
}
/// Set the maximum width and/or height of the content.
///
/// ```
/// let exact = tengri::wh_exact(Some(3), Some(5), "Hello");
/// ```
pub const fn wh_exact <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, it: impl Draw<T>)
-> impl Draw<T>
{
thunk(move|_to: &mut T|it.draw(todo!()))
}
/// Limit size of drawing area
/// ```
/// let clipped = tengri::wh_clip(Some(3), Some(5), "Hello");
/// ```
pub const fn wh_clip <T: Screen> (
w: Option<T::Unit>, h: Option<T::Unit>, it: impl Draw<T>
) -> impl Draw<T> {
thunk(move|_to: &mut T|it.draw(todo!()))
}
pub const fn wh_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
todo!();
a
}
pub const fn w_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
todo!();
a
}
pub const fn h_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
todo!();
a
}
pub const fn h_max <T: Screen> (h: Option<T::Unit>, a: impl Draw<T>) -> impl Draw<T> {
wh_max(None, h, a)
}
pub const fn h_min <T: Screen> (h: Option<T::Unit>, a: impl Draw<T>) -> impl Draw<T> {
wh_min(None, h, a)
}
pub const fn h_exact <T: Screen> (h: T::Unit, c: impl Draw<T>) -> impl Draw<T> {
wh_exact(None, Some(h), c)
}
pub const fn w_max <T: Screen> (w: Option<T::Unit>, a: impl Draw<T>) -> impl Draw<T> {
wh_max(w, None, a)
}
pub const fn w_min <T: Screen> (w: Option<T::Unit>, a: impl Draw<T>) -> impl Draw<T> {
wh_min(w, None, a)
}
pub const fn w_exact <T: Screen> (w: T::Unit, c: impl Draw<T>) -> impl Draw<T> {
wh_exact(Some(w), None, c)
}
/// Shrink drawing area symmetrically.
///
/// ```
/// let padded = tengri::space::w_pad(3, "Hello");
/// ```
pub const fn w_pad <T: Screen> (x: T::Unit, draw: impl Draw<T>) -> impl Draw<T> {
thunk(move|to: &mut T|draw.draw(todo!()))
}
/// Shrink drawing area symmetrically.
///
/// ```
/// let padded = tengri::space::w_pad(3, "Hello");
/// ```
pub const fn h_pad <T: Screen> (x: T::Unit, draw: impl Draw<T>) -> impl Draw<T> {
thunk(move|to: &mut T|draw.draw(todo!()))
}
pub const fn xy_push <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}
pub const fn xy_pull <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}
pub const fn x_push <T: Screen> (x: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}
pub const fn x_pull <T: Screen> (x: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}
pub const fn y_push <T: Screen> (x: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}
pub const fn y_pull <T: Screen> (x: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
a
}