Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alters-mit committed Dec 1, 2023
1 parent b174076 commit baee390
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 237 deletions.
2 changes: 1 addition & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub mod music_panel_field;
pub use edit_mode::*;
mod selectable;
mod selection;
pub use selection::Selection;
pub use selectable::Selectable;
pub use selection::Selection;
mod piano_roll_mode;
pub use piano_roll_mode::PianoRollMode;
use std::env::current_dir;
Expand Down
8 changes: 4 additions & 4 deletions common/src/selectable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum Selectable {
Effect(Effect),
Note(Note)
Note(Note),
}

impl Selectable {
pub fn get_start_time(&self) -> u64 {
match self {
Self::Effect(effect) => effect.time,
Self::Note(note) => note.start
Self::Note(note) => note.start,
}
}

pub fn get_end_time(&self) -> u64 {
match self {
Self::Effect(effect) => effect.time,
Self::Note(note) => note.end
Self::Note(note) => note.end,
}
}
}
}
209 changes: 170 additions & 39 deletions common/src/selection.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
use crate::{Effect, Music, Note, MidiTrack, selectable};
use crate::{Effect, Music, Note};
use serde::{Deserialize, Serialize};

enum Selectable<'track> {
Effect{ effect: &'track Effect, index: usize},
Note{ note: &'track Note, index: usize}
Effect {
effect: &'track Effect,
index: usize,
},
Note {
note: &'track Note,
index: usize,
},
}

impl<'track> Selectable<'track> {
fn get_start_time(&self) -> u64 {
match self {
Self::Effect {effect, index: _} => effect.time,
Self::Note{note, index: _} => note.start
Self::Effect { effect, index: _ } => effect.time,
Self::Note { note, index: _ } => note.start,
}
}

fn get_end_time(&self) -> u64 {
match self {
Self::Effect {effect, index: _} => effect.time,
Self::Note{note, index: _} => note.end
Self::Effect { effect, index: _ } => effect.time,
Self::Note { note, index: _ } => note.end,
}
}
}
Expand All @@ -41,8 +47,6 @@ impl Selection {
}

/// Returns the selected notes and effects.
///
/// - `music` The music.
pub fn get_selection<'a>(&self, music: &'a Music) -> Option<(Vec<&'a Note>, Vec<&'a Effect>)> {
match music.get_selected_track() {
None => None,
Expand All @@ -53,6 +57,7 @@ impl Selection {
}
}

/// Returns mutable selected notes and effects.
pub fn get_selection_mut<'a>(
&self,
music: &'a mut Music,
Expand All @@ -64,84 +69,210 @@ impl Selection {
.notes
.iter_mut()
.enumerate()
.filter(|n| self.notes.contains(&n.0))
.map(|n| n.1)
.filter(|(i, _)| self.notes.contains(i))
.map(|(_, note)| note)
.collect(),
track
.effects
.iter_mut()
.enumerate()
.filter(|n| self.effects.contains(&n.0))
.map(|n| n.1)
.filter(|(i, _)| self.effects.contains(i))
.map(|(_, effect)| effect)
.collect(),
)),
}
}

