mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-01-12 02:56:42 +01:00
sweeeeping sweep
This commit is contained in:
parent
c9b09b7dea
commit
e677d1d7d4
38 changed files with 766 additions and 691 deletions
|
|
@ -7,7 +7,7 @@ pub enum ArrangerMode {
|
|||
/// Tracks are rows
|
||||
H,
|
||||
}
|
||||
render!(<Tui>|self: ArrangerMode|"");
|
||||
impl<E: Engine> Content<E> for ArrangerMode {}
|
||||
/// Arranger display mode can be cycled
|
||||
impl ArrangerMode {
|
||||
/// Cycle arranger display mode
|
||||
|
|
|
|||
|
|
@ -7,39 +7,42 @@ pub struct ArrangerVClips<'a> {
|
|||
tracks: &'a Vec<ArrangerTrack>,
|
||||
rows: Vec<(usize, usize)>,
|
||||
}
|
||||
|
||||
from!(<'a>|args:(&'a ArrangerTui, usize)|ArrangerVClips<'a> = Self {
|
||||
size: &args.0.size,
|
||||
scenes: &args.0.scenes,
|
||||
tracks: &args.0.tracks,
|
||||
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
|
||||
});
|
||||
|
||||
render!(<Tui>|self: ArrangerVClips<'a>|Fill::xy(
|
||||
col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => {
|
||||
Self::format_scene(self.tracks, scene, pulses)
|
||||
})
|
||||
));
|
||||
|
||||
impl<'a> ArrangerVClips<'a> {
|
||||
pub fn new (state: &'a ArrangerTui, zoom: usize) -> Self {
|
||||
Self {
|
||||
size: &state.size,
|
||||
tracks: &state.tracks,
|
||||
scenes: &state.scenes,
|
||||
rows: ArrangerScene::ppqs(&state.scenes, zoom),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, E: Engine> Content<E> for ArrangerVClips<'a> {
|
||||
fn content (&self) -> Option<impl Content<E>> {
|
||||
let iter = self.scenes.iter().zip(self.rows.iter().map(|row|row.0));
|
||||
let col = col_iter!(iter => |(scene, pulses)|Self::format_scene(self.tracks, scene, pulses));
|
||||
Some(Fill::xy(col))
|
||||
}
|
||||
}
|
||||
impl<'a> ArrangerVClips<'a> {
|
||||
|
||||
fn format_scene (
|
||||
tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, pulses: usize
|
||||
) -> impl Render<Tui> + use<'a> {
|
||||
) -> impl Content<Tui> + use<'a> {
|
||||
let height = 1.max((pulses / PPQ) as u16);
|
||||
let playing = scene.is_playing(tracks);
|
||||
Fixed::y(height, row!([
|
||||
Fixed::y(height, row!(
|
||||
Tui::bg(scene.color.base.rgb,
|
||||
if playing { "▶ " } else { " " }),
|
||||
Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb,
|
||||
Expand::x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))),
|
||||
row!((index, track, x1, x2) in ArrangerTrack::with_widths(tracks) => {
|
||||
row_iter!((index, track, x1, x2) in ArrangerTrack::with_widths(tracks) => {
|
||||
Self::format_clip(scene, index, track, (x2 - x1) as u16, height)
|
||||
})])
|
||||
)
|
||||
}
|
||||
})))}
|
||||
|
||||
fn format_clip (
|
||||
scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16
|
||||
) -> impl Render<Tui> + use<'a> {
|
||||
) -> impl Content<Tui> + use<'a> {
|
||||
Fixed::xy(w, h, Layers::new(move |add|{
|
||||
if let Some(Some(phrase)) = scene.clips.get(index) {
|
||||
let mut bg = TuiTheme::border_bg();
|
||||
|
|
|
|||
|
|
@ -24,11 +24,9 @@ from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
|
|||
sub_modifier: Modifier::DIM
|
||||
}),
|
||||
});
|
||||
|
||||
render!(<Tui>(self: ArrangerVCursor)
|
||||
|layout|Ok(Some([0, 0])),
|
||||
|render|{
|
||||
let area = render.area();
|
||||
impl Content<Tui> for ArrangerVCursor {
|
||||
fn render (&self, to: &mut TuiOutput) {
|
||||
let area = to.area();
|
||||
let focused = true;
|
||||
let selected = self.selected;
|
||||
let get_track_area = |t: usize| [
|
||||
|
|
@ -67,17 +65,18 @@ render!(<Tui>(self: ArrangerVCursor)
|
|||
};
|
||||
let bg = self.color.lighter.rgb;//Color::Rgb(0, 255, 0);
|
||||
if let Some([x, y, width, height]) = track_area {
|
||||
render.fill_fg([x, y, 1, height], bg);
|
||||
render.fill_fg([x + width, y, 1, height], bg);
|
||||
to.fill_fg([x, y, 1, height], bg);
|
||||
to.fill_fg([x + width, y, 1, height], bg);
|
||||
}
|
||||
if let Some([_, y, _, height]) = scene_area {
|
||||
render.fill_ul([area.x(), y - 1, area.w(), 1], bg);
|
||||
render.fill_ul([area.x(), y + height - 1, area.w(), 1], bg);
|
||||
to.fill_ul([area.x(), y - 1, area.w(), 1], bg);
|
||||
to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg);
|
||||
}
|
||||
Ok(if focused {
|
||||
render.render_in(if let Some(clip_area) = clip_area { clip_area }
|
||||
to.render_in(if let Some(clip_area) = clip_area { clip_area }
|
||||
else if let Some(track_area) = track_area { track_area.clip_h(HEADER_H) }
|
||||
else if let Some(scene_area) = scene_area { scene_area.clip_w(self.scenes_w) }
|
||||
else { area.clip_w(self.scenes_w).clip_h(HEADER_H) }, &self.reticle)?
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,44 +15,48 @@ from!(<'a>|state: &'a ArrangerTui|ArrangerVHead<'a> = Self { // A
|
|||
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
|
||||
});
|
||||
|
||||
render!(<Tui>|self: ArrangerVHead<'a>|Push::x(self.scenes_w, row!(
|
||||
(_, track, x1, x2) in ArrangerTrack::with_widths(self.tracks) => {
|
||||
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
|
||||
let color = track.color();
|
||||
fn row <T: Render<Tui>> (color: ItemPalette, field: &T) -> impl Render<Tui> + use<'_, T> {
|
||||
row!([
|
||||
Tui::fg(color.light.rgb, "▎"),
|
||||
Tui::fg(color.lightest.rgb, field)
|
||||
])
|
||||
impl Content<Tui> for ArrangerVCursor {
|
||||
fn content (&self) -> Option<impl Content<Tui>> {
|
||||
|
||||
fn row <T: Content<Tui>> (color: ItemPalette, field: &T) -> impl Content<Tui> + use<'_, T> {
|
||||
row!([Tui::fg(color.light.rgb, "▎"), Tui::fg(color.lightest.rgb, field)])
|
||||
}
|
||||
Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, col!([
|
||||
row(color, &Self::format_name(track, w)),
|
||||
row(color, &Self::format_input(track)?),
|
||||
row(color, &Self::format_output(track)?),
|
||||
row(color, &Self::format_elapsed(track, self.timebase)),
|
||||
row(color, &Self::format_until_next(track, self.current)),
|
||||
]))))
|
||||
|
||||
Some(Push::x(self.scenes_w, row_iter!(
|
||||
(_0, track, x1, x2) in ArrangerTrack::with_widths(self.tracks) => {
|
||||
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
|
||||
let color = track.color();
|
||||
Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, col!([
|
||||
row(color, &Self::format_name(track, w)),
|
||||
row(color, &Self::format_input(track)?),
|
||||
row(color, &Self::format_output(track)?),
|
||||
row(color, &Self::format_elapsed(track, self.timebase)),
|
||||
row(color, &Self::format_until_next(track, self.current)),
|
||||
]))))
|
||||
}
|
||||
)))
|
||||
|
||||
}
|
||||
)));
|
||||
}
|
||||
|
||||
impl ArrangerVHead<'_> {
|
||||
/// name and width of track
|
||||
fn format_name (track: &ArrangerTrack, _w: usize) -> impl Render<Tui> {
|
||||
fn format_name (track: &ArrangerTrack, _w: usize) -> impl Content<Tui> {
|
||||
let name = track.name().read().unwrap().clone();
|
||||
Tui::bold(true, Tui::fg(track.color.lightest.rgb, name))
|
||||
}
|
||||
/// input port
|
||||
fn format_input (track: &ArrangerTrack) -> Usually<impl Render<Tui>> {
|
||||
fn format_input (track: &ArrangerTrack) -> Usually<impl Content<Tui>> {
|
||||
Ok(format!(">{}", track.player.midi_ins().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
/// output port
|
||||
fn format_output (track: &ArrangerTrack) -> Usually<impl Render<Tui>> {
|
||||
fn format_output (track: &ArrangerTrack) -> Usually<impl Content<Tui>> {
|
||||
Ok(format!("<{}", track.player.midi_outs().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
/// beats elapsed
|
||||
fn format_elapsed (track: &ArrangerTrack, timebase: &Arc<Timebase>) -> impl Render<Tui> {
|
||||
fn format_elapsed (track: &ArrangerTrack, timebase: &Arc<Timebase>) -> impl Content<Tui> {
|
||||
let mut result = String::new();
|
||||
if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() {
|
||||
let length = phrase.read().unwrap().length;
|
||||
|
|
@ -66,7 +70,7 @@ impl ArrangerVHead<'_> {
|
|||
}
|
||||
/// beats until switchover
|
||||
fn format_until_next (track: &ArrangerTrack, current: &Arc<Moment>)
|
||||
-> Option<impl Render<Tui>>
|
||||
-> Option<impl Content<Tui>>
|
||||
{
|
||||
let timebase = ¤t.timebase;
|
||||
let mut result = String::new();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from!(<'a>|args: &'a ArrangerTui|ArrangerVIns<'a> = Self {
|
|||
tracks: &args.tracks,
|
||||
});
|
||||
|
||||
render!(<Tui>|self: ArrangerVIns<'a>|"");
|
||||
render!(Tui: (self: ArrangerVIns<'a>) => "");
|
||||
|
||||
pub struct ArrangerVOuts<'a> {
|
||||
size: &'a Measure<Tui>,
|
||||
|
|
@ -23,4 +23,4 @@ from!(<'a>|args: &'a ArrangerTui|ArrangerVOuts<'a> = Self {
|
|||
tracks: &args.tracks,
|
||||
});
|
||||
|
||||
render!(<Tui>|self: ArrangerVOuts<'a>|"");
|
||||
render!(Tui: (self: ArrangerVOuts<'a>) => "");
|
||||
|
|
|
|||
|
|
@ -11,17 +11,15 @@ from!(|state:&ArrangerTui|ArrangerVColSep = Self {
|
|||
cols: ArrangerTrack::widths(&state.tracks),
|
||||
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
|
||||
});
|
||||
render!(<Tui>(self: ArrangerVColSep)
|
||||
|layout|Ok(Some([0, 0])),
|
||||
|render|{
|
||||
let style = Some(Style::default().fg(self.fg));
|
||||
Ok(for x in self.cols.iter().map(|col|col.1) {
|
||||
let x = self.scenes_w + render.area().x() + x as u16;
|
||||
for y in render.area().y()..render.area().y2() {
|
||||
render.blit(&"▎", x, y, style);
|
||||
}
|
||||
})
|
||||
});
|
||||
render!(Tui: |self: ArrangerVColSep, to| {
|
||||
let style = Some(Style::default().fg(self.fg));
|
||||
Ok(for x in self.cols.iter().map(|col|col.1) {
|
||||
let x = self.scenes_w + to.area().x() + x as u16;
|
||||
for y in to.area().y()..to.area().y2() {
|
||||
to.blit(&"▎", x, y, style);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
pub struct ArrangerVRowSep {
|
||||
fg: Color,
|
||||
|
|
@ -31,16 +29,14 @@ from!(|args:(&ArrangerTui, usize)|ArrangerVRowSep = Self {
|
|||
fg: TuiTheme::separator_fg(false),
|
||||
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
|
||||
});
|
||||
render!(<Tui>(self: ArrangerVRowSep)
|
||||
|layout|Ok(Some([0, 0])),
|
||||
|render|Ok(for y in self.rows.iter().map(|row|row.1) {
|
||||
let y = render.area().y() + (y / PPQ) as u16 + 1;
|
||||
if y >= render.buffer.area.height { break }
|
||||
for x in render.area().x()..render.area().x2().saturating_sub(2) {
|
||||
if x < render.buffer.area.x && y < render.buffer.area.y {
|
||||
let cell = render.buffer.get_mut(x, y);
|
||||
cell.modifier = Modifier::UNDERLINED;
|
||||
cell.underline_color = self.fg;
|
||||
}
|
||||
render!(Tui: |self: ArrangerVRowSep, to|for y in self.rows.iter().map(|row|row.1) {
|
||||
let y = to.area().y() + (y / PPQ) as u16 + 1;
|
||||
if y >= to.buffer.area.height { break }
|
||||
for x in to.area().x()..to.area().x2().saturating_sub(2) {
|
||||
if x < to.buffer.area.x && y < to.buffer.area.y {
|
||||
let cell = to.buffer.get_mut(x, y);
|
||||
cell.modifier = Modifier::UNDERLINED;
|
||||
cell.underline_color = self.fg;
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue