pierro 0.1.0

An immediate mode UI library for Rust
Documentation

use core::f32;
use std::fmt::Display;

use crate::Animatable;

use super::{vec2, Axis, Margin, Range, Vec2};

#[derive(Clone, Copy)]
pub struct Rect {
    min: Vec2,
    max: Vec2
}

impl Rect {

    pub const fn min_max(min: Vec2, max: Vec2) -> Self {
        Self {
            min,
            max
        }
    }

    pub fn min_size(min: Vec2, size: Vec2) -> Self {
        Self {
            min,
            max: min + size
        }
    }

    pub const fn from_ranges(x_range: Range, y_range: Range) -> Self {
        Self {
            min: vec2(x_range.min, y_range.min),
            max: vec2(x_range.max, y_range.max)
        }
    }

    pub const fn to_infinity(from: Vec2) -> Self {
        Self {
            min: from,
            max: Vec2::INFINITY 
        }
    }

    pub const ZERO: Self = Self::min_max(Vec2::ZERO, Vec2::ZERO);

    pub const fn tl(&self) -> Vec2 {
        self.min
    }

    pub const fn tr(&self) -> Vec2 {
        vec2(self.max.x, self.min.y)
    }

    pub const fn bl(&self) -> Vec2 {
        vec2(self.min.x, self.max.y)
    }

    pub const fn br(&self) -> Vec2 {
        self.max
    }
    
    pub const fn left(&self) -> f32 {
        self.min.x
    }

    pub const fn right(&self) -> f32 {
        self.max.x
    }

    pub const fn top(&self) -> f32 {
        self.min.y
    }

    pub const fn bottom(&self) -> f32 {
        self.max.y
    }

    pub fn center(&self) -> Vec2 {
        (self.min + self.max) * 0.5
    }

    pub fn size(&self) -> Vec2 {
        self.max - self.min
    }

    pub fn width(&self) -> f32 {
        self.size().x
    }
    
    pub fn height(&self) -> f32 {
        self.size().y
    }

    pub const fn x_range(&self) -> Range {
        Range::new(self.min.x, self.max.x)
    }

    pub fn set_x_range(&mut self, range: Range) {
        self.min.x = range.min;
        self.max.x = range.max;
    } 

    pub const fn y_range(&self) -> Range {
        Range::new(self.min.y, self.max.y)
    }

    pub fn set_y_range(&mut self, range: Range) {
        self.min.y = range.min;
        self.max.y = range.max;
    } 

    pub const fn axis_range(&self, axis: Axis) -> Range {
        Range::new(self.min.on_axis(axis), self.max.on_axis(axis))
    }

    pub fn set_axis_range(&mut self, axis: Axis, range: Range) {
        *self.min.on_axis_mut(axis) = range.min; 
        *self.max.on_axis_mut(axis) = range.max; 
    }

    pub fn contains(&self, pt: Vec2) -> bool {
        self.x_range().contains(pt.x) && self.y_range().contains(pt.y)
    }

    pub fn intersect(&self, other: Rect) -> Rect {
        Self::from_ranges(
            self.x_range().intersect(other.x_range()),
            self.y_range().intersect(other.y_range()) 
        )
    }

    pub fn shift(&self, offset: Vec2) -> Rect {
        Self::min_max(self.min + offset, self.max + offset)
    }

    pub fn grow(&self, margin: Margin) -> Rect {
        Self::min_max(self.min - margin.min, self.max + margin.max)
    }

    pub fn map(&self, from: Rect, to: Rect) -> Self {
        Self::min_max(
            self.min.map(from, to),
           self.max.map(from, to) 
        )
    }

    pub fn area(&self) -> f32 {
        self.width() * self.height()
    }

    pub fn left_frac(&self, frac: f32) -> Rect {
        Self::min_max(self.tl(), self.bl().lerp(self.br(), frac))
    }
    
    pub fn right_frac(&self, frac: f32) -> Rect {
        Self::min_max(self.tl().lerp(self.tr(), frac), self.br())
    }

    pub fn top_frac(&self, frac: f32) -> Rect {
        Self::min_max(self.tl(), self.tr().lerp(self.br(), frac))
    }

    pub fn bottom_frac(&self, frac: f32) -> Rect {
        Self::min_max(self.bl().lerp(self.tl(), frac), self.br())
    }

    pub fn left_half(&self) -> Rect {
        self.left_frac(0.5)
    }

    pub fn right_half(&self) -> Rect {
        self.right_frac(0.5)
    }

    pub fn top_half(&self) -> Rect {
        self.top_frac(0.5)
    }

    pub fn bottom_half(&self) -> Rect {
        self.bottom_frac(0.5)
    }

}

impl Display for Rect {

    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.tl().fmt(f)?;
        f.write_str(" -> ")?;
        self.br().fmt(f)
    }

}