initial text impl
This commit is contained in:
235
src/layout/pos.rs
Normal file
235
src/layout/pos.rs
Normal file
@@ -0,0 +1,235 @@
|
||||
use crate::{
|
||||
layout::{Axis, Corner, Vec2, vec2},
|
||||
util::{F32Util, impl_op},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
||||
pub struct UiPos {
|
||||
pub anchor: Vec2,
|
||||
pub offset: Vec2,
|
||||
}
|
||||
|
||||
impl UiPos {
|
||||
/// expands this position into a sized region centered at self
|
||||
pub fn expand(&self, size: impl Into<Vec2>) -> UiRegion {
|
||||
let size = size.into();
|
||||
UiRegion {
|
||||
top_left: self.shifted(-size / 2.0),
|
||||
bot_right: self.shifted(size / 2.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn center() -> Self {
|
||||
Self::anchor(vec2(0.5, 0.5))
|
||||
}
|
||||
|
||||
pub const fn anchor(anchor: Vec2) -> Self {
|
||||
Self {
|
||||
anchor,
|
||||
offset: Vec2::ZERO,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn offset(offset: Vec2) -> Self {
|
||||
Self {
|
||||
anchor: Vec2::ZERO,
|
||||
offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn corner(corner: Corner) -> Self {
|
||||
Self::anchor(corner.anchor())
|
||||
}
|
||||
|
||||
pub const fn shift(&mut self, offset: Vec2) {
|
||||
self.offset += offset;
|
||||
}
|
||||
|
||||
pub const fn shifted(mut self, offset: Vec2) -> Self {
|
||||
self.shift(offset);
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn within(&self, region: &UiRegion) -> UiPos {
|
||||
let anchor = self
|
||||
.anchor
|
||||
.lerp(region.top_left.anchor, region.bot_right.anchor);
|
||||
let offset = self.offset
|
||||
+ self
|
||||
.anchor
|
||||
.lerp(region.top_left.offset, region.bot_right.offset);
|
||||
UiPos { anchor, offset }
|
||||
}
|
||||
|
||||
pub fn axis_mut(&mut self, axis: Axis) -> UIScalarView<'_> {
|
||||
match axis {
|
||||
Axis::X => UIScalarView {
|
||||
anchor: &mut self.anchor.x,
|
||||
offset: &mut self.offset.x,
|
||||
},
|
||||
Axis::Y => UIScalarView {
|
||||
anchor: &mut self.anchor.y,
|
||||
offset: &mut self.offset.y,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flip(&mut self) {
|
||||
self.anchor = 1.0 - self.anchor;
|
||||
self.offset = -self.offset;
|
||||
}
|
||||
|
||||
pub fn flipped(mut self) -> Self {
|
||||
self.flip();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_size(&self, size: Vec2) -> Vec2 {
|
||||
self.anchor * size + self.offset
|
||||
}
|
||||
|
||||
/// snaps this to a specific screen size to get actual pixel coordinates
|
||||
pub fn snap(&self, size: Vec2) -> Vec2 {
|
||||
self.to_size(size).round()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct UIScalar {
|
||||
pub anchor: f32,
|
||||
pub offset: f32,
|
||||
}
|
||||
|
||||
impl_op!(UIScalar Add add; anchor offset);
|
||||
impl_op!(UIScalar Sub sub; anchor offset);
|
||||
|
||||
impl UIScalar {
|
||||
pub fn new(anchor: f32, offset: f32) -> Self {
|
||||
Self { anchor, offset }
|
||||
}
|
||||
pub fn min() -> Self {
|
||||
Self::new(0.0, 0.0)
|
||||
}
|
||||
|
||||
pub fn max() -> Self {
|
||||
Self::new(1.0, 0.0)
|
||||
}
|
||||
|
||||
pub fn from_anchor(anchor: f32) -> Self {
|
||||
Self::new(anchor, 0.0)
|
||||
}
|
||||
|
||||
pub fn offset(mut self, amt: f32) -> Self {
|
||||
self.offset += amt;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn within(&self, start: UIScalar, end: UIScalar) -> Self {
|
||||
let anchor = self.anchor.lerp(start.anchor, end.anchor);
|
||||
let offset = self.offset + self.anchor.lerp(start.offset, end.offset);
|
||||
Self { anchor, offset }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct UiRegion {
|
||||
pub top_left: UiPos,
|
||||
pub bot_right: UiPos,
|
||||
}
|
||||
|
||||
impl UiRegion {
|
||||
pub const fn full() -> Self {
|
||||
Self {
|
||||
top_left: UiPos::corner(Corner::TopLeft),
|
||||
bot_right: UiPos::corner(Corner::BotRight),
|
||||
}
|
||||
}
|
||||
pub fn anchor(anchor: Vec2) -> Self {
|
||||
Self {
|
||||
top_left: UiPos::anchor(anchor),
|
||||
bot_right: UiPos::anchor(anchor),
|
||||
}
|
||||
}
|
||||
pub fn within(&self, parent: &Self) -> Self {
|
||||
Self {
|
||||
top_left: self.top_left.within(parent),
|
||||
bot_right: self.bot_right.within(parent),
|
||||
}
|
||||
}
|
||||
pub fn select(&mut self, inner: &Self) {
|
||||
*self = inner.within(self);
|
||||
}
|
||||
pub fn axis_mut(&mut self, axis: Axis) -> UIRegionAxisView<'_> {
|
||||
UIRegionAxisView {
|
||||
top_left: self.top_left.axis_mut(axis),
|
||||
bot_right: self.bot_right.axis_mut(axis),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flip(&mut self) {
|
||||
self.top_left.flip();
|
||||
self.bot_right.flip();
|
||||
std::mem::swap(&mut self.top_left, &mut self.bot_right);
|
||||
}
|
||||
|
||||
pub fn shift(&mut self, offset: impl Into<Vec2>) {
|
||||
let offset = offset.into();
|
||||
self.top_left.shift(offset);
|
||||
self.bot_right.shift(offset);
|
||||
}
|
||||
|
||||
pub fn shifted(mut self, offset: impl Into<Vec2>) -> Self {
|
||||
self.shift(offset);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_screen(&self, size: Vec2) -> ScreenRect {
|
||||
ScreenRect {
|
||||
top_left: self.top_left.anchor * size + self.top_left.offset,
|
||||
bot_right: self.bot_right.anchor * size + self.bot_right.offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn center(&self) -> UiPos {
|
||||
UiPos::center().within(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ScreenRect {
|
||||
top_left: Vec2,
|
||||
bot_right: Vec2,
|
||||
}
|
||||
impl ScreenRect {
|
||||
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 struct UIRegionAxisView<'a> {
|
||||
pub top_left: UIScalarView<'a>,
|
||||
pub bot_right: UIScalarView<'a>,
|
||||
}
|
||||
|
||||
pub struct UIScalarView<'a> {
|
||||
pub anchor: &'a mut f32,
|
||||
pub offset: &'a mut f32,
|
||||
}
|
||||
|
||||
impl UIScalarView<'_> {
|
||||
pub fn set(&mut self, scalar: UIScalar) {
|
||||
*self.anchor = scalar.anchor;
|
||||
*self.offset = scalar.offset;
|
||||
}
|
||||
pub fn get(self) -> UIScalar {
|
||||
UIScalar {
|
||||
anchor: *self.anchor,
|
||||
offset: *self.offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user