wip: new old arranger scenes
Some checks are pending
/ build (push) Waiting to run

This commit is contained in:
🪞👃🪞 2025-05-15 23:06:15 +03:00
parent 4ba88bfd6d
commit 9aeb792f7d
6 changed files with 197 additions and 176 deletions

View file

@ -1,5 +1,156 @@
use crate::*;
pub type SceneWith<'a, T: Send + Sync> = (usize, &'a Scene, usize, usize, T);
pub trait ArrangerSceneRows: Send + Sync {
/// Default scene height.
const H_SCENE: usize = 2;
/// Default editor height.
const H_EDITOR: usize = 15;
/// Render scenes with clips
fn scenes_view <'a> (&'a self, editor: &'a Option<MidiEditor>) -> impl Content<TuiOut> + 'a {
Tryptich::center(self.scenes_height())
.left(self.width_side(), self.scenes_names())
.middle(self.width_mid(), self.scenes_clips(editor))
}
fn is_editing (&self) -> bool;
fn arrangement (&self) -> &Arrangement;
fn scene_last (&self) -> usize;
fn scene_selected (&self) -> Option<usize>;
fn track_selected (&self) -> Option<usize>;
fn scenes_height (&self) -> u16;
fn width_side (&self) -> u16;
fn width_mid (&self) -> u16;
fn scenes_names (&self) -> impl Content<TuiOut> {
Map::new(move||self.scenes_with_prev_color(),
move|(s, scene, y1, y2, previous): SceneWith<'_, Option<ItemTheme>>, _|{
let height = (1 + y2 - y1) as u16;
let name = Some(scene.name.clone());
let content = Fill::x(Align::w(Tui::bold(true, Bsp::e("", name))));
let selected = self.scene_selected() == Some(s);
let neighbor = s > 0 && self.scene_selected() == Some(s - 1);
let is_last = self.scene_last() == s;
let theme = scene.color;
let fg = theme.lightest.rgb;
let bg = if selected { theme.light } else { theme.base }.rgb;
let hi = if let Some(previous) = previous {
if neighbor { previous.light.rgb } else { previous.base.rgb }
} else {
Reset
};
let lo = if is_last { Reset } else if selected {
theme.light.rgb
} else {
theme.base.rgb
};
Fill::x(map_south(y1 as u16, height, Fixed::y(height, Phat {
width: 0, height: 0, content, colors: [fg, bg, hi, lo]
})))
})
}
fn scenes_with_prev_color (&self) -> impl Iterator<Item=SceneWith<Option<ItemTheme>>> + Send + Sync {
self.scenes_iter().map(|(s, scene, y1, y2)|(s, scene, y1, y2,
(s>0).then_some(self.arrangement().scenes()[s-1].color)))
}
fn scenes_clips <'a> (&'a self, editor: &'a Option<MidiEditor>)
-> impl Content<TuiOut> + 'a
{
per_track(||self.tracks_with_sizes_scrolled(),
move|track_index, track|Map::new(move||self.scenes_with_clip(track_index),
move|(s, scene, y1, y2, previous): SceneWith<'_, Option<ItemTheme>>, _|{
let (name, theme) = if let Some(clip) = &scene.clips[track_index] {
let clip = clip.read().unwrap();
(Some(clip.name.clone()), clip.color)
} else {
(None, ItemTheme::G[32])
};
let height = (1 + y2 - y1) as u16;
let content = Fill::x(Align::w(Tui::bold(true, Bsp::e("", name))));
let same_track = self.track_selected() == Some(track_index);
let selected = same_track && self.scene_selected() == Some(s);
let neighbor = same_track && s > 0 && self.scene_selected() == Some(s - 1);
let is_last = self.scene_last() == s;
let fg = theme.lightest.rgb;
let bg = if selected { theme.light } else { theme.base }.rgb;
let hi = if let Some(previous) = previous {
if neighbor {
previous.light.rgb
} else {
previous.base.rgb
}
} else {
Reset
};
let lo = if is_last {
Reset
} else if selected {
theme.light.rgb
} else {
theme.base.rgb
};
map_south(y1 as u16, height, Bsp::b(Fixed::y(height, Phat {
width: 0, height: 0, content, colors: [fg, bg, hi, lo]
}), When(
self.is_editing() && same_track && self.scene_selected() == Some(s),
editor
)))
}))
}
fn scenes_with_clip (&self, track_index: usize) -> impl Iterator<Item=SceneWith<'_, Option<ItemTheme>>> + Send + Sync {
self.scenes_iter().map(move|(s, scene, y1, y2)|(s, scene, y1, y2,
(s>0).then_some(self.arrangement().scenes()[s-1].clips[track_index].as_ref()
.map(|c|c.read().unwrap().color)
.unwrap_or(ItemTheme::G[32]))))
}
/// A scene with size and color.
fn scenes_iter (&self) -> impl Iterator<Item=(usize, &Scene, usize, usize,)> + Send + Sync {
let selection = Has::<Selection>::get(self.arrangement());
self.arrangement().scenes_with_sizes(
self.is_editing(),
Self::H_SCENE, Self::H_EDITOR,
selection.track(), selection.scene(),
).map_while(|(s, scene, y1, y2)|(y2<=self.scenes_height() as usize)
.then_some((s, scene, y1, y2)))
}
fn tracks_with_sizes_scrolled <'t> (&'t self) -> impl TracksSizes<'t> {
self.arrangement()
.tracks_with_sizes(
&self.arrangement().selection(),
self.is_editing().then_some(20/*FIXME*/)
)
.map_while(move|(t, track, x1, x2)|{
(self.width_mid() > x2 as u16).then_some((t, track, x1, x2))
})
}
}
impl<'a> ArrangerSceneRows for ArrangerView<'a> {
fn arrangement (&self) -> &Arrangement {
self.arrangement
}
fn scenes_height (&self) -> u16 {
self.scenes_height
}
fn width_side (&self) -> u16 {
self.width_side
}
fn width_mid (&self) -> u16 {
self.width_mid
}
fn scene_selected (&self) -> Option<usize> {
self.arrangement.selection.scene()
}
fn scene_last (&self) -> usize {
self.scene_last
}
fn track_selected (&self) -> Option<usize> {
self.arrangement.selection.track()
}
fn is_editing (&self) -> bool {
self.is_editing
}
}
impl<T: Has<Vec<Scene>> + Send + Sync> HasScenes for T {}
pub trait HasScenes: Has<Vec<Scene>> + Send + Sync {