summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-06-07 18:45:32 +0000
committerFlorian Jung <flo@windfisch.org>2011-06-07 18:45:32 +0000
commitc6f2151b1589c91292563a1b319cdbd193834d67 (patch)
treeb4df7786b2d03664fe45867ca8017b3f44233f8d
parent637498c87bf1ac780d8527d0596936fcdd2c6dfc (diff)
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
-rw-r--r--muse2/muse/arranger/pcanvas.cpp4
-rw-r--r--muse2/muse/arranger/pcanvas.h2
-rw-r--r--muse2/muse/functions.cpp39
-rw-r--r--muse2/muse/functions.h2
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp2
-rw-r--r--muse2/muse/midiedit/dcanvas.h2
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp58
-rw-r--r--muse2/muse/midiedit/prcanvas.h2
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp9
-rw-r--r--muse2/muse/part.cpp53
-rw-r--r--muse2/muse/part.h2
-rw-r--r--muse2/muse/song.h2
-rw-r--r--muse2/muse/widgets/canvas.cpp2
-rw-r--r--muse2/muse/widgets/canvas.h2
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<Part*>& 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();