use crate::layout::vec2; use super::*; #[derive(Clone, Copy, PartialEq, Eq)] pub struct Align { pub x: Option, pub y: Option, } impl Align { pub const TOP_LEFT: RegionAlign = RegionAlign::TOP_LEFT; pub const TOP_CENTER: RegionAlign = RegionAlign::TOP_CENTER; pub const TOP_RIGHT: RegionAlign = RegionAlign::TOP_RIGHT; pub const CENTER_LEFT: RegionAlign = RegionAlign::CENTER_LEFT; pub const CENTER: RegionAlign = RegionAlign::CENTER; pub const CENTER_RIGHT: RegionAlign = RegionAlign::CENTER_RIGHT; pub const BOT_LEFT: RegionAlign = RegionAlign::BOT_LEFT; pub const BOT_CENTER: RegionAlign = RegionAlign::BOT_CENTER; pub const BOT_RIGHT: RegionAlign = RegionAlign::BOT_RIGHT; pub const LEFT: CardinalAlign = CardinalAlign::LEFT; pub const H_CENTER: CardinalAlign = CardinalAlign::H_CENTER; pub const RIGHT: CardinalAlign = CardinalAlign::RIGHT; pub const TOP: CardinalAlign = CardinalAlign::TOP; pub const V_CENTER: CardinalAlign = CardinalAlign::V_CENTER; pub const BOT: CardinalAlign = CardinalAlign::BOT; pub fn tuple(&self) -> (Option, Option) { (self.x, self.y) } } #[derive(Clone, Copy, PartialEq, Eq)] pub enum AxisAlign { Neg, Center, Pos, } impl AxisAlign { pub const fn rel(&self) -> f32 { match self { Self::Neg => 0.0, Self::Center => 0.5, Self::Pos => 1.0, } } } pub struct CardinalAlign { axis: Axis, align: AxisAlign, } impl CardinalAlign { pub const LEFT: Self = Self::new(Axis::X, AxisAlign::Neg); pub const H_CENTER: Self = Self::new(Axis::X, AxisAlign::Center); pub const RIGHT: Self = Self::new(Axis::X, AxisAlign::Pos); pub const TOP: Self = Self::new(Axis::Y, AxisAlign::Neg); pub const V_CENTER: Self = Self::new(Axis::Y, AxisAlign::Center); pub const BOT: Self = Self::new(Axis::Y, AxisAlign::Pos); pub const fn new(axis: Axis, align: AxisAlign) -> Self { Self { axis, align } } } #[derive(Clone, Copy, PartialEq, Eq)] pub struct RegionAlign { pub x: AxisAlign, pub y: AxisAlign, } impl RegionAlign { pub const TOP_LEFT: Self = Self::new(AxisAlign::Neg, AxisAlign::Neg); pub const TOP_CENTER: Self = Self::new(AxisAlign::Center, AxisAlign::Neg); pub const TOP_RIGHT: Self = Self::new(AxisAlign::Pos, AxisAlign::Neg); pub const CENTER_LEFT: Self = Self::new(AxisAlign::Neg, AxisAlign::Center); pub const CENTER: Self = Self::new(AxisAlign::Center, AxisAlign::Center); pub const CENTER_RIGHT: Self = Self::new(AxisAlign::Pos, AxisAlign::Center); pub const BOT_LEFT: Self = Self::new(AxisAlign::Neg, AxisAlign::Pos); pub const BOT_CENTER: Self = Self::new(AxisAlign::Center, AxisAlign::Pos); pub const BOT_RIGHT: Self = Self::new(AxisAlign::Pos, AxisAlign::Pos); pub const fn new(x: AxisAlign, y: AxisAlign) -> Self { Self { x, y } } pub const fn rel(&self) -> Vec2 { vec2(self.x.rel(), self.y.rel()) } } impl UiVec2 { pub fn partial_align(&self, align: Align) -> UiRegion { UiRegion { x: if let Some(align) = align.x { self.x.align(align) } else { UiSpan::FULL }, y: if let Some(align) = align.y { self.y.align(align) } else { UiSpan::FULL }, } } pub fn align(&self, align: RegionAlign) -> UiRegion { UiRegion { x: self.x.align(align.x), y: self.y.align(align.y), } } } impl Vec2 { pub fn partial_align(&self, align: Align) -> UiRegion { let s = UiVec2::from(*self); UiRegion { x: if let Some(align) = align.x { s.x.align(align) } else { UiSpan::FULL }, y: if let Some(align) = align.y { s.y.align(align) } else { UiSpan::FULL }, } } pub fn align(&self, align: RegionAlign) -> UiRegion { let s = UiVec2::from(*self); UiRegion { x: s.x.align(align.x), y: s.y.align(align.y), } } } impl UiScalar { pub const fn align(&self, align: AxisAlign) -> UiSpan { let rel = align.rel(); let mut start = UiScalar::rel(rel); start.abs -= self.abs * rel; start.rel -= self.rel * rel; let mut end = UiScalar::rel(rel); end.abs += self.abs * (1.0 - rel); end.rel += self.rel * (1.0 - rel); UiSpan { start, end } } } impl From for Align { fn from(region: RegionAlign) -> Self { Self { x: Some(region.x), y: Some(region.y), } } } impl From for RegionAlign { fn from(align: Align) -> Self { Self { x: align.x.unwrap_or(AxisAlign::Center), y: align.y.unwrap_or(AxisAlign::Center), } } } impl From for RegionAlign { fn from(align: CardinalAlign) -> Self { Align::from(align).into() } } impl From for Align { fn from(cardinal: CardinalAlign) -> Self { let align = Some(cardinal.align); match cardinal.axis { Axis::X => Self { x: align, y: None }, Axis::Y => Self { x: None, y: align }, } } } impl const From for UiVec2 { fn from(align: RegionAlign) -> Self { Self::rel(align.rel()) } } impl RegionAlign { pub const fn pos(self) -> UiVec2 { UiVec2::from(self) } }