pub fn select_previous(&self, music: &Music) -> bool {
/// Select the note or event prior to the current selection.
pub fn select_previous(&mut self, music: &Music, cursor_time: u64) -> bool {
match Self::get_music_selectables(music) {
Some(music_selectables) => {
let selectables = self.get_selectables(music).unwrap();
// Nothing is selected.
if selectables.is_empty() {
// There is nothing to select.
if music_selectables.is_empty() {
false
// The track has a program but no notes or events.
if music_selectables.is_empty() {
false
} else {
match self.get_selectables(music) {
Some(selectables) => {
// The selection is empty.
let s = if selectables.is_empty() {
music_selectables
.iter()
.filter(|s| s.get_start_time() < cursor_time)
.last()
} else {
music_selectables
.iter()
.filter(|s| s.get_end_time() < selectables[0].get_start_time())
.last()
};
match s {
Some(s) => {
self.add_selectable(s);
true
}
None => false,
}
}
None => false,
}
// Select the first available option.
else {
}
}
None => false,
}
}

/// Select the note or event after to the current selection.
pub fn select_next(&mut self, music: &Music, cursor_time: u64) -> bool {
match Self::get_music_selectables(music) {
Some(music_selectables) => {
// The track has a program but no notes or events.
if music_selectables.is_empty() {
false
} else {
match self.get_selectables(music) {
Some(selectables) => {
// The selection is empty.
let s = if selectables.is_empty() {
music_selectables
.iter()
.filter(|s| s.get_end_time() > cursor_time)
.last()
} else {
music_selectables
.iter()
.filter(|s| {
s.get_start_time()
> selectables[selectables.len() - 1].get_end_time()
})
.last()
};
match s {
Some(s) => {
self.add_selectable(s);
true
}
None => false,
}
}
None => false,
}
}
}
None => false,
}
}

pub fn deselect_first(&mut self, music: &Music) -> bool {
match self.get_selectables(music) {
Some(selectables) => {
// Try to remove the first selected note or event.
if !selectables.is_empty() {
match selectables[0] {
Selectable::Effect { effect: _, index } => self.effects.remove(index),
Selectable::Note { note: _, index } => self.notes.remove(index),
};
true
}
else {
false
}
}
None => false,
}
}

pub fn deselect_last(&mut self, music: &Music) -> bool {
match self.get_selectables(music) {
Some(selectables) => {
// Try to remove the first selected note or event.
if !selectables.is_empty() {
match selectables.last().unwrap() {
Selectable::Effect { effect: _, index } => self.effects.remove(*index),
Selectable::Note { note: _, index } => self.notes.remove(*index),
};
true
}
else {
false
}
}
None => false
None => false,
}
// Get all selected notes and effects.
let selectables = self.get_selectables(music);
}

/// Select all notes and effects.
pub fn select_all(&mut self, music: &Music) {
if let Some(music_selectables) = Self::get_music_selectables(music) {
self.single = false;
self.notes.clear();
self.effects.clear();
for s in music_selectables.iter() {
self.add_selectable(s)
}
}
}

/// Returns a vec of selected notes and effects.
fn get_selectables<'track>(&self, music: &'track Music) -> Option<Vec<Selectable<'track>>> {
match self.get_selection(music) {
Some((notes, effects)) => {
let mut selectables = notes.iter().enumerate().map(|(index, note)| Selectable::Note{note, index}).collect::<Vec<Selectable>>();
selectables.extend(effects.iter().enumerate().map(|(index, effect)| Selectable::Effect {effect, index}));
let mut selectables = notes
.iter()
.enumerate()
.map(|(index, note)| Selectable::Note { note, index })
.collect::<Vec<Selectable>>();
selectables.extend(
effects
.iter()
.enumerate()
.map(|(index, effect)| Selectable::Effect { effect, index }),
);
// Sort the selectables by start time.
selectables.sort_by(|a, b| a.get_start_time().cmp(&b.get_start_time()));
Some(selectables)
}
None => None
None => None,
}
}

fn get_music_selectables(music: &Music) -> Option<Vec<Selectable<'track>>> {
match music.get_selected_track_mut() {
/// Convert the selected track's notes and effects into a vec of selectables.
fn get_music_selectables(music: &Music) -> Option<Vec<Selectable<'_>>> {
match music.get_selected_track() {
Some(track) => {
let mut selectables = track.notes.iter().enumerate().map(|(index, note)| Selectable::Note{note, index}).collect::<Vec<Selectable>>();
selectables.extend(track.effects.iter().enumerate().map(|(index, effect)| Selectable::Effect {effect, index}));
let mut selectables = track
.notes
.iter()
.enumerate()
.map(|(index, note)| Selectable::Note { note, index })
.collect::<Vec<Selectable>>();
selectables.extend(
track
.effects
.iter()
.enumerate()
.map(|(index, effect)| Selectable::Effect { effect, index }),
);
selectables.sort_by(|a, b| a.get_start_time().cmp(&b.get_start_time()));
Some(selectables)
}
None => None
None => None,
}
}

/// Add a note or effect to the selection.
fn add_selectable(&mut self, selectable: &Selectable) {
match selectable {
Selectable::Effect { effect, index } => {
Selectable::Effect { effect: _, index } => {
if self.effects.is_empty() || !self.single {
self.effects.push(*index)
}
else {
} else {
self.effects[0] = *index
}
}
Selectable::Note { note, index } => {
Selectable::Note { note: _, index } => {
if self.notes.is_empty() || !self.single {
self.notes.push(*index)
}
else {
} else {
self.notes[0] = *index
}
}
Expand Down
3 changes: 1 addition & 2 deletions io/src/piano_roll/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ impl Panel for Edit {
}
if snapshot {
Some(Snapshot::from_states(s0, state))
}
else {
} else {
None
}
}
Expand Down
Loading

0 comments on commit baee390

Please sign in to comment.