From c6f2151b1589c91292563a1b319cdbd193834d67 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 7 Jun 2011 18:45:32 +0000 Subject: modified behaviour for clones: - resizing a clone in the arranger also resizes all clones with the same length - same for auto-expanding in the pianoroll - auto-expanding in the pianoroll does NOT expand for parts which already contain hidden notes; then inserting notes is forbidden; buggy, see below still TODO and BUGS: - forbidding notes doesn't work properly. the pianoroll still displays them until the next full song update. - that stuff must be done in the drum canvas as well - step-rec and the score editor need support for auto-expanding --- muse2/muse/arranger/pcanvas.cpp | 4 +-- muse2/muse/arranger/pcanvas.h | 2 +- muse2/muse/functions.cpp | 39 ++++++++++++++++++++++++++ muse2/muse/functions.h | 2 ++ muse2/muse/midiedit/dcanvas.cpp | 2 +- muse2/muse/midiedit/dcanvas.h | 2 +- muse2/muse/midiedit/prcanvas.cpp | 58 +++++++++++++++++++-------------------- muse2/muse/midiedit/prcanvas.h | 2 +- muse2/muse/midiedit/scoreedit.cpp | 9 ++++-- muse2/muse/part.cpp | 53 +++++++++++++++++++---------------- muse2/muse/part.h | 2 ++ muse2/muse/song.h | 2 +- muse2/muse/widgets/canvas.cpp | 2 +- muse2/muse/widgets/canvas.h | 2 +- 14 files changed, 117 insertions(+), 64 deletions(-) diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index f7a2abde..9fefaf70 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -448,7 +448,7 @@ void PartCanvas::updateSelection() // resizeItem //--------------------------------------------------------- -void PartCanvas::resizeItem(CItem* i, bool noSnap) +void PartCanvas::resizeItem(CItem* i, bool noSnap, bool ctrl) { Track* t = ((NPart*)(i))->track(); Part* p = ((NPart*)(i))->part(); @@ -462,7 +462,7 @@ void PartCanvas::resizeItem(CItem* i, bool noSnap) if (newwidth == 0) newwidth = AL::sigmap.rasterStep(p->tick(), *_raster); - song->cmdResizePart(t, p, newwidth); + song->cmdResizePart(t, p, newwidth, !ctrl); } //--------------------------------------------------------- diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index acfe565e..ccfb1fcc 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -83,7 +83,7 @@ class PartCanvas : public Canvas { virtual int pitch2y(int p) const; virtual CItem* newItem(const QPoint&, int); - virtual void resizeItem(CItem*,bool); + virtual void resizeItem(CItem*,bool, bool ctrl); virtual void newItem(CItem*,bool); virtual bool deleteItem(CItem*); virtual void moveCanvasItems(CItemList&, int, int, DragType); diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index b47874fd..9ab209c6 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -866,6 +866,45 @@ void shrink_parts(int raster) song->applyOperationGroup(operations); } +void internal_schedule_expand_part(Part* part, int raster, Undo& operations) +{ + EventList* events=part->events(); + unsigned len=part->lenTick(); + + for (iEvent ev=events->begin(); ev!=events->end(); ev++) + if (ev->second.endTick() > len) + len=ev->second.endTick(); + + if (raster) len=ceil((float)len/raster)*raster; + + if (len > part->lenTick()) + { + MidiPart* new_part = new MidiPart(*(MidiPart*)part); + new_part->setLenTick(len); + operations.push_back(UndoOp(UndoOp::ModifyPart, part, new_part, true, false)); + } +} + +void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo& operations) +{ + unsigned old_len=part->lenTick(); + if (old_len!=new_len) + { + Part* part_it=part; + do + { + if (part_it->lenTick()==old_len) + { + MidiPart* new_part = new MidiPart(*(MidiPart*)part_it); + new_part->setLenTick(new_len); + operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, new_part, true, false)); + } + + part_it=part_it->nextClone(); + } while (part_it!=part); + } +} + void expand_parts(int raster) { Undo operations; diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h index 633457a9..90fc64e9 100644 --- a/muse2/muse/functions.h +++ b/muse2/muse/functions.h @@ -24,6 +24,7 @@ class QString; class QMimeData; +class Undo; extern GateTime* gatetime_dialog; extern Velocity* velocity_dialog; @@ -87,6 +88,7 @@ void select_not_in_loop(const std::set& parts); //functions for parts void shrink_parts(int raster=-1); //negative values mean "config.division" void expand_parts(int raster=-1); +void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo& operations); void clean_parts(); //functions for reading and writing default values diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 92e514af..b19831a0 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -308,7 +308,7 @@ CItem* DrumCanvas::newItem(int tick, int instrument, int velocity) // resizeItem //--------------------------------------------------------- -void DrumCanvas::resizeItem(CItem* item, bool) +void DrumCanvas::resizeItem(CItem* item, bool, bool) { DEvent* nevent = (DEvent*) item; Event ev = nevent->event(); diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h index 868113a6..a2d0f7de 100644 --- a/muse2/muse/midiedit/dcanvas.h +++ b/muse2/muse/midiedit/dcanvas.h @@ -57,7 +57,7 @@ class DrumCanvas : public EventCanvas { virtual Undo moveCanvasItems(CItemList&, int, int, DragType); virtual UndoOp moveItem(CItem*, const QPoint&, DragType); virtual CItem* newItem(const QPoint&, int); - virtual void resizeItem(CItem*, bool); + virtual void resizeItem(CItem*, bool, bool); virtual void newItem(CItem*, bool); virtual void newItem(CItem*, bool, bool replace ); virtual bool deleteItem(CItem*); diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index 091582ef..db42be6c 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -479,28 +479,28 @@ void PianoCanvas::newItem(CItem* item, bool noSnap) event.setLenTick(w); event.setPitch(y2pitch(item->y())); - song->startUndo(); - int modified=SC_EVENT_MODIFIED; + Undo operations; int diff = event.endTick()-part->lenTick(); - if (diff > 0) {// too short part? extend it - //printf("extend Part!\n"); - Part* newPart = part->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - // Indicate no undo, and do port controller values but not clone parts. - audio->msgChangePart(part, newPart, false, true, false); - modified=modified|SC_PART_MODIFIED; - part = newPart; // reassign + + if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed + { + operations.push_back(UndoOp(UndoOp::AddEvent,event, part, false, false)); + + if (diff > 0)// part must be extended? + { + schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); + printf("newItem: extending\n"); } - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(event, part, false, false, false); - song->endUndo(modified); + } + //FINDMICH TODO: forbid action! this is currently wrong! + song->applyOperationGroup(operations); } //--------------------------------------------------------- // resizeItem //--------------------------------------------------------- -void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental changes to try dynamically extending parts +void PianoCanvas::resizeItem(CItem* item, bool noSnap, bool) // experimental changes to try dynamically extending parts { //printf("resizeItem!\n"); NEvent* nevent = (NEvent*) item; @@ -519,23 +519,23 @@ void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental c if (len <= 0) len = editor->raster(); } - song->startUndo(); - int modified=SC_EVENT_MODIFIED; + + Undo operations; int diff = event.tick()+len-part->lenTick(); - if (diff > 0) {// too short part? extend it - //printf("extend Part!\n"); - Part* newPart = part->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - // Indicate no undo, and do port controller values but not clone parts. - audio->msgChangePart(part, newPart, false, true, false); - modified=modified|SC_PART_MODIFIED; - part = newPart; // reassign - } + + if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed + { + newEvent.setLenTick(len); + operations.push_back(UndoOp(UndoOp::ModifyEvent,newEvent, event, nevent->part(), false, false)); + + if (diff > 0)// part must be extended? + { + schedule_resize_all_same_len_clone_parts(part, event.tick()+len, operations); + printf("resizeItem: extending\n");} + } + //FINDMICH TODO: forbid action! this is currently wrong! + song->applyOperationGroup(operations); - newEvent.setLenTick(len); - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false); - song->endUndo(modified); } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h index c6e47c9e..d96dd4df 100644 --- a/muse2/muse/midiedit/prcanvas.h +++ b/muse2/muse/midiedit/prcanvas.h @@ -57,7 +57,7 @@ class PianoCanvas : public EventCanvas { virtual Undo moveCanvasItems(CItemList&, int, int, DragType); virtual UndoOp moveItem(CItem*, const QPoint&, DragType); virtual CItem* newItem(const QPoint&, int); - virtual void resizeItem(CItem*, bool noSnap); + virtual void resizeItem(CItem*, bool noSnap, bool); virtual void newItem(CItem*, bool noSnap); virtual bool deleteItem(CItem*); virtual void startDrag(CItem* item, bool copymode); diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 1a885d99..f7d9237b 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4457,11 +4457,14 @@ void staff_t::update_part_indices() * between, for example, when a cis is tied to a des * * CURRENT TODO - * o clones should have same size - * o insert empty measure should also work inside parts, that is, - * move notes _within_ parts + * o do autoexpand correctly in prcanvas.cpp, then port that to + * dcanvas.cpp, steprec.cpp and scoreedit.cpp * * IMPORTANT TODO + * o shrink a part from its beginning as well! watch out for clones! + * o insert empty measure should also work inside parts, that is, + * move notes _within_ parts + * * o canvas editor: create clone via "alt+drag" moves window instead * o investigate with valgrind * o controller view in score editor diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 398720af..9bb3431c 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -819,7 +819,7 @@ void Song::removePart(Part* part) // cmdResizePart //--------------------------------------------------------- -void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len) +void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClones) { switch(track->type()) { case Track::WAVE: @@ -899,28 +899,21 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len) case Track::DRUM: { Undo operations; - - MidiPart* nPart = new MidiPart(*(MidiPart*)oPart); - nPart->setLenTick(len); - // Do port controller values but not clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, true, false)); - - // cut Events in nPart - // Changed by T356. Don't delete events if this is a clone part. - // The other clones might be longer than this one and need these events. - if(nPart->cevents()->arefCount() <= 1) - { - if(oPart->lenTick() > len) { - EventList* el = nPart->events(); - iEvent ie = el->lower_bound(len); - for (; ie != el->end();) { - iEvent i = ie; - ++ie; - // Do port controller values and clone parts. - operations.push_back(UndoOp(UndoOp::DeleteEvent, i->second, nPart, true, true)); - } - } - } + + unsigned orig_len=oPart->lenTick(); + MidiPart* part_it=(MidiPart*)oPart; + do + { + if (part_it->lenTick()==orig_len) + { + MidiPart* newPart = new MidiPart(*part_it); + newPart->setLenTick(len); + // Do port controller values but not clone parts. + operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, newPart, true, false)); + } + + part_it=(MidiPart*)part_it->nextClone(); + } while (doClones && (part_it != (MidiPart*)oPart)); song->applyOperationGroup(operations); break; @@ -1176,3 +1169,17 @@ WavePart* WavePart::clone() const return new WavePart(*this); } + + +bool Part::hasHiddenNotes() +{ + unsigned lastNote=0; + + for (iEvent ev=events()->begin(); ev!=events()->end(); ev++) + if (ev->second.endTick() > lastNote) + lastNote=ev->second.endTick(); + + printf ("in hasHiddenNotes: lastNote=%i, lenTick=%i\n",lastNote, lenTick()); + + return lastNote > lenTick(); +} diff --git a/muse2/muse/part.h b/muse2/muse/part.h index 9b037edd..ff7091a6 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -82,6 +82,8 @@ class Part : public PosLen { void setPrevClone(Part* p) { _prevClone = p; } void setNextClone(Part* p) { _nextClone = p; } + bool hasHiddenNotes(); + iEvent addEvent(Event& p); virtual void write(int, Xml&, bool isCopy = false, bool forceWavePaths = false) const; diff --git a/muse2/muse/song.h b/muse2/muse/song.h index fd88b278..45751418 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -253,7 +253,7 @@ class Song : public QObject { // part manipulations //----------------------------------------- - void cmdResizePart(Track* t, Part* p, unsigned int size); + void cmdResizePart(Track* t, Part* p, unsigned int size, bool doClones=false); void cmdSplitPart(Track* t, Part* p, int tick); void cmdGluePart(Track* t, Part* p); diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index 650b10b7..9025590a 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -1131,7 +1131,7 @@ void Canvas::viewMouseReleaseEvent(QMouseEvent* event) case DRAG_OFF: break; case DRAG_RESIZE: - resizeItem(curItem, false); + resizeItem(curItem, false, ctrl); break; case DRAG_NEW: newItem(curItem, false); diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h index 2eae3d03..dbe13fcb 100644 --- a/muse2/muse/widgets/canvas.h +++ b/muse2/muse/widgets/canvas.h @@ -102,7 +102,7 @@ class Canvas : public View { virtual int pitch2y(int) const = 0; //CDW virtual CItem* newItem(const QPoint&, int state) = 0; - virtual void resizeItem(CItem*, bool noSnap=false) = 0; + virtual void resizeItem(CItem*, bool noSnap=false, bool ctrl=false) = 0; virtual void newItem(CItem*, bool noSnap=false) = 0; virtual bool deleteItem(CItem*) = 0; int getCurrentDrag(); -- cgit v1.2.3