From ae677748c718538288f7e6ba5d0737178e4e88dd Mon Sep 17 00:00:00 2001 From: EvanR Date: Mon, 29 Dec 2008 20:06:38 -0600 Subject: [PATCH] Added unsafe block resizing. Broke restating. You can now left click drag on block edges to resize them. If you have many blocks selected it will resize all of them. There is not yet a guard against resizing so as to overlap other blocks. Doing this may cause a crash while playing. There is not yet support for resizing to negative width. This is the reason there is not yet a test for resize safety. If some of the blocks are resized to negative width, their resize command will fail. Writing a collision test for this behavior would be too much work if it is temporary. If you resize, move, or delete (and later paste) blocks during an intersection with the play position, the changes will not be immediately registered by the sequencer. This is caused by a refactoring of the 'restating' policy and a rewriting of the restate function. The restate function is being called at the right time, but is apparently not working correctly. --- src/arranger.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/arranger.h | 3 +- src/seq.cpp | 17 +++++-- src/seq.h | 6 +++ src/util.cpp | 18 +++---- src/util.h | 3 +- 6 files changed, 174 insertions(+), 24 deletions(-) diff --git a/src/arranger.cpp b/src/arranger.cpp index d0a8cd6..2b4f9aa 100644 --- a/src/arranger.cpp +++ b/src/arranger.cpp @@ -179,8 +179,14 @@ int Arranger::handle(int event){ } if(over_lhandle(s,X,Y)){//begin resize + lresize_flag = 1; + lresize_torig = s->tick; + lresize_toffset = 0; } else if(over_rhandle(s,X,Y)){//begin resizemove + rresize_flag = 1; + rresize_torig = s->tick+s->dur; + rresize_toffset = 0; } else{//begin move @@ -266,6 +272,12 @@ int Arranger::handle(int event){ } new_track = Y / 30; } + else if(rresize_flag){ + rresize_toffset = xpix2tick(X)/128*128 - rresize_torig; + } + else if(lresize_flag){ + lresize_toffset = xpix2tick(X)/128*128 - lresize_torig; + } else if(move_flag){ move_toffset = quantize(xpix2tick(X)) - move_torig; move_koffset = event_y() / 30 - move_korig; @@ -293,6 +305,23 @@ int Arranger::handle(int event){ apply_move(); move_flag = 0; } + else if(rresize_flag){ + apply_rresize(); + rresize_flag = 0; + if(last_handle){ + last_handle->lhandle = 0; + last_handle->rhandle = 0; + } + } + else if(lresize_flag){ + apply_lresize(); + lresize_flag = 0; + if(last_handle){ + last_handle->lhandle = 0; + last_handle->rhandle = 0; + } + } + insert_flag=0; color_sel = NULL; } @@ -319,6 +348,8 @@ int Arranger::handle(int event){ delete_flag=0; } + + redraw(); return 1; case fltk::MOVE: @@ -455,9 +486,25 @@ void Arranger::draw(){ get_outline_color(s,&c1,&c2,&c3,&cx); fltk::setcolor(c1); - int X = tick2xpix(s->tick)+1; + + int R1 = lresize_flag&&s->selected ? lresize_toffset : 0; + int R2 = rresize_flag&&s->selected ? rresize_toffset : 0; + + int T1 = s->tick+R1; + int T2 = s->tick+s->dur+R2; + + if(T1 > T2){SWAP(T1,T2)}; + + int X = tick2xpix(T1)+1; int Y = s->track * 30; - int W = tick2xpix(s->tick+s->dur) - X; + int W = tick2xpix(T2)-tick2xpix(T1)-1; + + if(rresize_flag && s->selected && T1==T2){ + W = tick2xpix(128)-1; + } + if(lresize_flag && s->selected && T1==T2){ + W = tick2xpix(128)-1; + } fillrect(X+1,Y+1,W-2,27); float a = 1.5f; @@ -471,9 +518,9 @@ void Arranger::draw(){ fillrect(X,Y,1,28); fillrect(X,Y,W,1); - fltk::push_clip(tick2xpix(s->tick),s->track*30,tick2xpix(s->dur),30); + fltk::push_clip(tick2xpix(T1),s->track*30,tick2xpix(T2-T1),30); - if(s->rhandle){ + if(s->rhandle && !rresize_flag){ setcolor(cx); W = 5; X = tick2xpix(s->tick+s->dur) - W - 1; @@ -485,7 +532,7 @@ void Arranger::draw(){ fillpath(); } - if(s->lhandle){ + if(s->lhandle && !lresize_flag){ setcolor(cx); setcolor(cx); W = 5; @@ -732,7 +779,7 @@ void Arranger::apply_delete(){ while(s){ next = s->next; if(s->selected){ - seqpat_nonstick(s); + tracks[s->track]->modified = 1; c=new DeleteSeqpat(s); set_undo(c); N++; @@ -764,8 +811,8 @@ int Arranger::apply_move(){ while(s){ next = s->next; if(s->selected && s->modified == 0){ + tracks[s->track]->modified = 1; s->modified = 1; - seqpat_nonstick(s); c=new MoveSeqpat(s,s->track+move_koffset,s->tick+move_toffset); set_undo(c); N++; @@ -776,7 +823,6 @@ int Arranger::apply_move(){ undo_push(N); for(int i=0; irestate(); s = tracks[i]->head->next; while(s){ s->modified = 0; @@ -784,6 +830,7 @@ int Arranger::apply_move(){ } } + unmodify_blocks(); unmodify_and_unstick_tracks(); return 1; } @@ -792,8 +839,94 @@ void Arranger::apply_paste(){ } -void Arranger::apply_resize(){ +void Arranger::apply_rresize(){ + if(rresize_toffset==0){ + return; + } + + if(!check_resize_safety()){ + return; + } + + Command* c; + seqpat* s; + seqpat* next; + int N=0; + for(int i=0; ihead->next; + while(s){ + next = s->next; + if(s->selected && s->modified == 0){ + tracks[i]->modified = 1; + s->modified = 1; + int T1 = s->tick; + int T2 = s->tick + s->dur + rresize_toffset; + if(T1 > T2){ + //here perform reversal resize and move + } + else{ + if(T1==T2){ + T2 = T1+128; //magic + } + c=new ResizeSeqpat(s,s->dur+rresize_toffset); + set_undo(c); + N++; + } + + } + s = next; + } + } + undo_push(N); + + unmodify_blocks(); + unmodify_and_unstick_tracks(); +} + +void Arranger::apply_lresize(){ + if(lresize_toffset==0){ + return; + } + + if(!check_resize_safety()){ + return; + } + + Command* c; + seqpat* s; + seqpat* next; + int N=0; + for(int i=0; ihead->next; + while(s){ + next = s->next; + if(s->selected && s->modified == 0){ + tracks[i]->modified = 1; + s->modified = 1; + int T1 = s->tick + lresize_toffset; + int T2 = s->tick + s->dur; + if(T1 > T2){ + //here perform reversal resize and move + } + else{ + if(T1==T2){ + T2 = T1+128; //magic + } + c=new MoveSeqpat(s,s->track,T1); + set_undo(c); + c=new ResizeSeqpat(s,T2-T1); + set_undo(c); + N+=2; + } + + } + s = next; + } + } + undo_push(N); + unmodify_blocks(); + unmodify_and_unstick_tracks(); } diff --git a/src/arranger.h b/src/arranger.h index bd903ea..6edf8c6 100644 --- a/src/arranger.h +++ b/src/arranger.h @@ -97,7 +97,8 @@ class Arranger : public fltk::Widget { void apply_delete(); int apply_move(); void apply_paste(); - void apply_resize(); + void apply_rresize(); + void apply_lresize(); int check_move_safety(); int check_insert_safety(); diff --git a/src/seq.cpp b/src/seq.cpp index be705b7..ebf1820 100644 --- a/src/seq.cpp +++ b/src/seq.cpp @@ -325,20 +325,25 @@ CreateSeqpatBlank::CreateSeqpatBlank(int track, int tick, int len){ void DeleteSeqpat::redo(){ + //check for restate int pos = get_play_position(); if(pos >= s->tick && pos <= s->tick+s->dur){ tracks[s->track]->skip = s->next; } + tremove(s); } void DeleteSeqpat::undo(){ tinsert(s->prev, s); + //check for restate } void ResizeSeqpat::redo(){ tremove(s1); tinsert(s1->prev,s2); + + //check for restate } void ResizeSeqpat::undo(){ @@ -381,6 +386,9 @@ void MoveSeqpat::redo(){ s->skip = tfind(s->p->events, play_pos - s->tick)->next; tinsert(targ2,s); + //restate track 1 + //restate track 2 +/* if(s->tick+s->dur >= play_pos){ if(tracks[track2]->skip){ if(s->tick < tracks[track2]->skip->tick){ @@ -391,15 +399,14 @@ void MoveSeqpat::redo(){ tracks[track2]->skip = s; } } - - //send note off for all playing notes / all notes on this channel +*/ } void MoveSeqpat::undo(){ tremove(s); - int play_pos = get_play_position(); + int play_pos = get_play_position(); if(play_pos >= s->tick && play_pos <= s->tick+s->dur){ tracks[track2]->skip = s->next; } @@ -410,6 +417,9 @@ void MoveSeqpat::undo(){ s->skip = tfind(s->p->events, play_pos - s->tick)->next; tinsert(targ1,s); + + //restate tracks 1 and 2 +/* if(s->tick+s->dur >= play_pos){ if(tracks[track1]->skip){ if(s->tick < tracks[track1]->skip->tick){ @@ -420,6 +430,7 @@ void MoveSeqpat::undo(){ tracks[track1]->skip = s; } } +*/ } void SplitSeqpat::redo(){ diff --git a/src/seq.h b/src/seq.h index 80fe27b..e56b2e5 100644 --- a/src/seq.h +++ b/src/seq.h @@ -188,6 +188,9 @@ struct seqpat { selected = zs->selected; modified = zs->modified; + + rhandle=0; + lhandle=0; } seqpat(seqpat* zs, pattern* zp){ @@ -206,6 +209,9 @@ struct seqpat { selected = zs->selected; modified = zs->modified; + + rhandle=0; + lhandle=0; } ~seqpat(){ diff --git a/src/util.cpp b/src/util.cpp index bee3d01..bd5459b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -127,22 +127,22 @@ int note2ypix(int note, int* black){ } - -//used when a block is modified -//sets the modify flag is the current play position is in the block -int seqpat_nonstick(seqpat* s){ - int pos = get_play_position(); - if(pos > s->tick && pos < s->tick + s->dur){ - printf("track modified\n"); - tracks[s->track]->modified = 1; +void unmodify_blocks(){ + seqpat* s; + for(int i=0; ihead->next; + while(s){ + s->modified = 0; + s = s->next; + } } } int unmodify_and_unstick_tracks(){ for(int i=0; imodified){ - printf("sending off on track\n"); midi_track_off(i); + tracks[i]->restate(); tracks[i]->modified = 0; } } diff --git a/src/util.h b/src/util.h index 0f69b0d..8495bda 100644 --- a/src/util.h +++ b/src/util.h @@ -31,7 +31,6 @@ void hsv_to_rgb(float h, float s, float v, unsigned char* r, unsigned char* g, u int ypix2note(int ypix, int black); int note2ypix(int note, int* black); - -int seqpat_nonstick(seqpat* s); +void unmodify_blocks(); int unmodify_and_unstick_tracks(); #endif -- 2.11.4.GIT