use crate::*;
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub struct Rectangle2D {
pub pos : Vec2,
pub size: Vec2,
}
impl Rectangle2D {
pub fn lerp(self, rhs: Self, lerp: f32) -> Self {
Rectangle2D {
pos: self.pos.lerp(rhs.pos, lerp),
size: self.size.lerp(rhs.size, lerp),
}
}
}
impl Rectangle2D {
pub const EMPTY: Rectangle2D = Rectangle2D { pos : Vec2::ZERO, size: Vec2::ZERO };
pub const fn new() -> Self {
Rectangle2D::EMPTY
}
pub fn with_pos(mut self, pos: impl Into<Vec2>) -> Self {
self.pos = pos.into();
self
}
pub fn with_x(mut self, width: f32) -> Self {
self.pos.x = width;
self
}
pub fn with_y(mut self, height: f32) -> Self {
self.pos.y = height;
self
}
pub fn with_size(mut self, size: impl Into<Vec2>) -> Self {
self.size = size.into();
self
}
pub fn with_width(mut self, width: f32) -> Self {
self.size.x = width;
self
}
pub fn with_height(mut self, height: f32) -> Self {
self.size.y = height;
self
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub struct Align (pub f32);
impl Align {
pub const START: Align = Align(-1.0);
pub const LEFT: Align = Align(-1.0);
pub const CENTER: Align = Align(0.0);
pub const MIDDLE: Align = Align(0.0);
pub const END: Align = Align(1.0);
pub const RIGHT: Align = Align(1.0);
}
impl From<f32> for Align {
fn from(val: f32) -> Self {
Align(val)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub enum Scaling {
HorFill,
VerFill,
#[default] Fit,
Fill,
}
#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
pub enum UiLayoutType {
Boundary(UiLayoutTypeBoundary),
Window(UiLayoutTypeWindow),
Solid(UiLayoutTypeSolid),
}
impl UiLayoutType {
pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
match self {
UiLayoutType::Boundary(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
UiLayoutType::Window(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
UiLayoutType::Solid(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
}
}
}
impl From<UiLayoutTypeBoundary> for UiLayoutType {
fn from(value: UiLayoutTypeBoundary) -> Self {
UiLayoutType::Boundary(value)
}
}
impl From<UiLayoutTypeWindow> for UiLayoutType {
fn from(value: UiLayoutTypeWindow) -> Self {
UiLayoutType::Window(value)
}
}
impl From<UiLayoutTypeSolid> for UiLayoutType {
fn from(value: UiLayoutTypeSolid) -> Self {
UiLayoutType::Solid(value)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub struct UiLayoutTypeBoundary {
pub pos1: UiValue<Vec2>,
pub pos2: UiValue<Vec2>,
}
impl UiLayoutTypeBoundary {
pub const fn new() -> Self {
Self {
pos1: UiValue::new(),
pos2: UiValue::new(),
}
}
pub fn pos1(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
self.pos1 = pos.into();
self
}
pub fn pos2(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
self.pos2 = pos.into();
self
}
pub fn x1(mut self, x: impl Into<UiValue<f32>>) -> Self {
self.pos1.set_x(x);
self
}
pub fn y1(mut self, y: impl Into<UiValue<f32>>) -> Self {
self.pos1.set_y(y);
self
}
pub fn x2(mut self, x: impl Into<UiValue<f32>>) -> Self {
self.pos2.set_x(x);
self
}
pub fn y2(mut self, y: impl Into<UiValue<f32>>) -> Self {
self.pos2.set_y(y);
self
}
pub fn set_pos1(&mut self, pos: impl Into<UiValue<Vec2>>) {
self.pos1 = pos.into();
}
pub fn set_pos2(&mut self, pos: impl Into<UiValue<Vec2>>) {
self.pos2 = pos.into();
}
pub fn set_x1(&mut self, x: impl Into<UiValue<f32>>) {
self.pos1.set_x(x);
}
pub fn set_y1(&mut self, y: impl Into<UiValue<f32>>) {
self.pos1.set_y(y);
}
pub fn set_x2(&mut self, x: impl Into<UiValue<f32>>) {
self.pos2.set_x(x);
}
pub fn set_y2(&mut self, y: impl Into<UiValue<f32>>) {
self.pos2.set_y(y);
}
pub fn pack(self) -> UiLayout {
UiLayout::from(self)
}
pub fn wrap(self) -> UiLayoutType {
UiLayoutType::from(self)
}
pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
let pos1 = self.pos1.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
let pos2 = self.pos2.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
let size = pos2 - pos1;
Rectangle2D {
pos: -parent.size / 2.0 + pos1 + size/2.0,
size,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub struct UiLayoutTypeWindow {
pub pos : UiValue<Vec2>,
pub anchor: Anchor,
pub size: UiValue<Vec2>,
}
impl UiLayoutTypeWindow {
pub const fn new() -> Self {
Self {
pos: UiValue::new(),
anchor: Anchor::TopLeft,
size: UiValue::new(),
}
}
pub fn full(self) -> Self {
self.size(Rl(100.0))
}
pub fn pos(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
self.pos = pos.into();
self
}
pub fn x(mut self, x: impl Into<UiValue<f32>>) -> Self {
self.pos.set_x(x);
self
}
pub fn y(mut self, y: impl Into<UiValue<f32>>) -> Self {
self.pos.set_y(y);
self
}
pub fn size(mut self, size: impl Into<UiValue<Vec2>>) -> Self {
self.size = size.into();
self
}
pub fn width(mut self, width: impl Into<UiValue<f32>>) -> Self {
self.size.set_x(width);
self
}
pub fn height(mut self, height: impl Into<UiValue<f32>>) -> Self {
self.size.set_y(height);
self
}
pub fn anchor(mut self, anchor: impl Into<Anchor>) -> Self {
self.anchor = anchor.into();
self
}
pub fn set_pos(&mut self, pos: impl Into<UiValue<Vec2>>){
self.pos = pos.into();
}
pub fn set_x(&mut self, x: impl Into<UiValue<f32>>){
self.pos.set_x(x);
}
pub fn set_y(&mut self, y: impl Into<UiValue<f32>>){
self.pos.set_y(y);
}
pub fn set_size(&mut self, size: impl Into<UiValue<Vec2>>){
self.size = size.into();
}
pub fn set_width(&mut self, width: impl Into<UiValue<f32>>){
self.size.set_x(width);
}
pub fn set_height(&mut self, height: impl Into<UiValue<f32>>){
self.size.set_y(height);
}
pub fn set_anchor(&mut self, anchor: impl Into<Anchor>){
self.anchor = anchor.into();
}
pub fn pack(self) -> UiLayout {
UiLayout::from(self)
}
pub fn wrap(self) -> UiLayoutType {
UiLayoutType::from(self)
}
pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
let pos = self.pos.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
let size = self.size.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
let mut anchor = self.anchor.as_vec();
anchor.y *= -1.0;
Rectangle2D {
pos: -parent.size / 2.0 + pos - size * (anchor),
size,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
pub struct UiLayoutTypeSolid {
pub size: UiValue<Vec2>,
pub align_x: Align,
pub align_y: Align,
pub scaling: Scaling,
}
impl UiLayoutTypeSolid {
pub fn new() -> Self {
Self {
size: Ab(Vec2::ONE).into(),
align_x: Align::CENTER,
align_y: Align::CENTER,
scaling: Scaling::Fit,
}
}
pub fn size(mut self, size: impl Into<UiValue<Vec2>>) -> Self {
self.size = size.into();
self
}
pub fn width(mut self, width: impl Into<UiValue<f32>>) -> Self {
self.size.set_x(width);
self
}
pub fn height(mut self, height: impl Into<UiValue<f32>>) -> Self {
self.size.set_y(height);
self
}
pub fn align_x(mut self, align: impl Into<Align>) -> Self {
self.align_x = align.into();
self
}
pub fn align_y(mut self, align: impl Into<Align>) -> Self {
self.align_y = align.into();
self
}
pub fn scaling(mut self, scaling: Scaling) -> Self {
self.scaling = scaling;
self
}
pub fn set_size(&mut self, size: impl Into<UiValue<Vec2>>) {
self.size = size.into();
}
pub fn set_width(&mut self, width: impl Into<UiValue<f32>>) {
self.size.set_x(width);
}
pub fn set_height(&mut self, height: impl Into<UiValue<f32>>) {
self.size.set_y(height);
}
pub fn set_align_x(&mut self, align: impl Into<Align>) {
self.align_x = align.into();
}
pub fn set_align_y(&mut self, align: impl Into<Align>) {
self.align_y = align.into();
}
pub fn set_scaling(&mut self, scaling: Scaling) {
self.scaling = scaling;
}
pub fn pack(self) -> UiLayout {
UiLayout::from(self)
}
pub fn wrap(self) -> UiLayoutType {
UiLayoutType::from(self)
}
pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
let size = self.size.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
let scale = match self.scaling {
Scaling::HorFill => parent.size.x / size.x,
Scaling::VerFill => parent.size.y / size.y,
Scaling::Fit => f32::min(parent.size.x / size.x, parent.size.y / size.y),
Scaling::Fill => f32::max(parent.size.x / size.x, parent.size.y / size.y),
};
let center_point = parent.size / 2.0;
let computed_width = size.x * scale;
let computed_height = size.y * scale;
let computed_point = Vec2::new(center_point.x - computed_width / 2.0, center_point.y - computed_height / 2.0);
Rectangle2D {
pos: Vec2::new(
computed_point.x * self.align_x.0,
computed_point.y * self.align_y.0,
),
size: (computed_width, computed_height).into(),
}
}
}