refactor(output,tui): fix errors, now there's more...
Some checks failed
/ build (push) Has been cancelled

This commit is contained in:
same mf who else 2026-02-17 04:09:10 +02:00
parent 4fa5d74fa2
commit 2dc74657d5
9 changed files with 713 additions and 754 deletions

View file

@ -9,8 +9,10 @@ bumpalo = [ "dep:bumpalo" ]
dsl = []
[dependencies]
dizzle = { path = "../../dizzle" }
bumpalo = { optional = true, workspace = true }
atomic_float = { workspace = true }
bumpalo = { workspace = true, optional = true }
dizzle = { path = "../../dizzle" }
quanta = { workspace = true }
[dev-dependencies]
tengri = { path = "../tengri", features = [ "dsl", "tui" ] }

View file

@ -15,6 +15,8 @@ pub(crate) use std::ops::{Add, Sub, Mul, Div};
pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}};
pub(crate) use std::marker::PhantomData;
pub(crate) use dizzle::*;
pub(crate) use quanta::Clock;
pub(crate) use atomic_float::AtomicF64;
// Define macros first, so that private macros are available in private modules:

View file

@ -41,68 +41,68 @@ impl<O: Out> HasWH<O::Unit> for O {
}
impl<N: Coord> WH<N> {
fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] }
fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h)] }
fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
pub fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] }
pub fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h)] }
pub fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
if self.w() < w || self.h() < h { return Err(format!("min {w}x{h}").into()) }
Ok(self)
}
}
impl<N: Coord> XYWH<N> {
fn zero () -> Self {
pub fn zero () -> Self {
Self(0.into(), 0.into(), 0.into(), 0.into())
}
fn x2 (&self) -> N {
pub fn x2 (&self) -> N {
self.x().plus(self.w())
}
fn y2 (&self) -> N {
pub fn y2 (&self) -> N {
self.y().plus(self.h())
}
fn with_w (&self, w: N) -> XYWH<N> {
pub fn with_w (&self, w: N) -> XYWH<N> {
Self(self.x(), self.y(), w, self.h())
}
fn with_h (&self, h: N) -> XYWH<N> {
pub fn with_h (&self, h: N) -> XYWH<N> {
Self(self.x(), self.y(), self.w(), h)
}
fn lrtb (&self) -> XYWH<N> {
pub fn lrtb (&self) -> XYWH<N> {
Self(self.x(), self.x2(), self.y(), self.y2())
}
fn clipped_w (&self, w: N) -> XYWH<N> {
pub fn clipped_w (&self, w: N) -> XYWH<N> {
Self(self.x(), self.y(), self.w().min(w), self.h())
}
fn clipped_h (&self, h: N) -> XYWH<N> {
pub fn clipped_h (&self, h: N) -> XYWH<N> {
Self(self.x(), self.y(), self.w(), self.h().min(h))
}
fn clipped (&self, wh: WH<N>) -> XYWH<N> {
pub fn clipped (&self, wh: WH<N>) -> XYWH<N> {
Self(self.x(), self.y(), wh.w(), wh.h())
}
/// Iterate over every covered X coordinate.
fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
pub fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
let Self(x, _, w, _) = *self;
x..(x+w)
}
/// Iterate over every covered Y coordinate.
fn iter_y (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
pub fn iter_y (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
let Self(_, y, _, h) = *self;
y..(y+h)
}
fn center (&self) -> XY<N> {
pub fn center (&self) -> XY<N> {
let Self(x, y, w, h) = self;
XY(self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into()))
}
fn centered (&self) -> XY<N> {
pub fn centered (&self) -> XY<N> {
let Self(x, y, w, h) = *self;
XY(x.minus(w/2.into()), y.minus(h/2.into()))
}
fn centered_x (&self, n: N) -> XYWH<N> {
pub fn centered_x (&self, n: N) -> XYWH<N> {
let Self(x, y, w, h) = *self;
XYWH((x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into())
}
fn centered_y (&self, n: N) -> XYWH<N> {
pub fn centered_y (&self, n: N) -> XYWH<N> {
let Self(x, y, w, h) = *self;
XYWH(x.plus(w / 2.into()), (y.plus(h / 2.into())).minus(n / 2.into()), 1.into(), n)
}
fn centered_xy (&self, [n, m]: [N;2]) -> XYWH<N> {
pub fn centered_xy (&self, [n, m]: [N;2]) -> XYWH<N> {
let Self(x, y, w, h) = *self;
XYWH((x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m)
}
@ -847,3 +847,51 @@ impl<C, T, U> Field<C, T, U> {
Field::<C, T, V> { value, value_fg: fg, value_bg: bg, value_align: align, ..self }
}
}
impl Default for PerfModel {
fn default () -> Self {
Self {
enabled: true,
clock: quanta::Clock::new(),
used: Default::default(),
window: Default::default(),
}
}
}
impl PerfModel {
pub fn get_t0 (&self) -> Option<u64> {
if self.enabled {
Some(self.clock.raw())
} else {
None
}
}
pub fn get_t1 (&self, t0: Option<u64>) -> Option<std::time::Duration> {
if let Some(t0) = t0 {
if self.enabled {
Some(self.clock.delta(t0, self.clock.raw()))
} else {
None
}
} else {
None
}
}
pub fn update (&self, t0: Option<u64>, microseconds: f64) {
if let Some(t0) = t0 {
let t1 = self.clock.raw();
self.used.store(self.clock.delta_as_nanos(t0, t1) as f64, Relaxed);
self.window.store(microseconds, Relaxed,);
}
}
pub fn percentage (&self) -> Option<f64> {
let window = self.window.load(Relaxed) * 1000.0;
if window > 0.0 {
let used = self.used.load(Relaxed);
Some(100.0 * used / window)
} else {
None
}
}
}

View file

@ -256,3 +256,15 @@ pub struct Field<C, T, U> {
pub value_bg: Option<C>,
pub value_align: Option<Direction>,
}
/// Performance counter
#[derive(Debug)]
pub struct PerfModel {
pub enabled: bool,
pub clock: quanta::Clock,
// In nanoseconds. Time used by last iteration.
pub used: AtomicF64,
// In microseconds. Max prescribed time for iteration (frame, chunk...).
pub window: AtomicF64,
}

View file

@ -155,3 +155,7 @@ pub trait Measured<O: Out> {
fn measure_width (&self) -> O::Unit { self.measure().w() }
fn measure_height (&self) -> O::Unit { self.measure().h() }
}
pub trait HasPerf {
fn perf (&self) -> &PerfModel;
}