move everything out of layout
This commit is contained in:
464
core/src/orientation/pos.rs
Normal file
464
core/src/orientation/pos.rs
Normal file
@@ -0,0 +1,464 @@
|
||||
use std::{fmt::Display, hash::Hash, marker::Destruct};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
UiNum,
|
||||
util::{LerpUtil, impl_op},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
||||
pub struct UiVec2 {
|
||||
pub x: UiScalar,
|
||||
pub y: UiScalar,
|
||||
}
|
||||
|
||||
impl UiVec2 {
|
||||
pub const ZERO: Self = Self {
|
||||
x: UiScalar::ZERO,
|
||||
y: UiScalar::ZERO,
|
||||
};
|
||||
|
||||
pub const fn new(x: UiScalar, y: UiScalar) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub const fn abs(abs: impl const Into<Vec2>) -> Self {
|
||||
let abs = abs.into();
|
||||
Self {
|
||||
x: UiScalar::abs(abs.x),
|
||||
y: UiScalar::abs(abs.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn rel(rel: impl const Into<Vec2>) -> Self {
|
||||
let rel = rel.into();
|
||||
Self {
|
||||
x: UiScalar::rel(rel.x),
|
||||
y: UiScalar::rel(rel.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn shift(&mut self, offset: impl const Into<UiVec2>) {
|
||||
let offset = offset.into();
|
||||
*self += offset;
|
||||
}
|
||||
|
||||
pub const fn offset(mut self, offset: impl const Into<UiVec2>) -> Self {
|
||||
self.shift(offset);
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn within(&self, region: &UiRegion) -> UiVec2 {
|
||||
UiVec2 {
|
||||
x: self.x.within(®ion.x),
|
||||
y: self.y.within(®ion.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn outside(&self, region: &UiRegion) -> UiVec2 {
|
||||
UiVec2 {
|
||||
x: self.x.outside(®ion.x),
|
||||
y: self.y.outside(®ion.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn axis_mut(&mut self, axis: Axis) -> &mut UiScalar {
|
||||
match axis {
|
||||
Axis::X => &mut self.x,
|
||||
Axis::Y => &mut self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn axis(&self, axis: Axis) -> UiScalar {
|
||||
match axis {
|
||||
Axis::X => self.x,
|
||||
Axis::Y => self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_abs(&self, rel: Vec2) -> Vec2 {
|
||||
Vec2 {
|
||||
x: self.x.to_abs(rel.x),
|
||||
y: self.y.to_abs(rel.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const FULL_SIZE: Self = Self::rel(Vec2::ONE);
|
||||
|
||||
pub const fn from_axis(axis: Axis, aligned: UiScalar, ortho: UiScalar) -> Self {
|
||||
match axis {
|
||||
Axis::X => Self {
|
||||
x: aligned,
|
||||
y: ortho,
|
||||
},
|
||||
Axis::Y => Self {
|
||||
x: ortho,
|
||||
y: aligned,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_abs(&self) -> Vec2 {
|
||||
(self.x.abs, self.y.abs).into()
|
||||
}
|
||||
|
||||
pub fn get_rel(&self) -> Vec2 {
|
||||
(self.x.rel, self.y.rel).into()
|
||||
}
|
||||
|
||||
pub fn abs_mut(&mut self) -> Vec2View<'_> {
|
||||
Vec2View {
|
||||
x: &mut self.x.abs,
|
||||
y: &mut self.y.abs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UiVec2 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "rel{};abs{}", self.get_rel(), self.get_abs())
|
||||
}
|
||||
}
|
||||
|
||||
impl_op!(UiVec2 Add add; x y);
|
||||
impl_op!(UiVec2 Sub sub; x y);
|
||||
|
||||
impl const From<Vec2> for UiVec2 {
|
||||
fn from(abs: Vec2) -> Self {
|
||||
Self::abs(abs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: const UiNum, U: const UiNum> const From<(T, U)> for UiVec2
|
||||
where
|
||||
(T, U): const Destruct,
|
||||
{
|
||||
fn from(abs: (T, U)) -> Self {
|
||||
Self::abs(abs)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, Default, bytemuck::Zeroable)]
|
||||
pub struct UiScalar {
|
||||
pub rel: f32,
|
||||
pub abs: f32,
|
||||
}
|
||||
|
||||
impl Eq for UiScalar {}
|
||||
impl Hash for UiScalar {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
state.write_u32(self.rel.to_bits());
|
||||
state.write_u32(self.abs.to_bits());
|
||||
}
|
||||
}
|
||||
|
||||
impl_op!(UiScalar Add add; rel abs);
|
||||
impl_op!(UiScalar Sub sub; rel abs);
|
||||
|
||||
impl UiScalar {
|
||||
pub const ZERO: Self = Self { rel: 0.0, abs: 0.0 };
|
||||
pub const FULL: Self = Self { rel: 1.0, abs: 0.0 };
|
||||
|
||||
pub const fn new(rel: f32, abs: f32) -> Self {
|
||||
Self { rel, abs }
|
||||
}
|
||||
|
||||
pub const fn rel(rel: f32) -> Self {
|
||||
Self { rel, abs: 0.0 }
|
||||
}
|
||||
|
||||
pub const fn abs(abs: f32) -> Self {
|
||||
Self { rel: 0.0, abs }
|
||||
}
|
||||
|
||||
pub const fn rel_min() -> Self {
|
||||
Self::new(0.0, 0.0)
|
||||
}
|
||||
|
||||
pub const fn rel_max() -> Self {
|
||||
Self::new(1.0, 0.0)
|
||||
}
|
||||
|
||||
pub const fn max(&self, other: Self) -> Self {
|
||||
Self {
|
||||
rel: self.rel.max(other.rel),
|
||||
abs: self.abs.max(other.abs),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn min(&self, other: Self) -> Self {
|
||||
Self {
|
||||
rel: self.rel.min(other.rel),
|
||||
abs: self.abs.min(other.abs),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn offset(mut self, amt: f32) -> Self {
|
||||
self.abs += amt;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn within(&self, span: &UiSpan) -> Self {
|
||||
let anchor = self.rel.lerp(span.start.rel, span.end.rel);
|
||||
let offset = self.abs + self.rel.lerp(span.start.abs, span.end.abs);
|
||||
Self {
|
||||
rel: anchor,
|
||||
abs: offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn outside(&self, span: &UiSpan) -> Self {
|
||||
let rel = self.rel.lerp_inv(span.start.rel, span.end.rel);
|
||||
let abs = self.abs - rel.lerp(span.start.abs, span.end.abs);
|
||||
Self { rel, abs }
|
||||
}
|
||||
|
||||
pub fn within_len(&self, len: UiScalar) -> Self {
|
||||
self.within(&UiSpan {
|
||||
start: UiScalar::ZERO,
|
||||
end: len,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select_len(&self, len: UiScalar) -> Self {
|
||||
len.within_len(*self)
|
||||
}
|
||||
|
||||
pub const fn flip(&mut self) {
|
||||
self.rel = 1.0 - self.rel;
|
||||
self.abs = -self.abs;
|
||||
}
|
||||
|
||||
pub const fn to(&self, end: Self) -> UiSpan {
|
||||
UiSpan { start: *self, end }
|
||||
}
|
||||
|
||||
pub const fn to_abs(&self, rel: f32) -> f32 {
|
||||
self.rel * rel + self.abs
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct UiSpan {
|
||||
pub start: UiScalar,
|
||||
pub end: UiScalar,
|
||||
}
|
||||
|
||||
impl UiSpan {
|
||||
pub const FULL: Self = Self {
|
||||
start: UiScalar::ZERO,
|
||||
end: UiScalar::FULL,
|
||||
};
|
||||
|
||||
pub const fn rel(rel: f32) -> Self {
|
||||
Self {
|
||||
start: UiScalar::rel(rel),
|
||||
end: UiScalar::rel(rel),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn new(start: UiScalar, end: UiScalar) -> Self {
|
||||
Self { start, end }
|
||||
}
|
||||
|
||||
pub const fn flip(&mut self) {
|
||||
self.start.flip();
|
||||
self.end.flip();
|
||||
std::mem::swap(&mut self.start.rel, &mut self.end.rel);
|
||||
std::mem::swap(&mut self.start.abs, &mut self.end.abs);
|
||||
}
|
||||
|
||||
pub const fn shift(&mut self, offset: UiScalar) {
|
||||
self.start += offset;
|
||||
self.end += offset;
|
||||
}
|
||||
|
||||
pub const fn within(&self, parent: &Self) -> Self {
|
||||
Self {
|
||||
start: self.start.within(parent),
|
||||
end: self.end.within(parent),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn outside(&self, parent: &Self) -> Self {
|
||||
Self {
|
||||
start: self.start.outside(parent),
|
||||
end: self.end.outside(parent),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn len(&self) -> UiScalar {
|
||||
self.end - self.start
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct UiRegion {
|
||||
pub x: UiSpan,
|
||||
pub y: UiSpan,
|
||||
}
|
||||
|
||||
impl UiRegion {
|
||||
pub const FULL: Self = Self {
|
||||
x: UiSpan::FULL,
|
||||
y: UiSpan::FULL,
|
||||
};
|
||||
|
||||
pub const fn new(x: UiSpan, y: UiSpan) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub const fn rel(rel: Vec2) -> Self {
|
||||
Self {
|
||||
x: UiSpan::rel(rel.x),
|
||||
y: UiSpan::rel(rel.y),
|
||||
}
|
||||
}
|
||||
pub const fn within(&self, parent: &Self) -> Self {
|
||||
Self {
|
||||
x: self.x.within(&parent.x),
|
||||
y: self.y.within(&parent.y),
|
||||
}
|
||||
}
|
||||
pub const fn outside(&self, parent: &Self) -> Self {
|
||||
Self {
|
||||
x: self.x.outside(&parent.x),
|
||||
y: self.y.outside(&parent.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis(&mut self, axis: Axis) -> &UiSpan {
|
||||
match axis {
|
||||
Axis::X => &self.x,
|
||||
Axis::Y => &self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis_mut(&mut self, axis: Axis) -> &mut UiSpan {
|
||||
match axis {
|
||||
Axis::X => &mut self.x,
|
||||
Axis::Y => &mut self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn flip(&mut self, axis: Axis) {
|
||||
match axis {
|
||||
Axis::X => self.x.flip(),
|
||||
Axis::Y => self.y.flip(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shift(&mut self, offset: impl Into<UiVec2>) {
|
||||
let offset = offset.into();
|
||||
self.x.shift(offset.x);
|
||||
self.y.shift(offset.y);
|
||||
}
|
||||
|
||||
pub fn offset(mut self, offset: impl Into<UiVec2>) -> Self {
|
||||
self.shift(offset);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_px(&self, size: Vec2) -> PixelRegion {
|
||||
PixelRegion {
|
||||
top_left: self.top_left().get_rel() * size + self.top_left().get_abs(),
|
||||
bot_right: self.bot_right().get_rel() * size + self.bot_right().get_abs(),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn center(&self) -> UiVec2 {
|
||||
Align::CENTER.pos().within(self)
|
||||
}
|
||||
|
||||
pub const fn size(&self) -> UiVec2 {
|
||||
UiVec2 {
|
||||
x: self.x.len(),
|
||||
y: self.y.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn top_left(&self) -> UiVec2 {
|
||||
UiVec2 {
|
||||
x: self.x.start,
|
||||
y: self.y.start,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn bot_right(&self) -> UiVec2 {
|
||||
UiVec2 {
|
||||
x: self.x.end,
|
||||
y: self.y.end,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn from_axis(axis: Axis, aligned: UiSpan, ortho: UiSpan) -> Self {
|
||||
Self {
|
||||
x: match axis {
|
||||
Axis::X => aligned,
|
||||
Axis::Y => ortho,
|
||||
},
|
||||
y: match axis {
|
||||
Axis::X => ortho,
|
||||
Axis::Y => aligned,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UiRegion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} -> {} (size: {})",
|
||||
self.top_left(),
|
||||
self.bot_right(),
|
||||
self.size()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PixelRegion {
|
||||
pub top_left: Vec2,
|
||||
pub bot_right: Vec2,
|
||||
}
|
||||
|
||||
impl PixelRegion {
|
||||
pub fn contains(&self, pos: Vec2) -> bool {
|
||||
pos.x >= self.top_left.x
|
||||
&& pos.x <= self.bot_right.x
|
||||
&& pos.y >= self.top_left.y
|
||||
&& pos.y <= self.bot_right.y
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vec2 {
|
||||
self.bot_right - self.top_left
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PixelRegion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} -> {}", self.top_left, self.bot_right)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Vec2View<'a> {
|
||||
pub x: &'a mut f32,
|
||||
pub y: &'a mut f32,
|
||||
}
|
||||
|
||||
impl Vec2View<'_> {
|
||||
pub fn set(&mut self, other: Vec2) {
|
||||
*self.x = other.x;
|
||||
*self.y = other.y;
|
||||
}
|
||||
|
||||
pub fn add(&mut self, other: Vec2) {
|
||||
*self.x += other.x;
|
||||
*self.y += other.y;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user