wip: launcher scenes

This commit is contained in:
🪞👃🪞 2024-06-25 00:18:15 +03:00
parent 90998b1c6e
commit 143da7f1b8

View file

@ -5,7 +5,7 @@ pub struct Launcher {
cursor: (usize, usize), cursor: (usize, usize),
tracks: Vec<DynamicDevice<Sequencer>>, tracks: Vec<DynamicDevice<Sequencer>>,
chains: Vec<DynamicDevice<Chain>>, chains: Vec<DynamicDevice<Chain>>,
rows: usize, scenes: Vec<Scene>,
show_help: bool, show_help: bool,
view: LauncherView, view: LauncherView,
} }
@ -14,6 +14,18 @@ pub enum LauncherView {
Sequencer, Sequencer,
Chains Chains
} }
pub struct Scene {
name: String,
clips: Vec<Option<usize>>,
}
impl Scene {
pub fn new (name: impl AsRef<str>, clips: impl AsRef<[Option<usize>]>) -> Self {
Self {
name: name.as_ref().into(),
clips: clips.as_ref().iter().map(|x|x.clone()).collect()
}
}
}
impl Launcher { impl Launcher {
pub fn new ( pub fn new (
name: &str, name: &str,
@ -23,8 +35,17 @@ impl Launcher {
name: name.into(), name: name.into(),
view: LauncherView::Tracks, view: LauncherView::Tracks,
timebase: timebase.clone(), timebase: timebase.clone(),
cursor: (0, 0), cursor: (1, 2),
rows: 8, scenes: vec![
Scene::new(&"Scene#01", &[Some(0), None, None, None]),
Scene::new(&"Scene#02", &[None, None, None, None]),
Scene::new(&"Scene#03", &[None, None, None, None]),
Scene::new(&"Scene#04", &[None, None, None, None]),
Scene::new(&"Scene#05", &[None, None, None, None]),
Scene::new(&"Scene#06", &[None, None, None, None]),
Scene::new(&"Scene#07", &[None, None, None, None]),
Scene::new(&"Scene#08", &[None, None, None, None]),
],
tracks: vec![ tracks: vec![
Sequencer::new("Drum", timebase)?, Sequencer::new("Drum", timebase)?,
Sequencer::new("Bass", timebase)?, Sequencer::new("Bass", timebase)?,
@ -69,7 +90,7 @@ impl Launcher {
} }
} }
fn rows (&self) -> usize { fn rows (&self) -> usize {
(self.rows + 2) as usize (self.scenes.len() + 2) as usize
} }
fn row (&self) -> usize { fn row (&self) -> usize {
self.cursor.1 as usize self.cursor.1 as usize
@ -137,28 +158,26 @@ pub fn render (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usually<Rect>
} }
Ok(area) Ok(area)
} }
fn draw_scenes ( fn draw_scenes (
state: &Launcher, buf: &mut Buffer, x: u16, y: u16, state: &Launcher, buf: &mut Buffer, x: u16, y: u16,
) -> Rect { ) -> Rect {
let style = Style::default().not_dim().bold(); let style = Style::default().not_dim().bold();
let row = state.row() as u16; let row = state.row() as u16;
let col = state.col() as u16; let col = state.col() as u16;
let green = |r: u16, c: u16| if row == r && col == c {
Style::default().green()
} else {
Style::default()
};
let mut width = 8u16; let mut width = 8u16;
let mut height = 6u16; let mut height = 6u16;
format!("{} | ", state.name).blit(buf, x+2, y+1, Some( format!("{} | ", state.name).blit(buf, x+2, y+1, Some(green(0, 0)));
if row == 0 && col == 0 { Style::default().green() } else { Style::default() } format!("Sync 1/1").blit(buf, x+2, y+3, Some(green(1, 0)));
)); for (scene_index, scene) in state.scenes.iter().enumerate() {
format!("Sync 1/1").blit(buf, x+2, y+3, Some( let y = y + 5 + scene_index as u16 * 2;
if row == 1 && col == 0 { Style::default().green() } else { Style::default() } let label = format!("{}", &scene.name);
)); width = width.max(label.len() as u16 + 2);
for j in 0..=7 { label.blit(buf, x + 2, y, Some(green(scene_index as u16 + 2, 0)));
let y = y + 5 + j as u16 * 2;
let label = format!("▶ Scene {j}");
width = width.max(label.len() as u16 + 3);
label.blit(buf, x + 2, y, Some(
if row == j + 2 && col == 0 { Style::default().green() } else { Style::default() }
));
height = height + 2; height = height + 2;
} }
Rect { x, y, width, height } Rect { x, y, width, height }
@ -182,45 +201,52 @@ fn draw_tracks (
fn draw_track ( fn draw_track (
state: &Launcher, buf: &mut Buffer, x: u16, y: u16, i: u16, track: &Sequencer state: &Launcher, buf: &mut Buffer, x: u16, y: u16, i: u16, track: &Sequencer
) -> u16 { ) -> u16 {
let mut width = track.name.len() as u16 + 3; let mut width = 11.max(track.name.len() as u16 + 3);
let row = state.row() as u16; let row = state.row() as u16;
let col = state.col() as u16; let col = state.col() as u16;
track.name.blit(buf, x, y + 1, Some( track.name.blit(buf, x, y + 1, Some(
if row == 0 && col == i + 1 { Style::default().green() } else { Style::default() } if row == 0 && col == i + 1 { Style::default().green() } else { Style::default() }
)); ));
"(global)".blit(buf, x, y + 3, Some( "(global)".blit(buf, x, y + 3, Some(
if row == 1 && col == i + 1 { Style::default().green() } else { Style::default().dim() } if row == 1 && col == i + 1 { Style::default().green() } else { Style::default().dim() }
)); ));
"".blit(buf, x - 2, y + 3, Some( "".blit(buf, x - 2, y + 3, Some(
Style::default().dim() Style::default().dim()
)); ));
let green = |r: u16, c: u16| if row == r && col == c {
for j in 0..=7 { Style::default().green()
let y = y + 5 + j as u16 * 2; } else {
if let Some(sequence) = track.sequences.get(j) { Style::default()
let label = format!("{}", &sequence.name); };
width = width.max(label.len() as u16 + 1); for (scene_index, scene) in state.scenes.iter().enumerate() {
let style = if j + 2 == row as usize && i + 1 == col { let y = y + 5 + scene_index as u16 * 2;
Style::default().green().bold() //let label = format!("▶ {}", &scene.name);
} else { //width = width.max(label.len() as u16 + 2);
Style::default() //label.blit(buf, x + 2, y, Some(green(scene_index as u16 + 2, 0)));
}; //height = height + 2;
buf.set_string(x - 0, y + 0, &label, style); let style = if scene_index + 2 == row as usize && i + 1 == col {
buf.set_string(x - 2, y + 0, &"", style.dim()); Style::default().green().bold()
buf.set_string(x - 2, y + 1, &"", style.dim());
buf.set_string(x + width - 2, y + 0, &"", style.dim());
buf.set_string(x + width - 2, y + 1, &"", style.dim());
} else { } else {
buf.set_string(x - 2, y as u16, Style::default().dim()
format!("{}", &"·".repeat(track.name.len())), };
Style::default().dim() if let Some(Some(sequence_index)) = scene.clips.get(i as usize) {
); if let Some(sequence) = track.sequences.get(*sequence_index) {
let label = format!("{}", &sequence.name);
width = width.max(label.len() as u16 + 1);
label.blit(buf, x, y, Some(style));
} else {
format!("{}", &"?".repeat(track.name.len()))
.blit(buf, x - 2, y as u16, Some(Style::default().dim()));
}
} else {
"····".blit(buf, x, y, Some(style.dim()));
} }
let style = Some(style.dim());
"".blit(buf, x - 2, y + 0, style);
"".blit(buf, x - 2, y + 1, style);
"".blit(buf, x + width - 2, y + 0, style);
"".blit(buf, x + width - 2, y + 1, style);
} }
width width
} }
fn draw_crossings (state: &Launcher, buf: &mut Buffer, x: u16, y: u16) { fn draw_crossings (state: &Launcher, buf: &mut Buffer, x: u16, y: u16) {
@ -282,10 +308,12 @@ pub const KEYMAP: &'static [KeyBinding<Launcher>] = keymap!(Launcher {
[Tab, NONE, "focus_next", "focus next area", focus_next], [Tab, NONE, "focus_next", "focus next area", focus_next],
}); });
pub const KEYMAP_TRACKS: &'static [KeyBinding<Launcher>] = keymap!(Launcher { pub const KEYMAP_TRACKS: &'static [KeyBinding<Launcher>] = keymap!(Launcher {
[Up, NONE, "cursor_up", "move cursor up", cursor_up], [Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down], [Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Left, NONE, "cursor_left", "move cursor left", cursor_left], [Left, NONE, "cursor_left", "move cursor left", cursor_left],
[Right, NONE, "cursor_right", "move cursor right", cursor_right], [Right, NONE, "cursor_right", "move cursor right", cursor_right],
[Char('.'), NONE, "clip_next", "set clip to next phrase", clip_next],
[Char(','), NONE, "clip_next", "set clip to last phrase", clip_prev],
}); });
fn rename (_: &mut Launcher) -> Usually<bool> { fn rename (_: &mut Launcher) -> Usually<bool> {
Ok(true) Ok(true)
@ -326,3 +354,35 @@ fn focus_prev (state: &mut Launcher) -> Usually<bool> {
}; };
Ok(true) Ok(true)
} }
fn clip_next (state: &mut Launcher) -> Usually<bool> {
if state.cursor.0 >= 1 && state.cursor.1 >= 2 {
let scene_id = state.cursor.1 - 2;
let clip_id = state.cursor.0 - 1;
let scene = &mut state.scenes[scene_id];
scene.clips[clip_id] = match scene.clips[clip_id] {
None => Some(0),
Some(i) => if i >= state.tracks[clip_id].state().sequences.len().saturating_sub(1) {
None
} else {
Some(i + 1)
}
};
}
Ok(true)
}
fn clip_prev (state: &mut Launcher) -> Usually<bool> {
if state.cursor.0 >= 1 && state.cursor.1 >= 2 {
let scene_id = state.cursor.1 - 2;
let clip_id = state.cursor.0 - 1;
let scene = &mut state.scenes[scene_id];
scene.clips[clip_id] = match scene.clips[clip_id] {
None => Some(state.tracks[clip_id].state().sequences.len().saturating_sub(1)),
Some(i) => if i == 0 {
None
} else {
Some(i - 1)
}
};
}
Ok(true)
}