diff --git a/cheatsheet.txt b/cheatsheet.txt index 34000cc..0d97346 100644 --- a/cheatsheet.txt +++ b/cheatsheet.txt @@ -118,6 +118,7 @@ Shift+Click+Drag: Move copy of pattern(s) at cursor. +Click+Drag: Move pattern link(s) at cursor. Delete: Remove selected patterns. Ctrl+J: Join patterns across tracks into one. + S: Split patterns at cursor. Ctrl+D: Duplicate selection. Ctrl+Shift+D: Duplicate selection as link. Shift+Left/Right: Move patterns along track (+-step). diff --git a/model.cpp b/model.cpp index 9ff4382..77d434e 100644 --- a/model.cpp +++ b/model.cpp @@ -262,6 +262,28 @@ void Pattern::copy_from(const Pattern &pattern) { } } +void Pattern::move_frames(int row, int step, int channel) { + int length = get_length(); + + Pattern::iterator iter; + for (Pattern::iterator iter = begin(); + iter != end(); ++iter) { + int frame = iter->second.frame; + if (frame < row) + continue; + if ((channel >= 0) && (iter->second.channel != channel)) + continue; + int newframe = frame + step; + if ((newframe < row) || (newframe >= length)) { + iter->second.frame = -1; // will be deleted + } else { + iter->second.frame = newframe; + } + } + + update_keys(); +} + //============================================================================= SongEvent::SongEvent() { diff --git a/model.hpp b/model.hpp index f23c5b8..a8c3e6b 100644 --- a/model.hpp +++ b/model.hpp @@ -160,6 +160,8 @@ public: void update_keys(); void copy_from(const Pattern &pattern); + void move_frames(int row, int step, int channel); + Pattern(); protected: // length in frames diff --git a/patternview.cpp b/patternview.cpp index 8ad7410..644e7d1 100644 --- a/patternview.cpp +++ b/patternview.cpp @@ -1212,25 +1212,9 @@ void PatternView::transpose(int step) { void PatternView::move_frames(int step, bool all_channels/*=false*/) { int row = cursor.get_row(); int channel = cursor.get_channel(); - int length = get_pattern()->get_length(); - Pattern::iterator iter; - for (Pattern::iterator iter = get_pattern()->begin(); - iter != get_pattern()->end(); ++iter) { - int frame = iter->second.frame; - if (frame < row) - continue; - if (!all_channels && (iter->second.channel != channel)) - continue; - int newframe = frame + step; - if ((newframe < row) || (newframe >= length)) { - iter->second.frame = -1; // will be deleted - } else { - iter->second.frame = newframe; - } - } + get_pattern()->move_frames(row, step, (all_channels?-1:channel)); - get_pattern()->update_keys(); invalidate(); } diff --git a/songview.cpp b/songview.cpp index 1971287..ddee6f1 100644 --- a/songview.cpp +++ b/songview.cpp @@ -907,6 +907,44 @@ void SongView::set_loop_end() { invalidate_loop(); } +void SongView::split_at_mouse_cursor() { + SongCursor cur(*this); + cur.set_pos(cursor_x, cursor_y); + + int frame = quantize_frame(cur.get_frame()); + + invalidate_selection(); + Song::IterList new_selection; + + Song::IterList::iterator iter; + for (iter = selection.begin(); iter != selection.end(); ++iter) { + Song::Event &event = (*iter)->second; + if ((frame > event.frame) && (frame < event.get_last_frame())) { + // create two new events + Song::Event left_event = event; + Song::Event right_event = event; + left_event.pattern = &model->new_pattern(event.pattern); + left_event.pattern->set_length(frame - event.frame); + right_event.pattern = &model->new_pattern(event.pattern); + right_event.pattern->move_frames(0, event.frame - frame, -1); + right_event.pattern->set_length(event.get_end() - frame); + right_event.frame = frame; + + new_selection.push_back(model->song.add_event(left_event)); + new_selection.push_back(model->song.add_event(right_event)); + + _pattern_erased(*iter); + model->song.erase(*iter); + } + } + + selection = new_selection; + invalidate_selection(); + + // cleanup + model->delete_unused_patterns(); +} + void SongView::seek_to_mouse_cursor() { SongCursor cur(*this); cur.set_pos(cursor_x, cursor_y); @@ -1003,6 +1041,7 @@ bool SongView::on_key_press_event(GdkEventKey* event) { edit_pattern(selection.front()); return true; } break; + case GDK_s: split_at_mouse_cursor(); return true; case GDK_p: seek_to_mouse_cursor(); return true; case GDK_m: toggle_mute_selection(); return true; case GDK_Left: navigate(-1,0); return true; diff --git a/songview.hpp b/songview.hpp index 34e691d..b4b1d93 100644 --- a/songview.hpp +++ b/songview.hpp @@ -161,6 +161,7 @@ protected: int get_selection_end(); void play_from_selection(); void seek_to_mouse_cursor(); + void split_at_mouse_cursor(); bool can_resize_event(Song::iterator event, int x); void get_drag_offset(int &frame, int &track);