Compare commits
3 Commits
tuple_expe
...
132113f09e
| Author | SHA1 | Date | |
|---|---|---|---|
| 132113f09e | |||
| f2cbf90d1d | |||
| 848347e6b3 |
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gui"
|
name = "gui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitive::{Axis, Painter, RoundedRectData, UIRegion},
|
UIColor, Widget, WidgetArrLike, WidgetFn, WidgetId, WidgetLike,
|
||||||
ToId, UIColor, Widget, WidgetArrLike, WidgetFn, WidgetId, WidgetIdLikeTuple, WidgetLike,
|
primitive::{Axis, Painter, RoundedRectData, UIRegion, Vec2},
|
||||||
WidgetLikeTuple,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -57,13 +56,13 @@ impl Span {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let ratios = ratios.map(|r| r.to_f32());
|
let ratios = ratios.map(|r| r.to_f32());
|
||||||
let total: f32 = ratios.iter().sum();
|
let total: f32 = ratios.iter().sum();
|
||||||
let mut start = 0.0;
|
let mut start = -1.0;
|
||||||
Self {
|
Self {
|
||||||
elements: elements
|
elements: elements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(ratios)
|
.zip(ratios)
|
||||||
.map(|(e, r)| {
|
.map(|(e, r)| {
|
||||||
let end = start + r / total;
|
let end = start + (r / total) * 2.0;
|
||||||
let res = (start..end, e);
|
let res = (start..end, e);
|
||||||
start = end;
|
start = end;
|
||||||
res
|
res
|
||||||
@@ -120,6 +119,7 @@ impl<T: UINum> From<T> for Padding {
|
|||||||
|
|
||||||
pub trait WidgetUtil {
|
pub trait WidgetUtil {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned>;
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned>;
|
||||||
|
fn center(self, size: impl Into<Vec2>) -> impl WidgetLike<Widget = Regioned>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: WidgetLike> WidgetUtil for W {
|
impl<W: WidgetLike> WidgetUtil for W {
|
||||||
@@ -129,18 +129,22 @@ impl<W: WidgetLike> WidgetUtil for W {
|
|||||||
inner: self.add(ui).erase_type(),
|
inner: self.add(ui).erase_type(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn center(self, size: impl Into<Vec2>) -> impl WidgetLike<Widget = Regioned> {
|
||||||
|
WidgetFn(|ui| Regioned {
|
||||||
|
region: UIRegion::center(size.into()),
|
||||||
|
inner: self.add(ui).erase_type(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetArrUtil<const LEN: usize> {
|
pub trait WidgetArrUtil<const LEN: usize> {
|
||||||
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span>;
|
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Wa: WidgetArrLike<LEN>> WidgetArrUtil<LEN> for Wa
|
impl<const LEN: usize, Wa: WidgetArrLike<LEN>> WidgetArrUtil<LEN> for Wa {
|
||||||
where
|
|
||||||
<Wa::Ws as WidgetLikeTuple<LEN>>::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
|
||||||
{
|
|
||||||
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span> {
|
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span> {
|
||||||
WidgetFn(move |ui| Span::proportioned(axis, ratios, self.ui(ui).erase_types()))
|
WidgetFn(move |ui| Span::proportioned(axis, ratios, self.ui(ui).arr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,11 +31,15 @@ impl From<UI> for UIBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UIBuilder {
|
impl UIBuilder {
|
||||||
pub fn add<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
pub fn add<W: Widget>(&mut self, w: impl WidgetLike<Widget = W>) -> WidgetRef<W> {
|
||||||
WidgetRef::new(self.clone(), (self.push(w),))
|
WidgetRef::new([w.add(self).erase_type()])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
pub fn add_widget<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
||||||
|
WidgetRef::new([self.push(w)])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId {
|
||||||
let mut ui = self.ui.borrow_mut();
|
let mut ui = self.ui.borrow_mut();
|
||||||
let id = ui.ids.next();
|
let id = ui.ids.next();
|
||||||
ui.widgets.insert(id.duplicate(), w);
|
ui.widgets.insert(id.duplicate(), w);
|
||||||
|
|||||||
@@ -3,11 +3,7 @@ use std::{
|
|||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{primitive::Painter, util::ID, UIBuilder};
|
||||||
primitive::Painter,
|
|
||||||
util::{impl_tuple, ID},
|
|
||||||
UIBuilder,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait Widget: 'static + Any {
|
pub trait Widget: 'static + Any {
|
||||||
fn draw(&self, painter: &mut Painter);
|
fn draw(&self, painter: &mut Painter);
|
||||||
@@ -19,21 +15,19 @@ impl<W: Widget> Widget for (W,) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AnyWidget;
|
||||||
|
|
||||||
#[derive(Eq, Hash, PartialEq, Debug)]
|
#[derive(Eq, Hash, PartialEq, Debug)]
|
||||||
pub struct WidgetId<W = ()> {
|
pub struct WidgetId<W = AnyWidget> {
|
||||||
pub(super) ty: TypeId,
|
pub(super) ty: TypeId,
|
||||||
pub(super) id: ID,
|
pub(super) id: ID,
|
||||||
_pd: PhantomData<W>,
|
_pd: PhantomData<W>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: temp
|
// TODO: temp
|
||||||
impl<W: Widget> Clone for WidgetId<W> {
|
impl<W> Clone for WidgetId<W> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self::new(self.id.duplicate(), self.ty)
|
||||||
ty: self.ty,
|
|
||||||
id: self.id.duplicate(),
|
|
||||||
_pd: self._pd,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +39,7 @@ impl<W> WidgetId<W> {
|
|||||||
_pd: PhantomData,
|
_pd: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn erase_type(self) -> WidgetId<()> {
|
pub fn erase_type(self) -> WidgetId<AnyWidget> {
|
||||||
self.cast_type()
|
self.cast_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +53,7 @@ impl<W> WidgetId<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetLike {
|
pub trait WidgetLike {
|
||||||
type Widget: Widget;
|
type Widget;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<Self::Widget>;
|
fn add(self, ui: &mut UIBuilder) -> WidgetId<Self::Widget>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,109 +64,96 @@ impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike for WidgetFn<F, W> {
|
|||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
let w = (self.0)(ui);
|
let w = (self.0)(ui);
|
||||||
ui.add(w).to_id()
|
ui.add_widget(w).to_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike for W {
|
impl<W: Widget> WidgetLike for W {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
ui.add(self).to_id()
|
ui.add_widget(self).to_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike for WidgetId<W> {
|
impl<W> WidgetLike for WidgetId<W> {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike for WidgetArr<1, (W,)> {
|
impl<W> WidgetLike for WidgetArr<1, (W,)> {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
self.arr.0
|
let [id] = self.arr;
|
||||||
|
id.cast_type()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WidgetArr<const LEN: usize, Ws: WidgetLikeTuple<LEN>> {
|
pub struct WidgetArr<const LEN: usize, Ws> {
|
||||||
pub ui: UIBuilder,
|
pub arr: [WidgetId; LEN],
|
||||||
pub arr: Ws::Wrap<ToId>,
|
_pd: PhantomData<Ws>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Ws: WidgetLikeTuple<LEN>> WidgetArr<LEN, Ws>
|
impl<const LEN: usize, Ws> WidgetArr<LEN, Ws> {
|
||||||
where
|
pub fn new(arr: [WidgetId; LEN]) -> Self {
|
||||||
Ws::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
Self {
|
||||||
{
|
arr,
|
||||||
pub fn new(ui: UIBuilder, arr: Ws::Wrap<ToId>) -> Self {
|
_pd: PhantomData,
|
||||||
Self { ui, arr }
|
|
||||||
}
|
}
|
||||||
pub fn erase_types(self) -> [WidgetId; LEN] {
|
|
||||||
self.arr.map::<EraseId>(&mut ())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WidgetRef<W> = WidgetArr<1, (W,)>;
|
pub type WidgetRef<W> = WidgetArr<1, (W,)>;
|
||||||
|
|
||||||
impl<W: WidgetLike> WidgetRef<W> {
|
impl<W> WidgetRef<W> {
|
||||||
pub fn handle(&self) -> WidgetId<W::Widget> {
|
pub fn handle(&self) -> WidgetId<W> {
|
||||||
self.arr.0.clone()
|
let [id] = &self.arr;
|
||||||
|
id.clone().cast_type()
|
||||||
}
|
}
|
||||||
pub fn to_id(self) -> WidgetId<W::Widget> {
|
pub fn to_id(self) -> WidgetId<W> {
|
||||||
self.arr.0
|
let [id] = self.arr;
|
||||||
|
id.cast_type()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetArrLike<const LEN: usize> {
|
pub trait WidgetArrLike<const LEN: usize> {
|
||||||
type Ws: WidgetLikeTuple<LEN>;
|
type Ws;
|
||||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, Self::Ws>;
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, Self::Ws>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Ws: WidgetLikeTuple<LEN>> WidgetArrLike<LEN> for WidgetArr<LEN, Ws> {
|
impl<const LEN: usize, Ws> WidgetArrLike<LEN> for WidgetArr<LEN, Ws> {
|
||||||
type Ws = Ws;
|
type Ws = Ws;
|
||||||
fn ui(self, _: &mut UIBuilder) -> WidgetArr<LEN, Ws> {
|
fn ui(self, _: &mut UIBuilder) -> WidgetArr<LEN, Ws> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_tuple!(Widget);
|
// I hate this language it's so bad why do I even use it
|
||||||
impl_tuple!(WidgetLike);
|
macro_rules! impl_widget_arr {
|
||||||
impl_tuple!(WidgetIdLike);
|
($n:expr;$($T:tt)*) => {
|
||||||
|
impl<$($T: WidgetLike,)*> WidgetArrLike<$n> for ($($T,)*) {
|
||||||
pub trait WidgetIdLike {
|
type Ws = ($($T::Widget,)*);
|
||||||
fn erase_type(self) -> WidgetId;
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<$n, ($($T::Widget,)*)> {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let ($($T,)*) = self;
|
||||||
|
WidgetArr::new(
|
||||||
|
[$($T.add(ui).cast_type(),)*],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> WidgetIdLike for WidgetId<W> {
|
impl_widget_arr!(1;A);
|
||||||
fn erase_type(self) -> WidgetId {
|
impl_widget_arr!(2;A B);
|
||||||
self.erase_type()
|
impl_widget_arr!(3;A B C);
|
||||||
}
|
impl_widget_arr!(4;A B C D);
|
||||||
}
|
impl_widget_arr!(5;A B C D E);
|
||||||
|
impl_widget_arr!(6;A B C D E F);
|
||||||
pub struct ToId;
|
impl_widget_arr!(7;A B C D E F G);
|
||||||
impl WidgetLikeWrapper for ToId {
|
impl_widget_arr!(8;A B C D E F G H);
|
||||||
type Wrap<T: WidgetLike> = WidgetId<T::Widget>;
|
impl_widget_arr!(9;A B C D E F G H I);
|
||||||
type Ctx = UIBuilder;
|
impl_widget_arr!(10;A B C D E F G H I J);
|
||||||
fn wrap<T: WidgetLike>(t: T, ctx: &mut Self::Ctx) -> Self::Wrap<T> {
|
impl_widget_arr!(11;A B C D E F G H I J K);
|
||||||
t.add(ctx)
|
impl_widget_arr!(12;A B C D E F G H I J K L);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EraseId;
|
|
||||||
impl WidgetIdLikeMapper for EraseId {
|
|
||||||
type Map = WidgetId<()>;
|
|
||||||
type Ctx = ();
|
|
||||||
fn map<Id: WidgetIdLike>(t: Id, _: &mut Self::Ctx) -> Self::Map {
|
|
||||||
t.erase_type()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WidgetLikeTuple<LEN>, const LEN: usize> WidgetArrLike<LEN> for T
|
|
||||||
where
|
|
||||||
T::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
|
||||||
{
|
|
||||||
type Ws = T;
|
|
||||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, T> {
|
|
||||||
WidgetArr::new(ui.clone(), self.wrap::<ToId>(ui))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ impl<T: ColorNum> Color<T> {
|
|||||||
pub const fn rgb(r: T, g: T, b: T) -> Self {
|
pub const fn rgb(r: T, g: T, b: T) -> Self {
|
||||||
Self { r, g, b, a: T::MAX }
|
Self { r, g, b, a: T::MAX }
|
||||||
}
|
}
|
||||||
|
pub fn alpha(mut self, a: T) -> Self {
|
||||||
|
self.a = a;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ColorNum {
|
pub trait ColorNum {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use crate::primitive::{point::point, Point};
|
use crate::primitive::{Vec2, vec2::point};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
||||||
pub struct UIPos {
|
pub struct UIPos {
|
||||||
pub anchor: Point,
|
pub anchor: Vec2,
|
||||||
pub offset: Point,
|
pub offset: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UIPos {
|
impl UIPos {
|
||||||
@@ -15,24 +15,32 @@ impl UIPos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn top_left() -> Self {
|
pub const fn center() -> Self {
|
||||||
Self::anchor_offset(0.0, 0.0, 0.0, 0.0)
|
Self::anchor_offset(0.0, 0.0, 0.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn top_left() -> Self {
|
||||||
|
Self::anchor_offset(-1.0, -1.0, 0.0, 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn bottom_right() -> Self {
|
pub const fn bottom_right() -> Self {
|
||||||
Self::anchor_offset(1.0, 1.0, 0.0, 0.0)
|
Self::anchor_offset(1.0, 1.0, 0.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn within(&self, region: &UIRegion) -> UIPos {
|
pub const fn offset(mut self, offset: Vec2) -> Self {
|
||||||
let range = region.bot_right.anchor - region.top_left.anchor;
|
self.offset = offset;
|
||||||
let region_offset = region
|
self
|
||||||
.top_left
|
|
||||||
.offset
|
|
||||||
.lerp(region.bot_right.offset, self.anchor);
|
|
||||||
UIPos {
|
|
||||||
anchor: region.top_left.anchor + self.anchor * range,
|
|
||||||
offset: self.offset + region_offset,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn within(&self, region: &UIRegion) -> UIPos {
|
||||||
|
let lerp = self.anchor_01();
|
||||||
|
let anchor = region.top_left.anchor.lerp(region.bot_right.anchor, lerp);
|
||||||
|
let offset = self.offset + region.top_left.offset.lerp(region.bot_right.offset, lerp);
|
||||||
|
UIPos { anchor, offset }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn anchor_01(&self) -> Vec2 {
|
||||||
|
(self.anchor + 1.0) / 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn axis_mut(&mut self, axis: Axis) -> UIPosAxisView<'_> {
|
pub fn axis_mut(&mut self, axis: Axis) -> UIPosAxisView<'_> {
|
||||||
@@ -68,6 +76,12 @@ impl UIRegion {
|
|||||||
bot_right: UIPos::bottom_right(),
|
bot_right: UIPos::bottom_right(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn center(size: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
top_left: UIPos::center().offset(-size / 2.0),
|
||||||
|
bot_right: UIPos::center().offset(size / 2.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn within(&self, parent: &Self) -> Self {
|
pub fn within(&self, parent: &Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
top_left: self.top_left.within(parent),
|
top_left: self.top_left.within(parent),
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
mod color;
|
mod color;
|
||||||
mod def;
|
mod def;
|
||||||
mod format;
|
mod format;
|
||||||
mod point;
|
mod vec2;
|
||||||
|
|
||||||
pub use color::*;
|
pub use color::*;
|
||||||
pub use def::*;
|
pub use def::*;
|
||||||
pub use format::*;
|
pub use format::*;
|
||||||
pub use point::*;
|
pub use vec2::*;
|
||||||
|
|
||||||
use crate::{render::data::PrimitiveInstance, WidgetId, Widgets};
|
use crate::{render::data::PrimitiveInstance, WidgetId, Widgets};
|
||||||
use bytemuck::Pod;
|
use bytemuck::Pod;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, PartialEq, Default, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct Point {
|
pub struct Vec2 {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn point(x: f32, y: f32) -> Point {
|
pub const fn point(x: f32, y: f32) -> Vec2 {
|
||||||
Point::new(x, y)
|
Vec2::new(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Point {
|
impl Vec2 {
|
||||||
pub const fn new(x: f32, y: f32) -> Self {
|
pub const fn new(x: f32, y: f32) -> Self {
|
||||||
Self { x, y }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ const fn lerp(x: f32, y: f32, amt: f32) -> f32 {
|
|||||||
(1.0 - amt) * x + y * amt
|
(1.0 - amt) * x + y * amt
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const From<f32> for Point {
|
impl const From<f32> for Vec2 {
|
||||||
fn from(v: f32) -> Self {
|
fn from(v: f32) -> Self {
|
||||||
Self { x: v, y: v }
|
Self { x: v, y: v }
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ impl const From<f32> for Point {
|
|||||||
|
|
||||||
macro_rules! impl_op_inner {
|
macro_rules! impl_op_inner {
|
||||||
($op:ident $fn:ident $opa:ident $fna:ident) => {
|
($op:ident $fn:ident $opa:ident $fna:ident) => {
|
||||||
impl const $op for Point {
|
impl const $op for Vec2 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn $fn(self, rhs: Self) -> Self::Output {
|
fn $fn(self, rhs: Self) -> Self::Output {
|
||||||
@@ -47,13 +47,13 @@ macro_rules! impl_op_inner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl $opa for Point {
|
impl $opa for Vec2 {
|
||||||
fn $fna(&mut self, rhs: Self) {
|
fn $fna(&mut self, rhs: Self) {
|
||||||
self.x.$fna(rhs.x);
|
self.x.$fna(rhs.x);
|
||||||
self.y.$fna(rhs.y);
|
self.y.$fna(rhs.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl const $op<f32> for Point {
|
impl const $op<f32> for Vec2 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn $fn(self, rhs: f32) -> Self::Output {
|
fn $fn(self, rhs: f32) -> Self::Output {
|
||||||
@@ -63,7 +63,7 @@ macro_rules! impl_op_inner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl $opa<f32> for Point {
|
impl $opa<f32> for Vec2 {
|
||||||
fn $fna(&mut self, rhs: f32) {
|
fn $fna(&mut self, rhs: f32) {
|
||||||
self.x.$fna(rhs);
|
self.x.$fna(rhs);
|
||||||
self.y.$fna(rhs);
|
self.y.$fna(rhs);
|
||||||
@@ -82,3 +82,19 @@ impl_op!(Add add);
|
|||||||
impl_op!(Sub sub);
|
impl_op!(Sub sub);
|
||||||
impl_op!(Mul mul);
|
impl_op!(Mul mul);
|
||||||
impl_op!(Div div);
|
impl_op!(Div div);
|
||||||
|
|
||||||
|
impl Neg for Vec2 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(mut self) -> Self::Output {
|
||||||
|
self.x = -self.x;
|
||||||
|
self.y = -self.y;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(f32, f32)> for Vec2 {
|
||||||
|
fn from((x, y): (f32, f32)) -> Self {
|
||||||
|
Self { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,8 +42,8 @@ fn vs_main(
|
|||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
let top_left = in.top_left_anchor * window.dim + in.top_left_offset;
|
let top_left = (in.top_left_anchor + 1.0) / 2.0 * window.dim + in.top_left_offset;
|
||||||
let bot_right = in.bottom_right_anchor * window.dim + in.bottom_right_offset;
|
let bot_right = (in.bottom_right_anchor + 1.0) / 2.0 * window.dim + in.bottom_right_offset;
|
||||||
let size = bot_right - top_left;
|
let size = bot_right - top_left;
|
||||||
|
|
||||||
var pos = top_left + vec2<f32>(
|
var pos = top_left + vec2<f32>(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
use gui::{primitive::Axis, RoundedRect, UIColor, WidgetArrUtil, WidgetUtil, UI};
|
use gui::{RoundedRect, UI, UIColor, WidgetArrUtil, WidgetUtil, primitive::Axis};
|
||||||
use render::Renderer;
|
use render::Renderer;
|
||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ impl Client {
|
|||||||
(
|
(
|
||||||
blue,
|
blue,
|
||||||
(
|
(
|
||||||
rect.color(UIColor::RED),
|
rect.color(UIColor::RED).center((100.0, 100.0)),
|
||||||
(
|
(
|
||||||
rect.color(UIColor::ORANGE),
|
rect.color(UIColor::ORANGE),
|
||||||
rect.color(UIColor::LIME).pad(10.0),
|
rect.color(UIColor::LIME).pad(10.0),
|
||||||
@@ -50,6 +50,7 @@ impl Client {
|
|||||||
.span(Axis::Y, [3, 1])
|
.span(Axis::Y, [3, 1])
|
||||||
.pad(10),
|
.pad(10),
|
||||||
);
|
);
|
||||||
|
// let mut ui = ui.finish((blue, rect.color(UIColor::RED)).span(Axis::X, [1, 1]));
|
||||||
ui.widgets.get_mut(&handle).unwrap().color = UIColor::MAGENTA;
|
ui.widgets.get_mut(&handle).unwrap().color = UIColor::MAGENTA;
|
||||||
renderer.update(&ui);
|
renderer.update(&ui);
|
||||||
Self { renderer }
|
Self { renderer }
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ impl IDTracker {
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use this
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn free(&mut self, id: ID) {
|
pub fn free(&mut self, id: ID) {
|
||||||
self.free.push(id);
|
self.free.push(id);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
mod id;
|
mod id;
|
||||||
mod tuple;
|
|
||||||
|
|
||||||
pub use id::*;
|
pub use id::*;
|
||||||
pub use tuple::*;
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
macro_rules! impl_tuple {
|
|
||||||
($Tuple:ident $Bound:ident $Wrapper:ident $Mapper:ident $n:expr;$TL:tt $($T:tt)*) => {
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
impl<$($T: $Bound,)* $TL: $Bound> $Tuple<$n> for ($($T,)* $TL,) {
|
|
||||||
type Wrap<W: $Wrapper> = ($(W::Wrap<$T>,)* W::Wrap<$TL>,);
|
|
||||||
type Map<M: $Mapper> = [M::Map; $n];
|
|
||||||
fn wrap<W: $Wrapper>(self, ctx: &mut W::Ctx) -> ($(W::Wrap<$T>,)* W::Wrap<$TL>,) {
|
|
||||||
let ($($T,)* $TL,) = self;
|
|
||||||
($(W::wrap($T, ctx),)* W::wrap($TL, ctx),)
|
|
||||||
}
|
|
||||||
fn map<M: $Mapper>(self, ctx: &mut M::Ctx) -> [M::Map; $n] {
|
|
||||||
let ($($T,)* $TL,) = self;
|
|
||||||
[$(M::map($T, ctx),)* M::map($TL, ctx)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($Tuple:ident, $Bound:ident, $Wrapper:ident, $Mapper:ident) => {
|
|
||||||
pub trait $Wrapper {
|
|
||||||
type Wrap<T: $Bound>;
|
|
||||||
type Ctx;
|
|
||||||
fn wrap<T: $Bound>(t: T, ctx: &mut Self::Ctx) -> Self::Wrap<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait $Mapper {
|
|
||||||
type Map;
|
|
||||||
type Ctx;
|
|
||||||
fn map<T: $Bound>(t: T, ctx: &mut Self::Ctx) -> Self::Map;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait $Tuple<const LEN: usize> {
|
|
||||||
type Wrap<W: $Wrapper>;
|
|
||||||
type Map<M: $Mapper>;
|
|
||||||
fn map<M: $Mapper>(self, ctx: &mut M::Ctx) -> [M::Map; LEN];
|
|
||||||
fn wrap<W: $Wrapper>(self, ctx: &mut W::Ctx) -> Self::Wrap<W>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 1;A);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 2;A B);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 3;A B C);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 4;A B C D);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 5;A B C D E);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 6;A B C D E F);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 7;A B C D E F G);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 8;A B C D E F G H);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 9;A B C D E F G H I);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 10;A B C D E F G H I J);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 11;A B C D E F G H I J K);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 12;A B C D E F G H I J K L);
|
|
||||||
};
|
|
||||||
($Bound:ident) => {
|
|
||||||
impl_tuple!(${concat($Bound, Tuple)}, $Bound, ${concat($Bound, Wrapper)}, ${concat($Bound, Mapper)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub(crate) use impl_tuple;
|
|
||||||
Reference in New Issue
Block a user