From c56758b616dcc0cee05cf7fe6377a4dd3fa21ddc Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 22 Oct 2024 21:30:47 +0300 Subject: [PATCH] remove H_KEYS_OFFSET, just use row macro --- crates/tek_core/src/space.rs | 42 +++++++++---------- crates/tek_sequencer/src/arranger.rs | 2 +- crates/tek_sequencer/src/arranger_tui.rs | 8 ++-- crates/tek_sequencer/src/sequencer_tui.rs | 50 +++++++++++------------ 4 files changed, 50 insertions(+), 52 deletions(-) diff --git a/crates/tek_core/src/space.rs b/crates/tek_core/src/space.rs index 7b8ff912..57c93122 100644 --- a/crates/tek_core/src/space.rs +++ b/crates/tek_core/src/space.rs @@ -47,6 +47,8 @@ pub trait Size { #[inline] fn w (&self) -> N { self.x() } #[inline] fn h (&self) -> N { self.y() } #[inline] fn wh (&self) -> [N;2] { [self.x(), self.y()] } + #[inline] fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w.into()), self.h()] } + #[inline] fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h.into())] } #[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> { if self.w() < w || self.h() < h { Err(format!("min {w}x{h}").into()) @@ -67,20 +69,29 @@ impl Size for [N;2] { } pub trait Area: Copy { - fn x (&self) -> N; - fn y (&self) -> N; - fn w (&self) -> N; - fn h (&self) -> N; + fn x (&self) -> N; + fn y (&self) -> N; + fn w (&self) -> N; + fn h (&self) -> N; fn x2 (&self) -> N { self.x() + self.w() } fn y2 (&self) -> N { self.y() + self.h() } - #[inline] fn wh (&self) -> [N;2] { - [self.w(), self.h()] + #[inline] fn wh (&self) -> [N;2] { [self.w(), self.h()] } + #[inline] fn xywh (&self) -> [N;4] { [self.x(), self.y(), self.w(), self.h()] } + #[inline] fn lrtb (&self) -> [N;4] { [self.x(), self.x2(), self.y(), self.y2()] } + #[inline] fn push_x (&self, x: N) -> [N;4] { [self.x() + x, self.y(), self.w(), self.h()] } + #[inline] fn push_y (&self, y: N) -> [N;4] { [self.x(), self.y() + y, self.w(), self.h()] } + #[inline] fn shrink_x (&self, x: N) -> [N;4] { [self.x(), self.y(), self.w() - x, self.h()] } + #[inline] fn shrink_y (&self, y: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h() - y] } + #[inline] fn set_w (&self, w: N) -> [N;4] { [self.x(), self.y(), w, self.h()] } + #[inline] fn set_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), h] } + #[inline] fn clip_h (&self, h: N) -> [N;4] { + [self.x(), self.y(), self.w(), self.h().min(h.into())] } - #[inline] fn xywh (&self) -> [N;4] { - [self.x(), self.y(), self.w(), self.h()] + #[inline] fn clip_w (&self, w: N) -> [N;4] { + [self.x(), self.y(), self.w().min(w.into()), self.h()] } - #[inline] fn lrtb (&self) -> [N;4] { - [self.x(), self.x2(), self.y(), self.y2()] + #[inline] fn clip (&self, wh: impl Size) -> [N;4] { + [self.x(), self.y(), wh.w(), wh.h()] } #[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> { if self.w() < w || self.h() < h { @@ -89,9 +100,6 @@ pub trait Area: Copy { Ok(self) } } - #[inline] fn clip (&self, wh: impl Size) -> [N;4] { - [self.x(), self.y(), wh.w(), wh.h()] - } #[inline] fn split_fixed (&self, direction: Direction, a: N) -> ([N;4],[N;4]) { match direction { Direction::Up => ( @@ -109,14 +117,6 @@ pub trait Area: Copy { _ => todo!(), } } - #[inline] fn push_x (&self, x: N) -> [N;4] { [self.x() + x, self.y(), self.w(), self.h()] } - #[inline] fn push_y (&self, y: N) -> [N;4] { [self.x(), self.y() + y, self.w(), self.h()] } - #[inline] fn shrink_x (&self, x: N) -> [N;4] { [self.x(), self.y(), self.w() - x, self.h()] } - #[inline] fn shrink_y (&self, y: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h() - y] } - #[inline] fn set_w (&self, w: N) -> [N;4] { [self.x(), self.y(), w, self.h()] } - #[inline] fn set_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), h] } - #[inline] fn clip_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h().min(h)] } - #[inline] fn clip_w (&self, w: N) -> [N;4] { [self.x(), self.y(), self.w().min(w), self.h()] } } impl Area for (N, N, N, N) { diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index f799898f..845750c7 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -123,7 +123,7 @@ impl Arranger { transport, arrangement, phrases, - phrases_split: 20, + phrases_split: 20, arrangement_split: 20, }; app.update_focus(); diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 65d53c95..42e5116f 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -32,8 +32,8 @@ impl Content for ArrangerStatusBar { Self::ArrangementScene => "SCENE", Self::ArrangementClip => "CLIP", Self::PhrasePool => "SEQ LIST", - Self::PhraseView => "SEQ VIEW", - Self::PhraseEdit => "SEQ EDIT", + Self::PhraseView => "VIEW SEQ", + Self::PhraseEdit => "EDIT SEQ", }; let mode = TuiStyle::bg(format!(" {label} "), Color::Rgb(150, 160, 90)) .fg(Color::Rgb(0, 0, 0)) @@ -259,13 +259,13 @@ impl<'a> Content for VerticalArranger<'a, Tui> { to.render_in(clip_area, &CORNERS)?; //to.fill_bg(clip_area, Color::Rgb(40, 50, 30)); } else if let Some(track_area) = track_area { - to.render_in(track_area.clip_h(2), &CORNERS)?; + to.render_in(track_area.clip_h(2u16), &CORNERS)?; //to.fill_bg(track_area, Color::Rgb(40, 50, 30)); } else if let Some(scene_area) = scene_area { to.render_in(scene_area.clip_w(offset-1), &CORNERS)?; //to.fill_bg(scene_area, Color::Rgb(40, 50, 30)); } else { - to.render_in(area.clip_w(offset-1).clip_h(2), &CORNERS)?; + to.render_in(area.clip_w(offset-1).clip_h(2u16), &CORNERS)?; } } Ok(()) diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index 6bd548ee..140211f6 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -52,10 +52,9 @@ impl Content for PhraseEditor { let Self { focused, entered, time_axis, note_axis, keys, phrase, buffer, note_len, .. } = self; - let offset = Self::H_KEYS_OFFSET as u16; let color = Color::Rgb(0,255,0); let color = phrase.as_ref().map(|p|p.read().unwrap().color).unwrap_or(color); - let keys = CustomWidget::new(|_|Ok(Some([32u16,0u16])), move|to: &mut TuiOutput|{ + let keys = CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(5))), move|to: &mut TuiOutput|{ if to.area().h() >= 2 { to.buffer_update(to.area().set_w(5), &|cell, x, y|{ let y = y + note_axis.start as u16; @@ -66,11 +65,12 @@ impl Content for PhraseEditor { } Ok(()) }).fill_y(); - let notes = CustomWidget::new(|_|Ok(Some([32u16,4u16])), move|to: &mut TuiOutput|{ - if to.area().h() >= 2 && to.area().w() >= offset { - let area = to.area().push_x(offset).shrink_x(offset); + let notes_bg_null = Color::Rgb(28, 35, 25); + let notes = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{ + if to.area().h() >= 2 { + let area = to.area(); to.buffer_update(area, &move |cell, x, y|{ - cell.set_bg(Color::Rgb(20, 20, 20)); + cell.set_bg(notes_bg_null); let src_x = ((x as usize + time_axis.start) * time_axis.scale) as usize; let src_y = (y as usize + note_axis.start) as usize; if src_x < buffer.width && src_y < buffer.height - 1 { @@ -83,11 +83,11 @@ impl Content for PhraseEditor { } Ok(()) }).fill_x(); - let cursor = CustomWidget::new(|_|Ok(Some([1u16,1u16])), move|to: &mut TuiOutput|{ + let cursor = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{ if *entered { let area = to.area(); if let (Some(time), Some(note)) = (time_axis.point, note_axis.point) { - let x = area.x() + Self::H_KEYS_OFFSET as u16 + time as u16; + let x = area.x() + time as u16; let y = area.y() + 1 + note as u16 / 2; let c = if note % 2 == 0 { "▀" } else { "▄" }; to.blit(&c, x, y, Some(Style::default().fg(color))); @@ -95,22 +95,21 @@ impl Content for PhraseEditor { } Ok(()) }); - let playhead = CustomWidget::new(|_|Ok(Some([32u16,2u16])), move|to: &mut TuiOutput|{ + let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(0,0,0)); + let playhead_active = playhead_inactive.yellow().bold().not_dim(); + let playhead = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{ if let Some(_) = phrase { - let time_0 = time_axis.start; - let time_z = time_axis.scale; - let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length; - let [x, y, width, _] = to.area(); - let x2 = x as usize + Self::H_KEYS_OFFSET; - let x3 = x as usize + width as usize; - for x in x2..x3 { - let step = (time_0 + x2) * time_z; - let next_step = (time_0 + x2 + 1) * time_z; - let mut style = Style::default().fg(Color::Rgb(255,255,255)); - if step <= now && now < next_step { - style = style.yellow().bold().not_dim() - } - to.blit(&"-", x as u16, y, Some(style)); + let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length; + let ScaledAxis { start: first_beat, scale: time_zoom, .. } = time_axis; + for x in 0..10 { + let this_step = (first_beat + 0) * time_zoom; + let next_step = (first_beat + 1) * time_zoom; + let x = to.area().x() + x; + to.blit(&"-", x, to.area.y(), Some(if this_step <= now && now < next_step { + playhead_active + } else { + playhead_active + })); } } Ok(()) @@ -118,7 +117,8 @@ impl Content for PhraseEditor { let border_color = if *focused{Color::Rgb(100, 110, 40)}else{Color::Rgb(70, 80, 50)}; let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)}; let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)); - let piano_roll = lay!(keys, notes, cursor).fill_x(); + let note_area = lay!(notes, cursor, playhead).fill_x(); + let piano_roll = row!(keys, note_area).fill_x(); let content_bg = Color::Rgb(40, 50, 30); let content = piano_roll.bg(content_bg).border(border); let mut upper_left = String::from("Sequencer"); @@ -131,14 +131,12 @@ impl Content for PhraseEditor { } lay!( content, - playhead, TuiStyle::fg(upper_left.to_string(), title_color).push_x(1).align_nw().fill_xy(), TuiStyle::fg(upper_right.to_string(), title_color).pull_x(1).align_ne().fill_xy(), ) } } impl PhraseEditor { - const H_KEYS_OFFSET: usize = 5; pub fn put (&mut self) { if let (Some(phrase), Some(time), Some(note)) = ( &self.phrase,