use crate::Vec2;
use crate::XY;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Orientation {
Horizontal,
Vertical,
}
impl Orientation {
pub fn pair() -> XY<Orientation> {
XY::new(Orientation::Horizontal, Orientation::Vertical)
}
pub fn get<T: Clone>(self, v: &XY<T>) -> T {
v.get(self).clone()
}
#[must_use]
pub fn swap(self) -> Self {
match self {
Orientation::Horizontal => Orientation::Vertical,
Orientation::Vertical => Orientation::Horizontal,
}
}
pub fn get_ref<T>(self, v: &mut XY<T>) -> &mut T {
match self {
Orientation::Horizontal => &mut v.x,
Orientation::Vertical => &mut v.y,
}
}
pub fn stack<T: Iterator<Item = Vec2>>(self, iter: T) -> Vec2 {
match self {
Orientation::Horizontal => {
iter.fold(Vec2::zero(), |a, b| a.stack_horizontal(&b))
}
Orientation::Vertical => {
iter.fold(Vec2::zero(), |a, b| a.stack_vertical(&b))
}
}
}
pub fn make_vec(self, main_axis: usize, second_axis: usize) -> Vec2 {
let mut result = Vec2::zero();
*self.get_ref(&mut result) = main_axis;
*self.swap().get_ref(&mut result) = second_axis;
result
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Direction {
Abs(Absolute),
Rel(Relative),
}
impl Direction {
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
match self {
Direction::Abs(abs) => abs.relative(orientation),
Direction::Rel(rel) => Some(rel),
}
}
pub fn absolute(self, orientation: Orientation) -> Absolute {
match self {
Direction::Abs(abs) => abs,
Direction::Rel(rel) => rel.absolute(orientation),
}
}
#[must_use]
pub fn opposite(self) -> Self {
match self {
Direction::Abs(abs) => Direction::Abs(abs.opposite()),
Direction::Rel(rel) => Direction::Rel(rel.swap()),
}
}
pub fn back() -> Self {
Direction::Rel(Relative::Back)
}
pub fn front() -> Self {
Direction::Rel(Relative::Front)
}
pub fn left() -> Self {
Direction::Abs(Absolute::Left)
}
pub fn right() -> Self {
Direction::Abs(Absolute::Right)
}
pub fn up() -> Self {
Direction::Abs(Absolute::Up)
}
pub fn down() -> Self {
Direction::Abs(Absolute::Down)
}
pub fn none() -> Self {
Direction::Abs(Absolute::None)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Relative {
Front,
Back,
}
impl Relative {
pub fn absolute(self, orientation: Orientation) -> Absolute {
match (orientation, self) {
(Orientation::Horizontal, Relative::Front) => Absolute::Left,
(Orientation::Horizontal, Relative::Back) => Absolute::Right,
(Orientation::Vertical, Relative::Front) => Absolute::Up,
(Orientation::Vertical, Relative::Back) => Absolute::Down,
}
}
pub fn pick<T>(self, (front, back): (T, T)) -> T {
match self {
Relative::Front => front,
Relative::Back => back,
}
}
#[must_use]
pub fn swap(self) -> Self {
match self {
Relative::Front => Relative::Back,
Relative::Back => Relative::Front,
}
}
pub fn a_to_b(a: usize, b: usize) -> Option<Self> {
use std::cmp::Ordering;
match a.cmp(&b) {
Ordering::Less => Some(Relative::Front),
Ordering::Greater => Some(Relative::Back),
Ordering::Equal => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Absolute {
Left,
Up,
Right,
Down,
None,
}
impl Absolute {
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
match (orientation, self) {
(Orientation::Horizontal, Absolute::Left)
| (Orientation::Vertical, Absolute::Up) => Some(Relative::Front),
(Orientation::Horizontal, Absolute::Right)
| (Orientation::Vertical, Absolute::Down) => Some(Relative::Back),
_ => None,
}
}
#[must_use]
pub fn opposite(self) -> Self {
match self {
Absolute::Left => Absolute::Right,
Absolute::Right => Absolute::Left,
Absolute::Up => Absolute::Down,
Absolute::Down => Absolute::Up,
Absolute::None => Absolute::None,
}
}
pub fn split(self) -> (Orientation, Relative) {
match self {
Absolute::Left => (Orientation::Horizontal, Relative::Front),
Absolute::Right => (Orientation::Horizontal, Relative::Back),
Absolute::Up => (Orientation::Vertical, Relative::Front),
Absolute::Down => (Orientation::Vertical, Relative::Back),
Absolute::None => panic!("None direction not supported here"),
}
}
}