more color degrees

This commit is contained in:
🪞👃🪞 2024-12-11 19:29:11 +01:00
parent 042d480b67
commit 32e547194a
2 changed files with 49 additions and 69 deletions

View file

@ -11,9 +11,13 @@ pub struct ItemColor {
/// A color in OKHSL and RGB with lighter and darker variants.
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct ItemPalette {
pub base: ItemColor,
pub light: ItemColor,
pub dark: ItemColor,
pub base: ItemColor,
pub light: ItemColor,
pub lighter: ItemColor,
pub lightest: ItemColor,
pub dark: ItemColor,
pub darker: ItemColor,
pub darkest: ItemColor,
}
/// Adds TUI RGB representation to an OKHSL value.
impl From<Okhsl<f32>> for ItemColor {
@ -45,13 +49,34 @@ impl ItemColor {
}
}
impl From<ItemColor> for ItemPalette {
fn from (base: ItemColor) -> Self {
let mut light = base.okhsl.clone();
light.lightness = (light.lightness * 1.15).min(Okhsl::<f32>::max_lightness());
let mut dark = base.okhsl.clone();
dark.lightness = (dark.lightness * 0.85).max(Okhsl::<f32>::min_lightness());
dark.saturation = (dark.saturation * 0.85).max(Okhsl::<f32>::min_saturation());
Self { base, light: light.into(), dark: dark.into() }
let mut light = base.okhsl.clone();
light.lightness = (light.lightness * 1.2).min(Okhsl::<f32>::max_lightness());
let mut lighter = light.clone();
lighter.lightness = (lighter.lightness * 1.2).min(Okhsl::<f32>::max_lightness());
let mut lightest = lighter.clone();
lightest.lightness = (lightest.lightness * 1.2).min(Okhsl::<f32>::max_lightness());
let mut dark = base.okhsl.clone();
dark.lightness = (dark.lightness * 0.75).max(Okhsl::<f32>::min_lightness());
dark.saturation = (dark.saturation * 0.75).max(Okhsl::<f32>::min_saturation());
let mut darker = dark.clone();
darker.lightness = (darker.lightness * 0.66).max(Okhsl::<f32>::min_lightness());
darker.saturation = (darker.saturation * 0.66).max(Okhsl::<f32>::min_saturation());
let mut darkest = darker.clone();
darkest.lightness = (darkest.lightness * 0.50).max(Okhsl::<f32>::min_lightness());
darkest.saturation = (darkest.saturation * 0.50).max(Okhsl::<f32>::min_saturation());
Self {
base,
light: light.into(),
lighter: lighter.into(),
lightest: lightest.into(),
dark: dark.into(),
darker: darker.into(),
darkest: darkest.into(),
}
}
}
impl ItemPalette {

View file

@ -202,7 +202,7 @@ struct PhraseViewKeys<'a>(&'a PhraseView<'a>, ItemPalette);
render!(|self: PhraseViewKeys<'a>|{
let layout = |to:[u16;2]|Ok(Some(to.clip_w(5)));
Tui::fill_xy(Widget::new(layout, |to: &mut TuiOutput|Ok(
self.0.view_mode.render_keys(to, self.1.dark.rgb, Some(self.0.note_point), self.0.note_range)
self.0.view_mode.render_keys(to, self.1.light.rgb, Some(self.0.note_point), self.0.note_range)
)))
});
@ -397,6 +397,17 @@ impl PhraseViewMode for PianoHorizontal {
}
}
/// Draw the piano roll using full blocks on note on and half blocks on legato: █▄ █▄ █▄
fn draw_piano_horizontal (
target: &mut BigBuffer,
phrase: &Phrase,
time_zoom: usize,
note_len: usize,
) {
draw_piano_horizontal_bg(target, phrase, time_zoom, note_len);
draw_piano_horizontal_fg(target, phrase, time_zoom);
}
fn draw_piano_horizontal_bg (
target: &mut BigBuffer,
phrase: &Phrase,
@ -407,7 +418,8 @@ fn draw_piano_horizontal_bg (
for (x, time) in (0..target.width).map(|x|(x, x*time_zoom)) {
let cell = target.get_mut(x, y).unwrap();
//cell.set_fg(Color::Rgb(48, 55, 45));
cell.set_fg(phrase.color.dark.rgb);
cell.set_bg(phrase.color.darkest.rgb);
cell.set_fg(phrase.color.darker.rgb);
cell.set_char(if time % 384 == 0 {
'│'
} else if time % 96 == 0 {
@ -428,7 +440,7 @@ fn draw_piano_horizontal_fg (
phrase: &Phrase,
time_zoom: usize,
) {
let style = Style::default().fg(phrase.color.light.rgb);//.bg(Color::Rgb(0, 0, 0));
let style = Style::default().fg(phrase.color.lightest.rgb);//.bg(Color::Rgb(0, 0, 0));
let mut notes_on = [false;128];
for (x, time_start) in (0..phrase.length).step_by(time_zoom).enumerate() {
@ -462,63 +474,6 @@ fn draw_piano_horizontal_fg (
}
}
/// Draw the piano roll using full blocks on note on and half blocks on legato: █▄ █▄ █▄
fn draw_piano_horizontal (
target: &mut BigBuffer,
phrase: &Phrase,
time_zoom: usize,
note_len: usize,
) {
let color = phrase.color.light.rgb;
let style = Style::default().fg(color);//.bg(Color::Rgb(0, 0, 0));
for (y, note) in (0..127).rev().enumerate() {
for (x, time) in (0..target.width).map(|x|(x, x*time_zoom)) {
let cell = target.get_mut(x, y).unwrap();
//cell.set_fg(Color::Rgb(48, 55, 45));
cell.set_fg(phrase.color.dark.rgb);
cell.set_char(if time % 384 == 0 {
'│'
} else if time % 96 == 0 {
'╎'
} else if time % note_len == 0 {
'┊'
} else if (127 - note) % 12 == 1 {
'='
} else {
'·'
});
}
}
let mut notes_on = [false;128];
for (x, time_start) in (0..phrase.length).step_by(time_zoom).enumerate() {
let time_end = time_start + time_zoom;
for (y, note) in (0..127).rev().enumerate() {
let cell = target.get_mut(x, note).unwrap();
if notes_on[note] {
cell.set_char('▄');
cell.set_style(style);
}
}
for time in time_start..time_end {
for event in phrase.notes[time].iter() {
match event {
MidiMessage::NoteOn { key, .. } => {
let note = key.as_int() as usize;
let cell = target.get_mut(x, note).unwrap();
cell.set_char('█');
cell.set_style(style);
notes_on[note] = true
},
MidiMessage::NoteOff { key, .. } => {
notes_on[key.as_int() as usize] = false
},
_ => {}
}
}
}
}
}
#[derive(Clone, Debug)]
pub enum PhraseCommand {
// TODO: 1-9 seek markers that by default start every 8th of the phrase