remove last color conversion from render loop

This commit is contained in:
🪞👃🪞 2025-01-20 16:27:16 +01:00
parent a31de6e819
commit 7ad574cf2a
9 changed files with 122 additions and 47 deletions

View file

@ -92,7 +92,7 @@ impl MidiClip {
controller: 123.into(),
value: 0.into()
}]]),
Some(ItemColor::from(Color::Rgb(32, 32, 32)).into())
Some(ItemColor::from_rgb(Color::Rgb(32, 32, 32)).into())
)
}
}

View file

@ -50,17 +50,17 @@ try_from_expr!(<'a, E>: Align<RenderBox<'a, E>>: |state, iter|
}
});
impl<A> Align<A> {
pub fn c (a: A) -> Self { Self(Alignment::Center, a) }
pub fn x (a: A) -> Self { Self(Alignment::X, a) }
pub fn y (a: A) -> Self { Self(Alignment::Y, a) }
pub fn n (a: A) -> Self { Self(Alignment::N, a) }
pub fn s (a: A) -> Self { Self(Alignment::S, a) }
pub fn e (a: A) -> Self { Self(Alignment::E, a) }
pub fn w (a: A) -> Self { Self(Alignment::W, a) }
pub fn nw (a: A) -> Self { Self(Alignment::NW, a) }
pub fn sw (a: A) -> Self { Self(Alignment::SW, a) }
pub fn ne (a: A) -> Self { Self(Alignment::NE, a) }
pub fn se (a: A) -> Self { Self(Alignment::SE, a) }
#[inline] pub fn c (a: A) -> Self { Self(Alignment::Center, a) }
#[inline] pub fn x (a: A) -> Self { Self(Alignment::X, a) }
#[inline] pub fn y (a: A) -> Self { Self(Alignment::Y, a) }
#[inline] pub fn n (a: A) -> Self { Self(Alignment::N, a) }
#[inline] pub fn s (a: A) -> Self { Self(Alignment::S, a) }
#[inline] pub fn e (a: A) -> Self { Self(Alignment::E, a) }
#[inline] pub fn w (a: A) -> Self { Self(Alignment::W, a) }
#[inline] pub fn nw (a: A) -> Self { Self(Alignment::NW, a) }
#[inline] pub fn sw (a: A) -> Self { Self(Alignment::SW, a) }
#[inline] pub fn ne (a: A) -> Self { Self(Alignment::NE, a) }
#[inline] pub fn se (a: A) -> Self { Self(Alignment::SE, a) }
}
impl<E: Output, A: Content<E>> Content<E> for Align<A> {
fn content (&self) -> impl Render<E> {

View file

@ -55,12 +55,12 @@ try_from_expr!(<'a, E>: Bsp<RenderBox<'a, E>, RenderBox<'a, E>>: |state, iter| {
}
});
impl<A, B> Bsp<A, B> {
pub fn n (a: A, b: B) -> Self { Self(North, a, b) }
pub fn s (a: A, b: B) -> Self { Self(South, a, b) }
pub fn e (a: A, b: B) -> Self { Self(East, a, b) }
pub fn w (a: A, b: B) -> Self { Self(West, a, b) }
pub fn a (a: A, b: B) -> Self { Self(Above, a, b) }
pub fn b (a: A, b: B) -> Self { Self(Below, a, b) }
#[inline] pub fn n (a: A, b: B) -> Self { Self(North, a, b) }
#[inline] pub fn s (a: A, b: B) -> Self { Self(South, a, b) }
#[inline] pub fn e (a: A, b: B) -> Self { Self(East, a, b) }
#[inline] pub fn w (a: A, b: B) -> Self { Self(West, a, b) }
#[inline] pub fn a (a: A, b: B) -> Self { Self(Above, a, b) }
#[inline] pub fn b (a: A, b: B) -> Self { Self(Below, a, b) }
}
pub trait BspAreas<E: Output, A: Content<E>, B: Content<E>> {
fn direction (&self) -> Direction;

View file

@ -1,10 +1,10 @@
use crate::*;
/// Show an item only when a condition is true.
pub struct When<A>(pub bool, pub A);
impl<A> When<A> { pub fn new (c: bool, a: A) -> Self { Self(c, a) } }
impl<A> When<A> { #[inline] pub fn new (c: bool, a: A) -> Self { Self(c, a) } }
/// Show one item if a condition is true and another if the condition is false
pub struct Either<A, B>(pub bool, pub A, pub B);
impl<A, B> Either<A, B> { pub fn new (c: bool, a: A, b: B) -> Self { Self(c, a, b) } }
impl<A, B> Either<A, B> { #[inline] pub fn new (c: bool, a: A, b: B) -> Self { Self(c, a, b) } }
try_from_expr!(<'a, E>: When<RenderBox<'a, E>>: |state, iter| {
if let Some(Token { value: Value::Key("when"), .. }) = iter.peek() {
let _ = iter.next().unwrap();

View file

@ -1,5 +1,5 @@
use crate::*;
pub fn map_south<O: Output>(
#[inline] pub fn map_south<O: Output>(
item_offset: O::Unit,
item_height: O::Unit,
item: impl Content<O>
@ -7,7 +7,7 @@ pub fn map_south<O: Output>(
Push::y(item_offset, Fixed::y(item_height, Fill::x(item)))
}
pub fn map_south_west<O: Output>(
#[inline] pub fn map_south_west<O: Output>(
item_offset: O::Unit,
item_height: O::Unit,
item: impl Content<O>
@ -15,7 +15,7 @@ pub fn map_south_west<O: Output>(
Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item))))
}
pub fn map_east<O: Output>(
#[inline] pub fn map_east<O: Output>(
item_offset: O::Unit,
item_width: O::Unit,
item: impl Content<O>

View file

@ -25,9 +25,9 @@ macro_rules! transform_xy {
($x:literal $y:literal $xy:literal |$self:ident : $Enum:ident, $to:ident|$area:expr) => {
pub enum $Enum<T> { X(T), Y(T), XY(T) }
impl<T> $Enum<T> {
pub fn x (item: T) -> Self { Self::X(item) }
pub fn y (item: T) -> Self { Self::Y(item) }
pub fn xy (item: T) -> Self { Self::XY(item) }
#[inline] pub fn x (item: T) -> Self { Self::X(item) }
#[inline] pub fn y (item: T) -> Self { Self::Y(item) }
#[inline] pub fn xy (item: T) -> Self { Self::XY(item) }
}
impl<'a, E: Output + 'a, T: ViewContext<'a, E>> TryFromAtom<'a, T>
for $Enum<RenderBox<'a, E>> {
@ -71,9 +71,9 @@ macro_rules! transform_xy_unit {
($x:literal $y:literal $xy:literal |$self:ident : $Enum:ident, $to:ident|$layout:expr) => {
pub enum $Enum<U, T> { X(U, T), Y(U, T), XY(U, U, T), }
impl<U, T> $Enum<U, T> {
pub fn x (x: U, item: T) -> Self { Self::X(x, item) }
pub fn y (y: U, item: T) -> Self { Self::Y(y, item) }
pub fn xy (x: U, y: U, item: T) -> Self { Self::XY(x, y, item) }
#[inline] pub fn x (x: U, item: T) -> Self { Self::X(x, item) }
#[inline] pub fn y (y: U, item: T) -> Self { Self::Y(y, item) }
#[inline] pub fn xy (x: U, y: U, item: T) -> Self { Self::XY(x, y, item) }
}
impl<'a, E: Output + 'a, T: ViewContext<'a, E>> TryFromAtom<'a, T>
for $Enum<E::Unit, RenderBox<'a, E>> {
@ -118,12 +118,12 @@ macro_rules! transform_xy_unit {
}
}
impl<U: Copy + Coordinate, T> $Enum<U, T> {
pub fn dx (&self) -> U {
#[inline] pub fn dx (&self) -> U {
match self {
Self::X(x, _) => *x, Self::Y(_, _) => 0.into(), Self::XY(x, _, _) => *x,
}
}
pub fn dy (&self) -> U {
#[inline] pub fn dy (&self) -> U {
match self {
Self::X(_, _) => 0.into(), Self::Y(y, _) => *y, Self::XY(_, y, _) => *y,
}

82
tek/src/arranger.edn Normal file
View file

@ -0,0 +1,82 @@
This is the unified Tek Arranger.
Its appearance is defined by the following view definition:
{def :view (bsp/s (fixed/y 2 :toolbar)
(fill/x (align/c (bsp/w (fixed/x :pool-w :pool)
(bsp/n (fixed/y 3 :outputs)
(bsp/n (fixed/y 3 :inputs)
(bsp/n (fixed/y 3 :tracks) :scenes)))))))}
The arranger's behavior is controlled by the
following keymaps:
{def :keys
(@u undo 1)
(@shift-u redo 1)
(@space clock toggle)
(@shift-space clock toggle 0)
(@ctrl-a scene add)
(@ctrl-t track add)
(@tab edit)
(@c color)}
{def :keys-mix
(@down select 0 1)
(@s select 0 1)
(@right select 1 0)
(@d select 1 0)}
{def :keys-track
(@left select :track-prev :scene)
(@a select :track-prev :scene)
(@right select :track-next :scene)
(@d select :track-next :scene)
(@down select :track :scene-next)
(@s select :track :scene-next)
(@q track launch)
(@c track color :track)
(@comma track swap-prev)
(@period track swap-next)
(@lt track size-dec)
(@gt track size-inc)
(@delete track delete)}
{def :keys-scene
(@up select :track :scene-prev)
(@w select :track :scene-prev)
(@down select :track :scene-next)
(@s select :track :scene-next)
(@right select :track-next :scene)
(@d select :track-next :scene)
(@q scene launch)
(@c scene color :scene)
(@comma scene swap-prev)
(@period scene swap-next)
(@lt scene size-dec)
(@gt scene size-inc)
(@delete scene delete)}
{def :keys-clip
(@up select :track :scene-prev)
(@w select :track :scene-prev)
(@down select :track :scene-next)
(@s select :track :scene-next)
(@left select :track-prev :scene)
(@a select :track-prev :scene)
(@right select :track-next :scene)
(@d select :track-next :scene)
(@q enqueue :clip)
(@c clip color :track :scene)
(@g clip get)
(@p clip put)
(@delete clip del)
(@comma clip prev)
(@period clip next)
(@lt clip swap-prev)
(@gt clip swap-next)
(@l clip loop-toggle)}

View file

@ -380,13 +380,10 @@ impl Tek {
let time = ||now.map(|now|format!("{:.3}s", now/1000000.))
.unwrap_or("-.---s".into());
let bpm = ||format!("{:.3}", clock.timebase.bpm.get());
let theme = ItemPalette::G[128];
Either::new(compact,
row!(Field(Tui::g(128).into(), "BPM", bpm()),
Field(Tui::g(128).into(), "Beat", beat()),
Field(Tui::g(128).into(), "Time", time())),
row!(FieldV(Tui::g(128).into(), "BPM", bpm()),
FieldV(Tui::g(128).into(), "Beat", beat()),
FieldV(Tui::g(128).into(), "Time", time())))
row!(Field(theme, "BPM", bpm()), Field(theme, "Beat", beat()), Field(theme, "Time", time())),
row!(FieldV(theme, "BPM", bpm()), FieldV(theme, "Beat", beat()), FieldV(theme, "Time", time())))
}
fn view_engine_stats (&self) -> impl Content<TuiOut> + use<'_> {
let compact = self.size.w() > 80;
@ -396,17 +393,14 @@ impl Tek {
let sr = move||format!("{}", if compact {format!("{:.1}kHz", rate / 1000.)} else {format!("{:.0}Hz", rate)});
let buf = move||format!("{chunk}");
let latency = move||format!("{:.1}ms", chunk as f64 / rate * 1000.);
let theme = ItemPalette::G[128];
Either::new(compact,
row!(Field(Tui::g(128).into(), "SR", sr()),
Field(Tui::g(128).into(), "Buf", buf()),
Field(Tui::g(128).into(), "Lat", latency())),
row!(FieldV(Tui::g(128).into(), "SR", sr()),
FieldV(Tui::g(128).into(), "Buf", buf()),
FieldV(Tui::g(128).into(), "Lat", latency())))
row!(Field(theme, "SR", sr()), Field(theme, "Buf", buf()), Field(theme, "Lat", latency())),
row!(FieldV(theme, "SR", sr()), FieldV(theme, "Buf", buf()), FieldV(theme, "Lat", latency())))
}
fn view_meter <'a> (&'a self, label: &'a str, value: f32) -> impl Content<TuiOut> + 'a {
col!(
Field(Tui::g(128).into(), label, format!("{:>+9.3}", value)),
Field(ItemPalette::G[128], label, format!("{:>+9.3}", value)),
Fixed::xy(if value >= 0.0 { 13 }
else if value >= -1.0 { 12 }
else if value >= -2.0 { 11 }
@ -507,7 +501,7 @@ impl Tek {
let c = c.read().unwrap();
(c.name.to_string(), c.color.lightest.rgb, c.color)
} else {
("".to_string(), Tui::g(64), Tui::g(32).into())
("".to_string(), Tui::g(64), ItemPalette::G[32])
};
let same_track = selected_track == Some(t+1);
let selected = same_track && Some(s+1) == selected_scene;

View file

@ -90,8 +90,8 @@ impl ItemColor {
impl ItemPalette {
pub const G: [Self;256] = {
let mut builder = konst::array::ArrayBuilder::new();
let mut index = 0;
while !builder.is_full() {
let index = builder.len() as u8;
let light = (index as f64 * 1.3) as u8;
let lighter = (index as f64 * 1.6) as u8;
let lightest = (index as f64 * 1.9) as u8;
@ -107,7 +107,6 @@ impl ItemPalette {
darker: ItemColor::from_rgb(Color::Rgb(darker, darker, darker, )),
darkest: ItemColor::from_rgb(Color::Rgb(darkest, darkest, darkest, )),
});
index += 1;
}
builder.build()
};