Give a length with no share in it its own type again
`UiScalar` was `Len` without the `leftover` weight, which is the separation canonical `main` already had as `Len` beside `LayoutLen` and this branch collapsed. It is needed back for the queued clamp: a cap may not contain a share, because a cap has to read the report a rule otherwise makes moot, and a share puts the container's division into the same equation -- two self-consistent assignments, which is the multiple-fixed-point failure generated seed 13 punished for orthogonal sizing. `min(report, cap)` is not a `LayoutLen` either: it is a sum of parts, and the smaller of two of them is not one. So `UiScalar` is `Len`, what was `Len` is `LayoutLen`, and the two say in their docs which is which: a `Len` is pixels plus a fraction of a box -- a position being the length from the box's start, which is why a span is two of them -- and a `LayoutLen` is a `Len` plus a claim only a container dividing its room can answer. `From<Len> for LayoutLen` is the one-way step between them. Names only; the shader's `UiScalar` is renamed with them. Checked: fmt, clippy, 105 tests, and `tabs`, `minimal`, `view`, `text` and `random` byte-identical at 1920x1200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f5e27cba9
commit
a8898aaa54
27 files changed
+218
-202
No files matched your search
@@ -172,14 +172,14 @@ impl Vec2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl UiScalar {
|
||||
impl Len {
|
||||
pub const fn align(&self, align: AxisAlign) -> UiSpan {
|
||||
let rel = align.rel();
|
||||
let rest = Rel::ONE.sub(rel);
|
||||
let at = UiScalar::from_parts(rel, Px::ZERO);
|
||||
let at = Len::from_parts(rel, Px::ZERO);
|
||||
UiSpan {
|
||||
start: UiScalar::from_parts(at.rel.sub(self.rel.mul(rel)), at.px.sub(self.px.mul(rel))),
|
||||
end: UiScalar::from_parts(at.rel.add(self.rel.mul(rest)), at.px.add(self.px.mul(rest))),
|
||||
start: Len::from_parts(at.rel.sub(self.rel.mul(rel)), at.px.sub(self.px.mul(rel))),
|
||||
end: Len::from_parts(at.rel.add(self.rel.mul(rest)), at.px.add(self.px.mul(rest))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,8 +221,8 @@ impl From<CardinalAlign> for Align {
|
||||
const impl From<RegionAlign> for UiVec2 {
|
||||
fn from(align: RegionAlign) -> Self {
|
||||
Self::new(
|
||||
UiScalar::from_parts(align.x.rel(), Px::ZERO),
|
||||
UiScalar::from_parts(align.y.rel(), Px::ZERO),
|
||||
Len::from_parts(align.x.rel(), Px::ZERO),
|
||||
Len::from_parts(align.y.rel(), Px::ZERO),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+54
-37
@@ -3,23 +3,28 @@ use crate::{Px, PxVec2, Rel, UiNum, Weight, util::impl_op};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct Size {
|
||||
pub x: Len,
|
||||
pub y: Len,
|
||||
pub x: LayoutLen,
|
||||
pub y: LayoutLen,
|
||||
}
|
||||
|
||||
/// What a widget asks for along one axis: pixels, a fraction of the box it
|
||||
/// is given, and a share of whatever is left over once everything fixed has
|
||||
/// been taken. The three add up rather than choosing between one another.
|
||||
/// What a widget asks for along one axis: a [`Len`] -- pixels and a fraction
|
||||
/// of the box it is given -- plus a share of whatever is left over once
|
||||
/// everything fixed has been taken. The parts add up rather than choosing
|
||||
/// between one another.
|
||||
///
|
||||
/// Only a container dividing its room can answer a share, so a length nobody
|
||||
/// divides is a `Len`: a position, a padding, a cap, anything already
|
||||
/// resolved.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Len {
|
||||
pub struct LayoutLen {
|
||||
pub px: Px,
|
||||
pub rel: Rel,
|
||||
pub leftover: Weight,
|
||||
}
|
||||
|
||||
impl<N: UiNum> From<N> for Len {
|
||||
impl<N: UiNum> From<N> for LayoutLen {
|
||||
fn from(value: N) -> Self {
|
||||
Len::px(value.to_f32())
|
||||
LayoutLen::px(value.to_f32())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,21 +37,33 @@ impl<Nx: UiNum, Ny: UiNum> From<(Nx, Ny)> for Size {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Len> for Size {
|
||||
fn from(value: Len) -> Self {
|
||||
/// A length with no share in it is a length a container does not have to
|
||||
/// divide, which is one it can always give.
|
||||
impl From<Len> for LayoutLen {
|
||||
fn from(len: Len) -> Self {
|
||||
Self {
|
||||
px: len.px,
|
||||
rel: len.rel,
|
||||
leftover: Weight::ZERO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LayoutLen> for Size {
|
||||
fn from(value: LayoutLen) -> Self {
|
||||
Self { x: value, y: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl Size {
|
||||
pub const ZERO: Self = Self {
|
||||
x: Len::ZERO,
|
||||
y: Len::ZERO,
|
||||
x: LayoutLen::ZERO,
|
||||
y: LayoutLen::ZERO,
|
||||
};
|
||||
|
||||
pub const LEFTOVER: Self = Self {
|
||||
x: Len::LEFTOVER,
|
||||
y: Len::LEFTOVER,
|
||||
x: LayoutLen::LEFTOVER,
|
||||
y: LayoutLen::LEFTOVER,
|
||||
};
|
||||
|
||||
/// From something measured outside layout -- a texture, a shaped line --
|
||||
@@ -57,28 +74,28 @@ impl Size {
|
||||
|
||||
pub const fn from_px(v: PxVec2) -> Self {
|
||||
Self {
|
||||
x: Len {
|
||||
x: LayoutLen {
|
||||
px: v.x,
|
||||
..Len::ZERO
|
||||
..LayoutLen::ZERO
|
||||
},
|
||||
y: Len {
|
||||
y: LayoutLen {
|
||||
px: v.y,
|
||||
..Len::ZERO
|
||||
..LayoutLen::ZERO
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rel(v: Vec2) -> Self {
|
||||
Self {
|
||||
x: Len::rel(v.x),
|
||||
y: Len::rel(v.y),
|
||||
x: LayoutLen::rel(v.x),
|
||||
y: LayoutLen::rel(v.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leftover(v: Vec2) -> Self {
|
||||
Self {
|
||||
x: Len::leftover(v.x),
|
||||
y: Len::leftover(v.y),
|
||||
x: LayoutLen::leftover(v.x),
|
||||
y: LayoutLen::leftover(v.y),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +106,7 @@ impl Size {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_axis(axis: Axis, aligned: Len, ortho: Len) -> Self {
|
||||
pub fn from_axis(axis: Axis, aligned: LayoutLen, ortho: LayoutLen) -> Self {
|
||||
match axis {
|
||||
Axis::X => Self {
|
||||
x: aligned,
|
||||
@@ -102,7 +119,7 @@ impl Size {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn axis(&self, axis: Axis) -> Len {
|
||||
pub fn axis(&self, axis: Axis) -> LayoutLen {
|
||||
match axis {
|
||||
Axis::X => self.x,
|
||||
Axis::Y => self.y,
|
||||
@@ -110,7 +127,7 @@ impl Size {
|
||||
}
|
||||
}
|
||||
|
||||
impl Len {
|
||||
impl LayoutLen {
|
||||
pub const ZERO: Self = Self {
|
||||
px: Px::ZERO,
|
||||
rel: Rel::ZERO,
|
||||
@@ -126,12 +143,12 @@ impl Len {
|
||||
/// The whole of what is left over counts as the whole box, which is what
|
||||
/// a length means to something that is not dividing a box between
|
||||
/// siblings -- a scroll asking how long its content is.
|
||||
pub fn apply_leftover(&self) -> UiScalar {
|
||||
pub fn apply_leftover(&self) -> Len {
|
||||
let share = match self.leftover > Weight::ZERO {
|
||||
true => Rel::ONE,
|
||||
false => Rel::ZERO,
|
||||
};
|
||||
UiScalar::from_parts(self.rel.add(share), self.px)
|
||||
Len::from_parts(self.rel.add(share), self.px)
|
||||
}
|
||||
|
||||
pub fn px(px: impl UiNum) -> Self {
|
||||
@@ -157,24 +174,24 @@ impl Len {
|
||||
pub mod len_fns {
|
||||
use super::*;
|
||||
|
||||
pub fn px(px: impl UiNum) -> Len {
|
||||
Len::px(px)
|
||||
pub fn px(px: impl UiNum) -> LayoutLen {
|
||||
LayoutLen::px(px)
|
||||
}
|
||||
pub fn rel(rel: impl UiNum) -> Len {
|
||||
Len::rel(rel)
|
||||
pub fn rel(rel: impl UiNum) -> LayoutLen {
|
||||
LayoutLen::rel(rel)
|
||||
}
|
||||
pub fn leftover(ratio: impl UiNum) -> Len {
|
||||
Len::leftover(ratio)
|
||||
pub fn leftover(ratio: impl UiNum) -> LayoutLen {
|
||||
LayoutLen::leftover(ratio)
|
||||
}
|
||||
}
|
||||
|
||||
impl_op!(same Len Add add; px rel leftover);
|
||||
impl_op!(same Len Sub sub; px rel leftover);
|
||||
impl_op!(same LayoutLen Add add; px rel leftover);
|
||||
impl_op!(same LayoutLen Sub sub; px rel leftover);
|
||||
|
||||
impl_op!(same Size Add add; x y);
|
||||
impl_op!(same Size Sub sub; x y);
|
||||
|
||||
impl Default for Len {
|
||||
impl Default for LayoutLen {
|
||||
fn default() -> Self {
|
||||
Self::leftover(1.0)
|
||||
}
|
||||
@@ -186,7 +203,7 @@ impl std::fmt::Display for Size {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Len {
|
||||
impl std::fmt::Display for LayoutLen {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.px != Px::ZERO {
|
||||
write!(f, "{} px;", self.px)?;
|
||||
|
||||
+42
-38
@@ -6,41 +6,41 @@ use crate::{Px, PxVec2, Rel, UiNum, util::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,
|
||||
pub x: Len,
|
||||
pub y: Len,
|
||||
}
|
||||
|
||||
impl UiVec2 {
|
||||
pub const ZERO: Self = Self {
|
||||
x: UiScalar::ZERO,
|
||||
y: UiScalar::ZERO,
|
||||
x: Len::ZERO,
|
||||
y: Len::ZERO,
|
||||
};
|
||||
|
||||
pub const fn new(x: UiScalar, y: UiScalar) -> Self {
|
||||
pub const fn new(x: Len, y: Len) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub const fn px(px: impl const Into<Vec2>) -> Self {
|
||||
let px = px.into();
|
||||
Self {
|
||||
x: UiScalar::px(px.x),
|
||||
y: UiScalar::px(px.y),
|
||||
x: Len::px(px.x),
|
||||
y: Len::px(px.y),
|
||||
}
|
||||
}
|
||||
|
||||
/// From lengths already on the grid, with no fraction of a box.
|
||||
pub const fn from_px(px: PxVec2) -> Self {
|
||||
Self {
|
||||
x: UiScalar::from_parts(Rel::ZERO, px.x),
|
||||
y: UiScalar::from_parts(Rel::ZERO, px.y),
|
||||
x: Len::from_parts(Rel::ZERO, px.x),
|
||||
y: Len::from_parts(Rel::ZERO, px.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),
|
||||
x: Len::rel(rel.x),
|
||||
y: Len::rel(rel.y),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +61,14 @@ impl UiVec2 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn axis_mut(&mut self, axis: Axis) -> &mut UiScalar {
|
||||
pub fn axis_mut(&mut self, axis: Axis) -> &mut Len {
|
||||
match axis {
|
||||
Axis::X => &mut self.x,
|
||||
Axis::Y => &mut self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn axis(&self, axis: Axis) -> UiScalar {
|
||||
pub fn axis(&self, axis: Axis) -> Len {
|
||||
match axis {
|
||||
Axis::X => self.x,
|
||||
Axis::Y => self.y,
|
||||
@@ -83,7 +83,7 @@ impl UiVec2 {
|
||||
|
||||
pub const FULL_SIZE: Self = Self::rel(Vec2::ONE);
|
||||
|
||||
pub const fn from_axis(axis: Axis, aligned: UiScalar, ortho: UiScalar) -> Self {
|
||||
pub const fn from_axis(axis: Axis, aligned: Len, ortho: Len) -> Self {
|
||||
match axis {
|
||||
Axis::X => Self {
|
||||
x: aligned,
|
||||
@@ -129,21 +129,27 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A position along one axis, as a fraction of the box it sits in plus an
|
||||
/// offset: `rel * len + px`. Both parts are fixed point, so composing one
|
||||
/// through a chain of boxes rounds only where it multiplies and lands on the
|
||||
/// same number as any other route to the same place.
|
||||
/// A length along one axis: a fraction of the box it is measured in plus an
|
||||
/// offset, `rel * box + px`. A position is the same number -- the length from
|
||||
/// the start of the box to the point -- which is why a [`UiSpan`] is two of
|
||||
/// these. Both parts are fixed point, so composing one through a chain of
|
||||
/// boxes rounds only where it multiplies, and lands on the same number as any
|
||||
/// other route to the same place.
|
||||
///
|
||||
/// It carries no claim on what a container has left over. That is
|
||||
/// [`crate::LayoutLen`], which is this plus a weight, and which means nothing
|
||||
/// to anyone but whoever divides the room.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, Default, bytemuck::Zeroable)]
|
||||
pub struct UiScalar {
|
||||
pub struct Len {
|
||||
pub rel: Rel,
|
||||
pub px: Px,
|
||||
}
|
||||
|
||||
impl_op!(same UiScalar Add add; rel px);
|
||||
impl_op!(same UiScalar Sub sub; rel px);
|
||||
impl_op!(same Len Add add; rel px);
|
||||
impl_op!(same Len Sub sub; rel px);
|
||||
|
||||
impl UiScalar {
|
||||
impl Len {
|
||||
pub const ZERO: Self = Self {
|
||||
rel: Rel::ZERO,
|
||||
px: Px::ZERO,
|
||||
@@ -192,10 +198,8 @@ impl UiScalar {
|
||||
}
|
||||
}
|
||||
|
||||
/// Both channels by the same factor, which is what a fraction of a
|
||||
/// length means when the length is part pixels and part a share.
|
||||
/// Both channels by the same fraction, which is what a part of a length
|
||||
/// means when the length is part pixels and part a share.
|
||||
/// Both parts by the same fraction, which is what a part of a length
|
||||
/// means when the length is part pixels and part a fraction of a box.
|
||||
pub const fn scale(&self, by: Rel) -> Self {
|
||||
Self {
|
||||
rel: self.rel.mul(by),
|
||||
@@ -215,14 +219,14 @@ impl UiScalar {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn within_len(&self, len: UiScalar) -> Self {
|
||||
pub fn within_len(&self, len: Len) -> Self {
|
||||
self.within(&UiSpan {
|
||||
start: UiScalar::ZERO,
|
||||
start: Len::ZERO,
|
||||
end: len,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select_len(&self, len: UiScalar) -> Self {
|
||||
pub fn select_len(&self, len: Len) -> Self {
|
||||
len.within_len(*self)
|
||||
}
|
||||
|
||||
@@ -245,24 +249,24 @@ impl UiScalar {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct UiSpan {
|
||||
pub start: UiScalar,
|
||||
pub end: UiScalar,
|
||||
pub start: Len,
|
||||
pub end: Len,
|
||||
}
|
||||
|
||||
impl UiSpan {
|
||||
pub const FULL: Self = Self {
|
||||
start: UiScalar::ZERO,
|
||||
end: UiScalar::FULL,
|
||||
start: Len::ZERO,
|
||||
end: Len::FULL,
|
||||
};
|
||||
|
||||
pub const fn rel(rel: f32) -> Self {
|
||||
Self {
|
||||
start: UiScalar::rel(rel),
|
||||
end: UiScalar::rel(rel),
|
||||
start: Len::rel(rel),
|
||||
end: Len::rel(rel),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn new(start: UiScalar, end: UiScalar) -> Self {
|
||||
pub const fn new(start: Len, end: Len) -> Self {
|
||||
Self { start, end }
|
||||
}
|
||||
|
||||
@@ -273,7 +277,7 @@ impl UiSpan {
|
||||
std::mem::swap(&mut self.start.px, &mut self.end.px);
|
||||
}
|
||||
|
||||
pub const fn shift(&mut self, offset: UiScalar) {
|
||||
pub const fn shift(&mut self, offset: Len) {
|
||||
self.start += offset;
|
||||
self.end += offset;
|
||||
}
|
||||
@@ -285,7 +289,7 @@ impl UiSpan {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn len(&self) -> UiScalar {
|
||||
pub const fn len(&self) -> Len {
|
||||
self.end - self.start
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user