From d2a88cfaad5ac385fc3c6212c09ad7fbc38e9454 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Mon, 28 May 2012 14:15:52 +0000 Subject: merged with release_2_0 --- muse2/muse/arranger/pcanvas.cpp | 262 +++++++++++++++++++++------------------- 1 file changed, 139 insertions(+), 123 deletions(-) (limited to 'muse2/muse/arranger/pcanvas.cpp') diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index f3e71916..cc23b59b 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -80,6 +80,8 @@ NPart::NPart(MusECore::Part* e) : CItem(MusECore::Event(), e) leftBorderTouches = false; rightBorderTouches = false; + _serial=e->sn(); + int y = track()->y(); setPos(QPoint(e->tick(), y)); setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); @@ -155,7 +157,7 @@ int PartCanvas::pitch2y(int p) const void PartCanvas::leaveEvent(QEvent*) { - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- @@ -215,7 +217,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) emit dclickPart(((NPart*)(curItem))->track()); } } - // + // double click creates new part between left and // right mark @@ -226,7 +228,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) int y = event->y(); for (it = tl->begin(); it != tl->end(); ++it) { int h = (*it)->height(); - if (y >= yy && y < (yy + h)) + if (y >= yy && y < (yy + h) && (*it)->isVisible()) break; yy += h; } @@ -395,7 +397,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& // But just in case we ever have two different lists... dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it // so we must decrement it first :/ - spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it + spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it // so we must increment it first :/ dpart->setSelected(spart->selected()); // These will increment ref count if not a clone, and will chain clones... @@ -444,23 +446,24 @@ void PartCanvas::songIsClearing() void PartCanvas::partsChanged() { int sn = -1; - if (curItem) sn=curItem->part()->sn(); - curItem=NULL; + if (curItem) sn=static_cast(curItem)->serial(); + curItem=NULL; items.clearDelete(); for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) { + if ((*t)->isVisible()) //ignore parts from hidden tracks + { MusECore::PartList* pl = (*t)->parts(); for (MusECore::iPart i = pl->begin(); i != pl->end(); ++i) { MusECore::Part* part = i->second; NPart* np = new NPart(part); items.add(np); - if (np->part()->sn() == sn) + if (np->serial() == sn) curItem=np; - if (i->second->selected()) { + if (i->second->selected()) selectItem(np, true); - } // Check for touching borders. p4.0.29 MusECore::Part* pp; @@ -476,10 +479,11 @@ void PartCanvas::partsChanged() if(pp->tick() == part->endTick()) np->rightBorderTouches = true; } - } } - redraw(); + } } + redraw(); +} //--------------------------------------------------------- // updateSelection @@ -868,10 +872,10 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) // viewMousePressEvent //--------------------------------------------------------- -void PartCanvas::mousePress(QMouseEvent* event) +bool PartCanvas::mousePress(QMouseEvent* event) { if (event->modifiers() & Qt::ControlModifier) { - return; + return true; } QPoint pt = event->pos(); CItem* item = items.find(pt); @@ -900,10 +904,26 @@ void PartCanvas::mousePress(QMouseEvent* event) } } case AutomationTool: - if (automation.controllerState != doNothing) - automation.moveController=true; - break; + if (event->button() & Qt::RightButton) { + QMenu *automationMenu = new QMenu(this); + QAction* act; + act = automationMenu->addAction(tr("Remove selected")); + act = automationMenu->exec(event->globalPos()); + if (act && automation.currentTrack) { + foreach(int frame, automation.currentCtrlFrameList) + MusEGlobal::audio->msgEraseACEvent((MusECore::AudioTrack*)automation.currentTrack, + automation.currentCtrlList->id(), frame); + } + + } + else { + if (automation.controllerState != doNothing) + automation.moveController=true; + } + return false; + break; } + return true; } //--------------------------------------------------------- @@ -3317,11 +3337,9 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //-------------------------------- MusECore::TrackList* tl = MusEGlobal::song->tracks(); - //int yy = 0; int yy = -rmapy(yorg) - ypos; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3331,9 +3349,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (MusEGlobal::config.canvasShowGrid && (track->isMidiTrack() || track->type() == MusECore::Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - //p.drawLine(x, yy + th, x + w, yy + th); p.drawLine(mx, yy + th, mx + mw, yy + th); - //p.setPen(baseColor); } // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). @@ -3346,26 +3362,10 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) // does NOT depend on the update rectangle (except to check intersection). That's why this issue // does not show up there. Should probably try to make that routine more efficient, just like here. Tim. p4.0.30 QRect r(mx, yy, mw, th); - //if(r.intersects(mr)) DELETETHIS { if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); drawAudioTrack(p, mr, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - - // DELETETHIS 13 - // This was redundant drawing. Not required, done via drawTopItem in Canvas::draw - /* - //p.setWorldMatrixEnabled(true); - //if (!track->isMidiTrack()) { // draw automation - if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - //p.setWorldMatrixEnabled(false); - */ + } } yy += th; } @@ -3378,8 +3378,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. - QRect mr = map(rect); // Use our own map instead. + QRect mr = map(rect); int mx = mr.x(); int my = mr.y(); @@ -3396,7 +3395,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int yy = yoff; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) DELETETHIS if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3404,15 +3402,12 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) if (!th) continue; if (!track->isMidiTrack()) { // draw automation - //QRect r = rect & QRect(x, yy, w, track->height()); DELETETHIS QRect r(mx, yy, mw, th); if(r.intersects(mr)) { drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); DELETETHIS } } - //yy += track->height(); DELETETHIS yy += th; } @@ -3631,13 +3626,25 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); pen2.setColor((automation.currentCtrlValid && automation.currentCtrlList == cl && - automation.currentCtrlFrame == ic->second.frame) ? + automation.currentCtrlFrameList.contains(ic->second.frame)) ? Qt::white : cl->color()); p.setPen(pen2); p.drawRect(xpixel-2, ypixel-2, 5, 5); oldX = xpixel; oldY = ypixel; + if (automation.currentCtrlValid && automation.currentCtrlList == cl && + automation.currentCtrlFrameList.contains(ic->second.frame) && + automation.currentCtrlFrameList.size() == 1) { + double val = ic->second.val; + QRect textRect = rr; + textRect.setX(xpixel + 20); + textRect.setY(ypixel); + if (cl->valueType() == MusECore::VAL_LOG) { + val = MusECore::fast_log10(ic->second.val) * 20.0; + } + p.drawText(textRect, QString("Value: %1").arg(val)); + } } } if (xpixel <= rr.right()) @@ -3648,6 +3655,42 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra } } +//--------------------------------------------------------- +// checkIfOnLine +// check if our point is on the line defined by +// by first/last X/Y +//--------------------------------------------------------- + +bool checkIfOnLine(double mouseX, double mouseY, double firstX, double lastX, double firstY, double lastY, int circumference) +{ + double proportion = (mouseX-firstX)/(lastX-firstX); + + // 10 X(15) 20 + // proportion = 0.5 + // 10 + // / + // Y(5) + // / + // 1 + double calcY = (lastY-firstY)*proportion+firstY; + if(ABS(calcY-mouseY) < circumference || (lastX == firstX && ABS(mouseX-lastX) < circumference)) + return true; + return false; +} + +//--------------------------------------------------------- +// checkIfNearPoint +//--------------------------------------------------------- + +bool checkIfNearPoint(int mouseX, int mouseY, int eventX, int eventY, int circumference) +{ + int x1 = ABS(mouseX - eventX) ; + int y1 = ABS(mouseY - eventY); + if (x1 < circumference && y1 < circumference) { + return true; + } + return false; +} //--------------------------------------------------------- // checkAutomation @@ -3660,22 +3703,22 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra // controller added. //--------------------------------------------------------- -void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool addNewCtrl) +void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool NOTaddNewCtrl) { if (t->isMidiTrack()) return; - int currY; + int mouseY; int trackY = t->y(); int trackH = t->height(); { int y = pointer.y(); if(y < trackY || y >= (trackY + trackH)) return; - currY = mapy(y); } + mouseY = mapy(y); } - int currX = mapx(pointer.x()); - int circumference = 5; + int mouseX = mapx(pointer.x()); + int circumference = 10; MusECore::CtrlListList* cll = ((MusECore::AudioTrack*) t)->controller(); for(MusECore::CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) @@ -3686,15 +3729,15 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } MusECore::iCtrl ic=cl->begin(); - int oldX = mapx(0); - int xpixel = oldX; - int oldY = -1; - int ypixel = oldY; + int eventOldX = mapx(0); + int eventX = eventOldX; + int eventOldY = -1; + int eventY = eventOldY; double min, max; cl->range(&min,&max); bool discrete = cl->mode() == MusECore::CtrlList::DISCRETE; - // First check that there IS automation, ic == cl->end means no automation + // First check that there IS automation for this controller, ic == cl->end means no automation if (ic == cl->end()) { double y; @@ -3704,93 +3747,65 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } else y = (cl->curVal() - min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = oldY = mapy(trackY+trackH-1 - 2 - y * trackH); + eventY = eventOldY = mapy(trackY+trackH-1 - 2 - y * trackH); } - else + else // we have automation, loop through it { for (; ic !=cl->end(); ic++) { double y = ic->second.val; if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume - y = logToVal(y, min, max); // represent volume between 0 and 1 + y = logToVal(y, min, max); // represent volume between 0 and 1 if (y < 0) y = 0; } else y = (y-min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = mapy(trackY + trackH - 2 - y * trackH); - xpixel = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); + eventY = mapy(trackY + trackH - 2 - y * trackH); + eventX = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); - if (oldY==-1) oldY = ypixel; + if (eventOldY==-1) eventOldY = eventY; - bool foundIt=false; - if (addNewCtrl) { - double firstX=oldX; - double lastX=xpixel; - double firstY=oldY; - double lastY = discrete ? oldY : ypixel; - - double proportion = (currX-firstX)/(lastX-firstX); - - if((currX < oldX) || (currX > lastX) || (firstX==lastX) ) - { - oldX = xpixel; - oldY = ypixel; - continue; // not the right region - } - - // 10 X(15) 20 - // proportion = 0.5 - // 10 - // / - // Y(5) - // / - // 1 - double calcY = (lastY-firstY)*proportion+firstY; - if(ABS(calcY-currY) < circumference || (xpixel == oldX && ABS(currX-xpixel) < circumference)) - foundIt=true; - - } else { - int x1 = ABS(currX - xpixel) ; - int y1 = ABS(currY - ypixel); - if (x1 < circumference && y1 < circumference && pointer.x() > 0 && pointer.y() > 0) { - foundIt=true; - } - - } - oldX = xpixel; - oldY = ypixel; - - if (foundIt) { - QWidget::setCursor(Qt::CrossCursor); - if (addNewCtrl) { - //automation.currentCtrl = 0; + //if (addNewCtrl) { + bool onLine = checkIfOnLine(mouseX, mouseY, eventOldX,eventX, eventOldY, discrete? eventOldY:eventY, circumference); + bool onPoint = false; + if ( pointer.x() > 0 && pointer.y() > 0) + onPoint = checkIfNearPoint(mouseX, mouseY, eventX, eventY, circumference); + + eventOldX = eventX; + eventOldY = eventY; + + if (onLine) { + if (!onPoint) { + QWidget::setCursor(Qt::CrossCursor); automation.currentCtrlValid = false; automation.controllerState = addNewController; }else { - automation.currentCtrlFrame = ic->second.frame; + QWidget::setCursor(Qt::OpenHandCursor); + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(ic->second.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; } automation.currentCtrlList = cl; automation.currentTrack = t; + update(); return; } } } - if (addNewCtrl) { - // check if we are reasonably close to a line, we only need to check Y - // as the line is straight after the last controller - //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); - if(currX >= xpixel && ypixel == oldY && ABS(currY-ypixel) < circumference) { - QWidget::setCursor(Qt::CrossCursor); - automation.controllerState = addNewController; - automation.currentCtrlList = cl; - automation.currentTrack = t; - automation.currentCtrlValid = false; - return; - } + // we are now after the last existing controller + // check if we are reasonably close to a line, we only need to check Y + // as the line is straight after the last controller + //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); + if(mouseX >= eventX && eventY == eventOldY && ABS(mouseY-eventY) < circumference) { + QWidget::setCursor(Qt::CrossCursor); + automation.controllerState = addNewController; + automation.currentCtrlList = cl; + automation.currentTrack = t; + automation.currentCtrlValid = false; + return; } } // if there are no hits we default to clearing all the data @@ -3798,6 +3813,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo automation.currentCtrlValid = false; automation.currentCtrlList = 0; automation.currentTrack = 0; + automation.currentCtrlFrameList.clear(); setCursor(); } @@ -3820,10 +3836,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) } // automation.moveController is set, lets rock. - int prevFrame = 0; int nextFrame = -1; - int currFrame = 0; if (automation.controllerState == addNewController) { @@ -3835,7 +3849,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; if (cv.frame == frame) { - automation.currentCtrlFrame = cv.frame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(cv.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; break; @@ -3849,9 +3864,9 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; - if (cv.frame == automation.currentCtrlFrame) + if (automation.currentCtrlFrameList.contains(cv.frame)) { - currFrame = cv.frame; + //currFrame = cv.frame; break; } prevFrame = cv.frame; @@ -3885,7 +3900,7 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) automation.currentCtrlList->range(&min,&max); double cvval; if (automation.currentCtrlList->valueType() == MusECore::VAL_LOG ) { // use db scale for volume - printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); + //printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); cvval = valToLog(yfraction, min, max); if (cvval< min) cvval=min; if (cvval>max) cvval=max; @@ -3900,7 +3915,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) if (cvval>max) cvval=max; } - automation.currentCtrlFrame = newFrame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(newFrame); automation.currentCtrlValid = true; if(icc != automation.currentCtrlList->end()) -- cgit v1.2.3