diff options
author | Tim E. Real <termtech@rogers.com> | 2011-08-16 07:40:48 +0000 |
---|---|---|
committer | Tim E. Real <termtech@rogers.com> | 2011-08-16 07:40:48 +0000 |
commit | 96cd2ef23505deaadb030ea0f1ef284e8a753452 (patch) | |
tree | 8c77de1c9dabb19f57cd2f41341b23c03981038c | |
parent | 6ea3ca331aeef0b0702ff2d3c3e529cd226c5d8b (diff) |
More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now).
Much drawing changed to device (pixel) space instead of virtual space, for accuracy.
Fixed display of audio automation graphs. (But not editing).
-rw-r--r-- | muse2/ChangeLog | 4 | ||||
-rw-r--r-- | muse2/muse/app.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.cpp | 457 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.h | 2 | ||||
-rw-r--r-- | muse2/muse/arranger/tlist.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/ctrl/ctrlcanvas.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/master/master.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/midiedit/dcanvas.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/midiedit/dlist.cpp | 12 | ||||
-rw-r--r-- | muse2/muse/midiedit/drumedit.cpp | 2 | ||||
-rw-r--r-- | muse2/muse/midiedit/pianoroll.cpp | 2 | ||||
-rw-r--r-- | muse2/muse/midiedit/prcanvas.cpp | 155 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 2 | ||||
-rw-r--r-- | muse2/muse/widgets/canvas.cpp | 31 | ||||
-rw-r--r-- | muse2/muse/widgets/view.cpp | 142 | ||||
-rw-r--r-- | muse2/muse/widgets/view.h | 1 |
16 files changed, 563 insertions, 264 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog index e9be48f4..562361c7 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,7 @@ +16.08.2011: + - More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). (Tim p4.0.30) + Much drawing changed to device (pixel) space instead of virtual space, for accuracy. + - Fixed display of audio automation graphs. (But not editing). (Tim) 15.08.2011: - Remodel the Meter and the VerticalMeter (Orcan) 13.08.2011: diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 3abb116f..2227e7b0 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -1849,7 +1849,7 @@ void MusE::closeEvent(QCloseEvent* event) n = QMessageBox::warning(this, appName, tr("The current Project contains unsaved data\n" "Save Current Project?"), - tr("&Save"), tr("&Skip"), tr("&Cancel"), 0, 2); + tr("&Save"), tr("S&kip"), tr("&Cancel"), 0, 2); if (n == 0) { if (!save()) // dont quit if save failed { @@ -3212,7 +3212,7 @@ bool MusE::clearSong(bool clear_all) tr("The current Project contains unsaved data\n" "Load overwrites current Project:\n" "Save Current Project?"), - tr("&Save"), tr("&Skip"), tr("&Abort"), 0, 2); + tr("&Save"), tr("S&kip"), tr("&Abort"), 0, 2); switch (n) { case 0: if (!save()) // abort if save failed diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 402e8035..82f2de45 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -70,17 +70,9 @@ NPart::NPart(Part* e) : CItem(Event(), e) leftBorderTouches = false; rightBorderTouches = false; - int th = track()->height(); int y = track()->y(); - - ///setPos(QPoint(e->tick(), y + 1)); setPos(QPoint(e->tick(), y)); - - ///setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); - // NOTE: For adjustable border size: If using a two-pixel border width while drawing, use second line. - // If one-pixel width, use first line. Tim. - //setBBox(QRect(e->tick(), y, e->lenTick(), th)); - setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); + setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); } //--------------------------------------------------------- @@ -1727,22 +1719,24 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) if((unsigned int)to > part->lenTick()) to = part->lenTick(); + bool clone = part->events()->arefCount() > 1; + QBrush brush; + + QRect r = item->bbox(); + // Compensation required for two pixel wide border. FIXME Prefer to do this after the map, but r is needed below. + r.moveTop(r.y() + rmapyDev(1)); + //QRect rr = p.transform().mapRect(r); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(r); // Use our own map instead. + // Item bounding box x is in tick coordinates, same as rectangle. - if(item->bbox().intersect(rect).isNull()) + //if(item->bbox().intersect(rect).isNull()) + //if((item->bbox() & rect).isNull()) + if((rr & map(rect)).isNull()) { //printf("PartCanvas::drawItem rectangle is null\n"); return; } - QRect r = item->bbox(); - bool clone = part->events()->arefCount() > 1; - QBrush brush; - - //QRect rr = map(r); // Produced inconsistent positions. FIXME - //QRect rr = p.transform().mapRect(r); // Same. - QRect rr(QPoint(mapx(r.x()), mapy(r.y())), - QPoint(mapx(r.x() + r.width()) - 1, mapy(r.y() + r.height() - 1))); // Test OK so far. - //printf("PartCanvas::drawItem called map rx:%d rw:%d rrx:%d rrw:%d\n", r.x(), r.width(), rr.x(), rr.width()); //printf("PartCanvas::drawItem called map rx:%d rw:%d\n", r.x(), r.width()); @@ -1762,9 +1756,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int xs_2 = xs_0 + 2; if(xs_2 > xe_0) xs_2 = xe_0; - int xs_6 = xs_0 + 6; - if(xs_6 > xe_0) - xs_6 = xe_0; + int xs_j = xs_0 + 8; + if(xs_j > xe_0) + xs_j = xe_0; int xe_1 = xe_0 - 1; if(xe_1 < xs_0) @@ -1772,11 +1766,11 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int xe_2 = xe_0 - 2; if(xe_2 < xs_0) xe_2 = xs_0; - int xe_6 = xe_0 - 6; - if(xe_6 < xs_0) - xe_6 = xs_0; + int xe_j = xe_0 - 8; + if(xe_j < xs_0) + xe_j = xs_0; - int ys_0 = rr.y(); + int ys_0 = rr.y(); int ye_0 = ys_0 + rr.height(); int ys_1 = ys_0 + 1; if(ys_1 > ye_0) @@ -1784,6 +1778,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int ys_2 = ys_0 + 2; if(ys_2 > ye_0) ys_2 = ye_0; + int ys_3 = ys_0 + 3; + if(ys_3 > ye_0) + ys_3 = ye_0; int ye_1 = ye_0 - 1; if(ye_1 < ys_0) @@ -1834,13 +1831,14 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int h = rr.height(); double s = double(h) / 4.0; - int y0 = rr.y(); - int y1 = y0 + lrint(s); + int y0 = ys_0; + //int y1 = y0 + lrint(s); int y2 = y0 + lrint(s * 2.0); - int y3 = y0 + lrint(s * 3.0); + //int y3 = y0 + lrint(s * 3.0); int y4 = y0 + h; - QPoint points[16]; + //QPoint points[12]; + QPoint points[8]; int pts; // @@ -1854,41 +1852,62 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) pts = 0; if(het == (Part::LeftEventsHidden | Part::RightEventsHidden)) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); - points[pts++] = QPoint(xe_6, y1); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y3); + points[pts++] = QPoint(xe_j, y2); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); - points[pts++] = QPoint(xs_6, y3); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y1); + points[pts++] = QPoint(xs_j, y2); + p.drawConvexPolygon(points, pts); // Help says may be faster on some platforms (X11). } else if(het == Part::LeftEventsHidden) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); - points[pts++] = QPoint(xs_6, y3); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y1); + points[pts++] = QPoint(xs_j, y2); + p.drawConvexPolygon(points, pts); } else if(het == Part::RightEventsHidden) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + points[pts++] = QPoint(xs_0, y0); points[pts++] = QPoint(xe_0, y0); - - points[pts++] = QPoint(xe_6, y1); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y3); + points[pts++] = QPoint(xe_j, y2); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } @@ -1904,30 +1923,40 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) //else // color_brightness=32; // otherwise use dark color if ((brightness >= 12000 && !part->selected())) - color_brightness=32; // too light: use dark color + color_brightness=96; //0; // too light: use dark color else - color_brightness=223; // too dark: use lighter color + color_brightness=180; //255; // too dark: use lighter color QColor c(color_brightness,color_brightness,color_brightness, config.globalAlphaBlend); p.setBrush(QBrush(gGradientFromQColor(c, rr.topLeft(), rr.bottomLeft()))); //p.setBrush(QBrush(c)); if(het & Part::RightEventsHidden) { pts = 0; + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y1); + points[pts++] = QPoint(xe_0, y0); points[pts++] = QPoint(xe_0, y4); - points[pts++] = QPoint(xe_6, y3); - points[pts++] = QPoint(xe_0, y2); - points[pts++] = QPoint(xe_6, y1); + points[pts++] = QPoint(xe_j, y2); + p.drawConvexPolygon(points, pts); } if(het & Part::LeftEventsHidden) { pts = 0; + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xs_j, y1); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y4); + points[pts++] = QPoint(xs_0, y0); - points[pts++] = QPoint(xs_6, y1); - points[pts++] = QPoint(xs_0, y2); - points[pts++] = QPoint(xs_6, y3); + points[pts++] = QPoint(xs_j, y2); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } } @@ -1985,14 +2014,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) // Now draw the borders, using custom segments... // - // FIXME NOTE: For 1-pixel wide lines, setting pen style to anything other than solid didn't work out well. - // Much too screwy - the single-width lines kept getting shifted one pixel over intermittently. - // I tried EVERYTHING to make sure x is proper but the painter keeps shifting them over. - // Meanwhile the fills are correct. Seems painter doesn't like line patterns, whether stock or custom. - // Therefore I was forced to manually draw the left and right segments. - // It works. Which seems to be more proof that painter is handling line patterns and pen widths badly... - // DO NOT ERASE COMMENTED CODE BELOW for now, in case it can be fixed. Tim. p4.0.29 - p.setBrush(Qt::NoBrush); QColor pc((part->mute() || item->isMoving())? Qt::white : config.partColors[cidx]); @@ -2015,52 +2036,57 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) penNormal1V.setCosmetic(true); penNormal2V.setCosmetic(true); + //pc = Qt::white; + //pc = Qt::darkGray; + //QPen penHidden1(pc); + //QPen penHidden2(pc, 2.0); + //penHidden2.setCosmetic(true); + QVector<qreal> customDashPattern; + if(clone) { - customDashPattern << 4.0 << 8.0; + customDashPattern << 4.0 << 6.0; penSelect1H.setDashPattern(customDashPattern); penNormal1H.setDashPattern(customDashPattern); - //penSelect1V.setDashPattern(customDashPattern); - //penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashPattern(customDashPattern); + penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashOffset(2.0); + penNormal1V.setDashOffset(2.0); + //penHidden1.setDashPattern(customDashPattern); customDashPattern.clear(); - customDashPattern << 2.0 << 4.0; + customDashPattern << 2.0 << 3.0; penSelect2H.setDashPattern(customDashPattern); penNormal2H.setDashPattern(customDashPattern); - //penSelect2V.setDashPattern(customDashPattern); - //penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashPattern(customDashPattern); + penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashOffset(1.0); + penNormal2V.setDashOffset(1.0); + //penHidden2.setDashPattern(customDashPattern); } - pc = Qt::white; - QPen penHidden1(pc); - QPen penHidden2(pc, 2.0); - penHidden2.setCosmetic(true); - //customDashPattern.clear(); - //customDashPattern << 2.0 << 10.0; - //penHidden1.setDashPattern(customDashPattern); - //customDashPattern.clear(); - //customDashPattern << 1.0 << 5.0; - //penHidden2.setDashPattern(customDashPattern); - bool lbt = ((NPart*)item)->leftBorderTouches; bool rbt = ((NPart*)item)->rightBorderTouches; - QLine l1( lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top - //QLine l2(rbt?xe_1:xe_0, r.y() + (rbt?y_1:y_2) - 1, rbt?xe_1:xe_0, r.y() + r.height() - 1); // Right - QLine l3( lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom - //QLine l4(r.x(), r.y() + (lbt?y_1:y_2), r.x(), r.y() + r.height() - (lbt?y_1:y_2)); // Left + QLine l1(lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top + //QLine l2(rbt?xe_1:xe_0, rbt?ys_1:ys_2, rbt?xe_1:xe_0, rbt?ye_1:ye_2); // Right + QLine l2(rbt?xe_1:xe_0, ys_0, rbt?xe_1:xe_0, ye_0); // Right + QLine l3(lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom + //QLine l4(xs_0, lbt?ys_1:ys_2, xs_0, lbt?ye_1:ye_2); // Left + QLine l4(xs_0, ys_0, xs_0, ye_0); // Left - if(het & Part::RightEventsHidden) - p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2); - else + //if(het & Part::RightEventsHidden) + // p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2); + //else { if(((NPart*)item)->rightBorderTouches) p.setPen(part->selected() ? penSelect1V : penNormal1V); else p.setPen(part->selected() ? penSelect2V : penNormal2V); } - //p.drawLine(l2); // Right line + p.drawLine(l2); // Right line + /* int xx = rbt?xe_1:xe_0; if(clone) { @@ -2075,18 +2101,20 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } else p.drawLine(QPoint(xx, rbt?ys_1:ys_2), QPoint(xx, rbt?ye_1:ye_2)); // Right line + */ - if(het & Part::LeftEventsHidden) - p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2); - else + //if(het & Part::LeftEventsHidden) + // p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2); + //else { if(((NPart*)item)->leftBorderTouches) p.setPen(part->selected() ? penSelect1V : penNormal1V); else p.setPen(part->selected() ? penSelect2V : penNormal2V); } - //p.drawLine(l4); // Left line + p.drawLine(l4); // Left line + /* xx = xs_0; if(clone) { @@ -2101,6 +2129,7 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } else p.drawLine(QPoint(xx, lbt?ys_1:ys_2), QPoint(xx, lbt?ye_1:ye_2)); // Left line + */ p.setPen(part->selected() ? penSelect2H : penNormal2H); p.drawLine(l1); // Top line @@ -2133,8 +2162,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) p.setPen(Qt::white); p.drawText(tr, Qt::AlignBottom|Qt::AlignLeft, part->name()); } + p.restore(); - p.setWorldMatrixEnabled(true); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -2174,9 +2204,9 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi //else // color_brightness=64; // otherwise use dark color if (brightness >= 12000 && !pt->selected()) - color_brightness=64; // too bright: use dark color + color_brightness=64; // 96; // too bright: use dark color else - color_brightness=192; // too dark: use lighter color + color_brightness=190; //160; // too dark: use lighter color } else color_brightness=80; @@ -2392,8 +2422,10 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi void PartCanvas::drawWavePart(QPainter& p, const QRect& bb, WavePart* wp, const QRect& _pr) { - QRect rr = p.worldMatrix().mapRect(bb); - QRect pr = p.worldMatrix().mapRect(_pr); + //QRect rr = p.worldMatrix().mapRect(bb); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(bb); // Use our own map instead. + //QRect pr = p.worldMatrix().mapRect(_pr); + QRect pr = map(_pr); p.save(); p.resetTransform(); @@ -3066,9 +3098,22 @@ void PartCanvas::viewDropEvent(QDropEvent* event) void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) { int x = rect.x(); - int y = rect.y(); + //int y = rect.y(); int w = rect.width(); - int h = rect.height(); + //int h = rect.height(); + + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //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. + + p.save(); + p.setWorldMatrixEnabled(false); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); ////////// // GRID // @@ -3086,13 +3131,17 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) AL::sigmap.tickValues(x, &bar, &beat, &tick); for (;;) { int xt = AL::sigmap.bar2tick(bar++, 0, 0); + //int xt = mapx(AL::sigmap.bar2tick(bar++, 0, 0)); if (xt >= x + w) + //if (xt >= mx + mw) break; if (!((bar-1) % 4)) p.setPen(baseColor.dark(115)); else p.setPen(baseColor); - p.drawLine(xt, y, xt, y+h); + //p.drawLine(xt, y, xt, y+h); + int xtm = mapx(xt); + p.drawLine(xtm, my, xtm, my+mh); // append int noDivisors=0; @@ -3118,20 +3167,28 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) noDivisors=noDivisors/2; } p.setPen(baseColor); + int xx; for (int t=1;t< noDivisors;t++) - p.drawLine(xt+r*t, y, xt+r*t, y+h); + { + //p.drawLine(xt+r*t, y, xt+r*t, y+h); + xx = mapx(xt + r * t); + p.drawLine(xx, my, xx, my+mh); + } } } } + //-------------------------------- // horizontal lines //-------------------------------- TrackList* tl = song->tracks(); - int yy = 0; + //int yy = 0; + int yy = -rmapy(yorg) - ypos; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); @@ -3140,22 +3197,46 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (config.canvasShowGrid && (track->isMidiTrack() || track->type() == Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - p.drawLine(x, yy + th, x + w, yy + th); // Tim. - p.setPen(baseColor); - } - if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { - QRect r = rect & QRect(x, yy, w, track->height()); - drawAudioTrack(p, r, (AudioTrack*)track); - p.setPen(baseColor); + //p.drawLine(x, yy + th, x + w, yy + th); + p.drawLine(mx, yy + th, mx + mw, yy + th); + //p.setPen(baseColor); } - if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - - } - yy += track->height(); + + // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). + // The 'corrupt drawing' bug of drawAudioTrack was actually because the recently added gradient + // used the update rectangle, so the gradient was also being clipped at 0,0. + // One could remove that limiter, but no, that is the correct way. So instead let's construct a + // 'pseudo bounding box' (half update rectangle, half bounding box), un-clipped. The gradient needs this! + // + // Here is a different situation than PartCanvas::drawItem which uses un-clipped part bounding boxes and + // 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)) + { + if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAudioTrack(p, mr, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + + // 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() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + //p.setWorldMatrixEnabled(false); + */ } + yy += th; + } + + p.restore(); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -3163,36 +3244,55 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - int x = rect.x(); - int y = rect.y(); - int w = rect.width(); - int h = rect.height(); + //int x = rect.x(); + //int y = rect.y(); + //int w = rect.width(); + //int h = rect.height(); + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //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. + + //printf("PartCanvas::drawTopItem x:%d y:%d w:%d h:%d\n", rect.x(), rect.y(), rect.width(), rect.height()); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + QColor baseColor(config.partCanvasBg.light(104)); - p.setPen(baseColor); + //p.setPen(baseColor); + p.save(); + p.setWorldMatrixEnabled(false); + TrackList* tl = song->tracks(); - int yy = 0; + int yoff = -rmapy(yorg) - ypos; + //int yy = 0; + int yy = yoff; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); if (!th) continue; if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - + //QRect r = rect & QRect(x, yy, w, track->height()); + QRect r(mx, yy, mw, th); + if(r.intersects(mr)) + { + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } } - yy += track->height(); + //yy += track->height(); + yy += th; } - QRect rr = p.worldMatrix().mapRect(rect); - - unsigned int startPos = audio->getStartRecordPos().tick(); if (song->punchin()) startPos=song->lpos(); @@ -3200,38 +3300,47 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int width = mapx(song->cpos()) - mapx(startPos); if (song->cpos() < startPos) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are before punch out } if (song->punchout() && song->cpos() > song->rpos()) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are beyond punch out. } - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); // write recording while it happens to get feedback // should be enhanced with solution that draws waveform also - int yPos=0; + //int yPos=0; + int yPos = yoff; if (song->record() && audio->isPlaying()) { for (iTrack it = tl->begin(); it != tl->end(); ++it) { Track* track = *it; + th = track->height(); + if (!th) + continue; if (track->recordFlag()) { QPen pen(Qt::black, 0, Qt::SolidLine); p.setPen(pen); QColor c(config.partColors[0]); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+track->height())); + QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+th)); gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); QBrush cc(gradient); p.setBrush(cc); - p.drawRect(startx,yPos, width, track->height()); + p.drawRect(startx,yPos, width, th); } - yPos+=track->height(); + yPos+=th; } } p.restore(); + //p.setWorldMatrixEnabled(true); // draw midi events on yPos=0; @@ -3275,53 +3384,71 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) } } - } //--------------------------------------------------------- // drawAudioTrack //--------------------------------------------------------- -void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* /* t */) +void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox, AudioTrack* /*t*/) { - // NOTE: For one-pixel border use first line and don't bother with setCosmetic. - // For a two-pixel border use second line and MUST use setCosmetic! Tim. - QPen pen(Qt::black, 0, Qt::SolidLine); - //p.setPen(QPen(Qt::black, 2, Qt::SolidLine)); - //pen.setCosmetic(true); - p.setPen(pen); - //p.setBrush(Qt::gray); - + QRect mr = r & bbox; + if(mr.isNull()) + return; + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + int mex = bbox.x(); + int mey = bbox.y(); + //int mew = bbox.width(); + int meh = bbox.height(); + + p.setPen(Qt::black); QColor c(Qt::gray); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + //QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + QLinearGradient gradient(mex + 1, mey + 1, mex + 1, mey + meh - 1); // Inside the border gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); - QBrush cc(gradient); - p.setBrush(cc); - p.drawRect(r); - - // Factor in pen stroking size: - //QRect rr(r); - //rr.setHeight(rr.height() -1); + QBrush brush(gradient); + p.fillRect(mr, brush); // p4.0.30 ... -// p.fillRect(r, cc); + //int xx = -rmapx(xorg) - xpos; + //printf("PartCanvas::drawAudioTrack x:%d y:%d w:%d h:%d th:%d xx:%d\n", r.x(), r.y(), r.width(), r.height(), t->height(), xx); + //if(r.x() <= xx) + // p.drawLine(r.x(), r.y(), r.x(), r.y() + r.height()); // The left edge + //p.drawLine(r.x(), r.y(), r.x() + r.width(), r.y()); // The top edge + //p.drawLine(r.x(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height()); // The bottom edge + + if(mex >= mx && mex <= mx + mw) + p.drawLine(mex, my, mex, my + mh - 1); // The left edge + //if(mex + mew >= mx && mex + mew <= mx + mw) + // p.drawLine(mex + mew, my, mex + mew, my + mh - 1); // The right edge. Not used - infinite to the right + if(mey >= my && mey <= my + mh) + p.drawLine(mx, mey, mx + mw - 1, mey); // The top edge + if(mey + meh >= my && mey + meh <= my + mh) + p.drawLine(mx, mey + meh, mx + mw - 1, mey + meh); // The bottom edge. Special for Audio track - draw one past bottom. } //--------------------------------------------------------- // drawAutomation //--------------------------------------------------------- -void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) +void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, AudioTrack *t) { - QRect rr = p.worldMatrix().mapRect(r); + ///QRect rr = p.worldMatrix().mapRect(r); - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); int height=rr.bottom()-rr.top()-4; // limit height + //printf("PartCanvas::drawAutomation x:%d y:%d w:%d h:%d height:%d\n", rr.x(), rr.y(), rr.width(), rr.height(), height); + + p.setBrush(Qt::NoBrush); + CtrlListList* cll = t->controller(); - bool firstRun=true; + ///bool firstRun=true; for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) { //iCtrlList *icl = icll->second; @@ -3332,7 +3459,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) iCtrl ic=cl->begin(); if (!cl->isVisible()) continue; // skip this iteration if this controller isn't in the visible list - p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + ///p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + p.setPen(QPen(cl->color(), 0, Qt::SolidLine)); // First check that there ARE automation, ic == cl->end means no automation if (ic != cl->end()) { @@ -3358,6 +3486,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-2)-prevVal*height-1, 3, 3); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); + bool firstRun=true; for (; ic !=cl->end(); ++ic) { CtrlVal cv = ic->second; @@ -3378,6 +3507,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) } int currentPixel = mapx(tempomap.frame2tick(cv.frame)); + //printf(" line x1:%d x2:%d prevVal:%f nextVal:%f\n", leftX, currentPixel, prevVal, nextVal); p.drawLine( leftX, (rr.bottom()-2)-prevVal*height, currentPixel, @@ -3390,20 +3520,23 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) prevPosFrame=cv.frame; prevVal=nextVal; if (currentPixel > rr.x()+ rr.width()) - goto quitDrawing; + ///goto quitDrawing; + break; // draw a square around the point p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); } + //printf(" endline prevVal:%f\n", prevVal); p.drawLine(mapx(tempomap.frame2tick(prevPosFrame)), (rr.bottom()-2)-prevVal*height, rr.x()+rr.width(), (rr.bottom()-2)-prevVal*height); } } -quitDrawing: - p.restore(); +///quitDrawing: + ///p.restore(); + return; } diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index 5f0aabae..05f380e6 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -115,7 +115,7 @@ class PartCanvas : public Canvas { //void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, const QRect& r, int pTick, int from, int to); void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, MidiPart*pt, const QRect& r, int pTick, int from, int to); Track* y2Track(int) const; - void drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* track); + void drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox, AudioTrack* track); void drawAutomation(QPainter& p, const QRect& r, AudioTrack* track); void drawTopItem(QPainter& p, const QRect& rect); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index d7cda62f..6fe2f31d 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -227,8 +227,7 @@ void TList::paint(const QRect& r) for (int index = 0; index < header->count(); ++index) { int section = header->logicalIndex(index); int w = header->sectionSize(section); - //QRect r = p.xForm(QRect(x+2, yy, w-4, trackHeight)); - QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, trackHeight)); + QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, trackHeight)); switch (section) { case COL_RECORD: diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 678cd823..68e29f20 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -25,9 +25,6 @@ #include "ctrlpanel.h" #include "midiedit/drummap.h" -extern void drawTickRaster(QPainter& p, int x, int y, - int w, int h, int quant); - static MidiCtrlValList veloList(CTRL_VELOCITY); // dummy //--------------------------------------------------------- diff --git a/muse2/muse/master/master.cpp b/muse2/muse/master/master.cpp index 4a33a8c4..6293e64c 100644 --- a/muse2/muse/master/master.cpp +++ b/muse2/muse/master/master.cpp @@ -22,9 +22,6 @@ #include "icons.h" #include "audio.h" -extern void drawTickRaster(QPainter& p, int x, int y, - int w, int h, int quant); - //--------------------------------------------------------- // Master //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 578e2616..d4ee9999 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -158,7 +158,7 @@ Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; - int diff = ip2c->second.xdiff; + //int diff = ip2c->second.xdiff; if (opart->hasHiddenEvents()) { @@ -465,8 +465,6 @@ void DrumCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect) // drawCanvas //--------------------------------------------------------- -extern void drawTickRaster(QPainter& p, int, int, int, int, int); - void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect) { int x = rect.x(); diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index 66922e83..d2d5659c 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -52,15 +52,18 @@ void DList::draw(QPainter& p, const QRect& rect) // else // p.eraseRect(x, yy, w, TH); QHeaderView *h = header; + p.save(); + p.setWorldMatrixEnabled(false); for (int k = 0; k < h->count(); ++k) { int x = h->sectionPosition(k); int w = h->sectionSize(k); - QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); + //QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect r = map(QRect(x+2, yy, w-4, TH)); // Use our own map instead. QString s; int align = Qt::AlignVCenter | Qt::AlignHCenter; - p.save(); - p.setWorldMatrixEnabled(false); + //p.save(); + //p.setWorldMatrixEnabled(false); switch (k) { case COL_VOL: s.setNum(dm->vol); @@ -114,8 +117,9 @@ void DList::draw(QPainter& p, const QRect& rect) } if (!s.isEmpty()) p.drawText(r, align, s); - p.restore(); + //p.restore(); } + p.restore(); } //--------------------------------------------------- diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 1e678432..ee610683 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -229,7 +229,7 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini signalMapper->setMapping(nextAction, DrumCanvas::CMD_SELECT_NEXT_PART); // Functions - menuFunctions = menuBar()->addMenu(tr("&Functions")); + menuFunctions = menuBar()->addMenu(tr("Fu&nctions")); menuFunctions->setTearOffEnabled(true); diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp index b2fe55ee..9ab5e063 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -174,7 +174,7 @@ PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned i connect(colorMapper, SIGNAL(mapped(int)), this, SLOT(eventColorModeChanged(int))); - menuFunctions = menuBar()->addMenu(tr("&Functions")); + menuFunctions = menuBar()->addMenu(tr("Fu&nctions")); menuFunctions->setTearOffEnabled(true); diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index eba1a13c..9e99f24d 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -37,6 +37,7 @@ #include "song.h" #include "audio.h" #include "functions.h" +#include "gconfig.h" #define CHORD_TIMEOUT 75 @@ -101,7 +102,7 @@ PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy) int PianoCanvas::pitch2y(int pitch) const { int tt[] = { - 5, 12, 19, 26, 33, 44, 51, 58, 64, 71, 78, 85 + 5, 13, 19, 26, 34, 44, 52, 58, 65, 71, 78, 85 }; int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12)); if (y < 0) @@ -146,9 +147,23 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, QRect r = item->bbox(); if(!virt()) r.moveCenter(map(item->pos())); - r = r.intersected(rect); - if(!r.isValid()) + + //QRect rr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(rect); // Use our own map instead. + QRect mer = map(r); + + ///r = r.intersected(rect); + //QRect rr = r & rect; + ///if(!r.isValid()) + //if(!rr.isValid()) + // return; + QRect mr = rr & mer; + //if(!mr.isValid()) + if(mr.isNull()) return; + + //p.save(); + p.setPen(Qt::black); struct Triple { int r, g, b; @@ -169,25 +184,25 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, { 0xff, 0xbf, 0x7a } }; + QColor color; NEvent* nevent = (NEvent*) item; Event event = nevent->event(); if (nevent->part() != curPart){ if(item->isMoving()) - p.setBrush(Qt::gray); + color = Qt::gray; else if(item->isSelected()) - p.setBrush(Qt::black); + color = Qt::black; else - p.setBrush(Qt::lightGray); + color = Qt::lightGray; } else { if (item->isMoving()) { - p.setBrush(Qt::gray); + color = Qt::gray; } else if (item->isSelected()) { - p.setBrush(Qt::black); + color = Qt::black; } else { - QColor color; color.setRgb(0, 0, 255); switch(colorMode) { case 0: @@ -208,10 +223,50 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, } break; } - p.setBrush(color); } } - p.drawRect(r); + + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + int mex = mer.x(); + int mey = mer.y(); + int mew = mer.width(); + int meh = mer.height(); + //int mfx = mx; + //if(mfx == mex) mfx += 1; + //int mfy = my; + //if(mfy == mey) mfy += 1; + //int mfw = mw; + //if(mfw == mew) mfw -= 1; + //if(mfx == mex) mfw -= 1; + //int mfh = mh; + //if(mfh == meh) mfh -= 1; + //if(mfy == mey) mfh -= 1; + color.setAlpha(config.globalAlphaBlend); + //QLinearGradient gradient(mex + 1, mey + 1, mex + 1, mey + meh - 2); // Inside the border + //gradient.setColorAt(0, color); + //gradient.setColorAt(1, color.darker()); + //QBrush brush(gradient); + QBrush brush(color); + p.fillRect(mr, brush); + //p.fillRect(mfx, mfy, mfw, mfh, brush); + + if(mex >= mx && mex <= mx + mw) + p.drawLine(mex, my, mex, my + mh - 1); // The left edge + if(mex + mew >= mx && mex + mew <= mx + mw) + p.drawLine(mex + mew, my, mex + mew, my + mh - 1); // The right edge + if(mey >= my && mey <= my + mh) + p.drawLine(mx, mey, mx + mw - 1, mey); // The top edge + if(mey + meh >= my && mey + meh <= my + mh) + p.drawLine(mx, mey + meh - 1, mx + mw - 1, mey + meh - 1); // The bottom edge + + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //p.restore(); } //--------------------------------------------------------- @@ -314,7 +369,7 @@ Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; - int diff = ip2c->second.xdiff; + //int diff = ip2c->second.xdiff; if (opart->hasHiddenEvents()) { @@ -682,48 +737,6 @@ void PianoCanvas::pianoReleased(int pitch, bool) } //--------------------------------------------------------- -// drawTickRaster -//--------------------------------------------------------- - -void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) - { - int bar1, bar2, beat; - unsigned tick; - AL::sigmap.tickValues(x, &bar1, &beat, &tick); - AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); - ++bar2; - int y2 = y + h; - for (int bar = bar1; bar < bar2; ++bar) { - unsigned x = AL::sigmap.bar2tick(bar, 0, 0); - p.setPen(Qt::black); - p.drawLine(x, y, x, y2); - int z, n; - AL::sigmap.timesig(x, z, n); - ///int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x(); - int q = p.combinedTransform().map(QPoint(raster, 0)).x() - p.combinedTransform().map(QPoint(0, 0)).x(); - int qq = raster; - if (q < 8) // grid too dense - qq *= 2; - p.setPen(Qt::lightGray); - if (raster>=4) { - int xx = x + qq; - int xxx = AL::sigmap.bar2tick(bar, z, 0); - while (xx <= xxx) { - p.drawLine(xx, y, xx, y2); - xx += qq; - } - xx = xxx; - } - p.setPen(Qt::gray); - for (int beat = 1; beat < z; beat++) { - int xx = AL::sigmap.bar2tick(bar, beat, 0); - p.drawLine(xx, y, xx, y2); - } - - } - } - -//--------------------------------------------------------- // draw //--------------------------------------------------------- @@ -734,31 +747,63 @@ void PianoCanvas::drawCanvas(QPainter& p, const QRect& rect) int w = rect.width(); int h = rect.height(); + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //int mx = mapx(x); + //int my = mapy(y); + //int mw = mapx(x + w) - mx; + //int mw = mapx(x + w) - mx - 1; + //int mh = mapy(y + h) - my; + //int mh = mapy(y + h) - my - 1; + + // p.save(); + // FIXME Can't get horizontal lines quite right yet. Draw in virtual space for now... + ///p.setWorldMatrixEnabled(false); + //--------------------------------------------------- // horizontal lines //--------------------------------------------------- int yy = ((y-1) / KH) * KH + KH; + //int yy = my + KH; + //int yy = ((my-1) / KH) * KH + KH; + //int yoff = -rmapy(yorg) - ypos; int key = 75 - (yy / KH); + + //printf("PianoCanvas::drawCanvas x:%d y:%d w:%d h:%d mx:%d my:%d mw:%d mh:%d yy:%d key:%d\n", x, y, w, h, mx, my, mw, mh, yy, key); + for (; yy < y + h; yy += KH) { + //for (; yy + yoff < my + mh; yy += KH) { + //for (; yy < my + mh; yy += KH) { switch (key % 7) { case 0: case 3: p.setPen(Qt::black); p.drawLine(x, yy, x + w, yy); + //p.drawLine(mx, yy + yoff, mx + mw, yy + yoff); + //p.drawLine(mx, yy, mx + mw, yy); break; default: p.fillRect(x, yy-3, w, 6, QBrush(QColor(230,230,230))); + //p.fillRect(mx, yy-3 + yoff, mw, 6, QBrush(QColor(230,230,230))); + //p.fillRect(mx, yy-3, mw, 6, QBrush(QColor(230,230,230))); break; } --key; } - + //p.restore(); + ///p.setWorldMatrixEnabled(true); + + //p.setWorldMatrixEnabled(false); + //--------------------------------------------------- // vertical lines //--------------------------------------------------- drawTickRaster(p, x, y, w, h, editor->raster()); + + //p.restore(); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index b6b2c6d9..4b2db2fc 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -419,7 +419,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) menu_mapper->setMapping(set_name_action, CMD_SET_NAME); - QMenu* functions_menu = menuBar()->addMenu(tr("&Functions")); + QMenu* functions_menu = menuBar()->addMenu(tr("Fu&nctions")); func_quantize_action = functions_menu->addAction(tr("&Quantize"), menu_mapper, SLOT(map())); func_notelen_action = functions_menu->addAction(tr("Change note &length"), menu_mapper, SLOT(map())); diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index c2c329a9..c7186a2d 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -380,13 +380,20 @@ void Canvas::draw(QPainter& p, const QRect& rect) // draw marker //--------------------------------------------------- - int y2 = y + h; + //p.save(); + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + + int my = mapy(y); + //int y2 = y + h; + int my2 = mapy(y + h); MarkerList* marker = song->marker(); for (iMarker m = marker->begin(); m != marker->end(); ++m) { int xp = m->second.tick(); if (xp >= x && xp < x+w) { p.setPen(Qt::green); - p.drawLine(xp, y, xp, y2); + //p.drawLine(xp, y, xp, y2); + p.drawLine(mapx(xp), my, mapx(xp), my2); } } @@ -395,16 +402,28 @@ void Canvas::draw(QPainter& p, const QRect& rect) //--------------------------------------------------- p.setPen(Qt::blue); + int mx; if (pos[1] >= unsigned(x) && pos[1] < unsigned(x2)) { - p.drawLine(pos[1], y, pos[1], y2); + //p.drawLine(pos[1], y, pos[1], y2); + mx = mapx(pos[1]); + p.drawLine(mx, my, mx, my2); + } + if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) { + //p.drawLine(pos[2], y, pos[2], y2); + mx = mapx(pos[2]); + p.drawLine(mx, my, mx, my2); } - if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) - p.drawLine(pos[2], y, pos[2], y2); p.setPen(Qt::red); if (pos[0] >= unsigned(x) && pos[0] < unsigned(x2)) { - p.drawLine(pos[0], y, pos[0], y2); + //p.drawLine(pos[0], y, pos[0], y2); + mx = mapx(pos[0]); + p.drawLine(mx, my, mx, my2); } + //p.restore(); + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //--------------------------------------------------- // draw lasso //--------------------------------------------------- diff --git a/muse2/muse/widgets/view.cpp b/muse2/muse/widgets/view.cpp index 49f559c6..57955c19 100644 --- a/muse2/muse/widgets/view.cpp +++ b/muse2/muse/widgets/view.cpp @@ -19,6 +19,8 @@ #include "math.h" +#include "al/sig.h" + // Don't use this, it was just for debugging. // It's much slower than muse-1 no matter how hard I tried. // The left/right pixmap shifters in seXPos setYPos @@ -494,26 +496,33 @@ void View::pdraw(QPainter& p, const QRect& r) int w = r.width(); int h = r.height(); if (xmag <= 0) { - x -= 1; + // TODO These adjustments are required, otherwise gaps. Tried, unable to remove them for now. p4.0.30 + x -= 1; w += 2; - x = (x + xpos + rmapx(xorg)) * (-xmag); + //x = (x + xpos + rmapx(xorg)) * (-xmag); + x = lrint((double(x + xpos) + rmapx_f(xorg)) * double(-xmag)); w = w * (-xmag); } else { - x = (x + xpos + rmapx(xorg)) / xmag; - w = (w + xmag - 1) / xmag; + //x = (x + xpos + rmapx(xorg)) / xmag; + x = lrint((double(x + xpos) + rmapx_f(xorg)) / double(xmag)); + //w = (w + xmag - 1) / xmag; + w = lrint(double(w) / double(xmag)); x -= 1; w += 2; } if (ymag <= 0) { y -= 1; h += 2; - y = (y + ypos + rmapy(yorg)) * (-ymag); + //y = (y + ypos + rmapy(yorg)) * (-ymag); + y = lrint((double(y + ypos) + rmapy_f(yorg)) * double(-ymag)); h = h * (-ymag); } else { - y = (y + ypos + rmapy(yorg)) / ymag; - h = (h + ymag - 1) / ymag; + //y = (y + ypos + rmapy(yorg)) / ymag; + y = lrint((double(y + ypos) + rmapy_f(yorg)) / double(ymag)); + //h = (h + ymag - 1) / ymag; + h = lrint(double(h) / double(ymag)); y -= 1; h += 2; } @@ -538,13 +547,93 @@ void View::setPainter(QPainter& p) p.resetMatrix(); // Q3 support says use resetMatrix instead, but resetMatrix advises resetTransform instead... //p.resetTransform(); - p.translate(double(-(xpos+rmapx(xorg))), double(-(ypos+rmapy(yorg)))); - double xMag = (xmag < 0) ? 1.0/(-xmag) : double(xmag); - double yMag = (ymag < 0) ? 1.0/(-ymag) : double(ymag); + //p.translate(double(-(xpos+rmapx(xorg))), double(-(ypos+rmapy(yorg)))); + p.translate( -(double(xpos) + rmapx_f(xorg)) , -(double(ypos) + rmapy(yorg))); + //double xMag = (xmag < 0) ? 1.0/(-xmag) : double(xmag); + //double yMag = (ymag < 0) ? 1.0/(-ymag) : double(ymag); + double xMag = (xmag < 0) ? 1.0/double(-xmag) : double(xmag); + double yMag = (ymag < 0) ? 1.0/double(-ymag) : double(ymag); p.scale(xMag, yMag); } //--------------------------------------------------------- +// drawTickRaster +//--------------------------------------------------------- + +void View::drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) + { + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //int mx = mapx(x); + int my = mapy(y); + //int mw = mapx(x + w) - mx; + //int mw = mapx(x + w) - mx - 1; + //int mh = mapy(y + h) - my; + //int mh = mapy(y + h) - my - 1; + + //p.save(); + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + + int xx,bar1, bar2, beat; + unsigned tick; + AL::sigmap.tickValues(x, &bar1, &beat, &tick); + AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); + ++bar2; + ///int y2 = y + h; + //int y2 = my + mh; + int y2 = mapy(y + h) - 1; + //printf("View::drawTickRaster x:%d y:%d w:%d h:%d mx:%d my:%d mw:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, mx, my, mw, mh, y2, bar1, bar2); + //printf("View::drawTickRaster x:%d y:%d w:%d h:%d my:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, my, mh, y2, bar1, bar2); + for (int bar = bar1; bar < bar2; ++bar) { + ///unsigned x = AL::sigmap.bar2tick(bar, 0, 0); + unsigned xb = AL::sigmap.bar2tick(bar, 0, 0); + int xt = mapx(xb); + p.setPen(Qt::black); + ///p.drawLine(x, y, x, y2); + p.drawLine(xt, my, xt, y2); + int z, n; + ///AL::sigmap.timesig(x, z, n); + AL::sigmap.timesig(xb, z, n); + ///int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x(); + ///int q = p.combinedTransform().map(QPoint(raster, 0)).x() - p.combinedTransform().map(QPoint(0, 0)).x(); + //int q = rmapx(raster); + int qq = raster; + //if (q < 8) // grid too dense + if (rmapx(raster) < 8) // grid too dense + qq *= 2; + p.setPen(Qt::lightGray); + if (raster>=4) { + ///int xx = x + qq; + //int xx = mapx(xb + qq); + xx = xb + qq; + int xxx = AL::sigmap.bar2tick(bar, z, 0); + //int xxx = mapx(AL::sigmap.bar2tick(bar, z, 0)); + while (xx <= xxx) { + ///p.drawLine(xx, y, xx, y2); + int x = mapx(xx); + p.drawLine(x, my, x, y2); + xx += qq; + //xx += rmapx(qq); + } + //xx = xxx; + } + p.setPen(Qt::gray); + for (int beat = 1; beat < z; beat++) { + ///int xx = AL::sigmap.bar2tick(bar, beat, 0); + xx = mapx(AL::sigmap.bar2tick(bar, beat, 0)); + //printf(" bar:%d z:%d beat:%d xx:%d\n", bar, z, beat, xx); + ///p.drawLine(xx, y, xx, y2); + p.drawLine(xx, my, xx, y2); + } + + } + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //p.restore(); + } + +//--------------------------------------------------------- // map //--------------------------------------------------------- @@ -681,29 +770,40 @@ int View::rmapyDev(int y) const QRect View::map(const QRect& r) const { - int x, y, w, h; + //int x, y, w, h; + double x, y, w, h; + int xx, yy, ww, hh; //printf("View::map xmag:%d xpos:%d xorg:%d\n", xmag, xpos, xorg); if (xmag < 0) { - x = lrint(double(r.x())/double(-xmag) - rmapx_f(xorg)) - xpos; - w = lrint(double(r.width()) / double(-xmag)); + //x = lrint(double(r.x())/double(-xmag) - rmapx_f(xorg)) - xpos; + x = double(r.x())/double(-xmag) - rmapx_f(xorg) - xpos; + //w = lrint(double(r.width()) / double(-xmag)); + w = double(r.width()) / double(-xmag); + xx = lrint(x); + ww = lrint(x + w) - xx; } else { - x = r.x()*xmag - xpos - lrint(rmapx_f(xorg)); - w = r.width() * xmag; + xx = r.x()*xmag - xpos - lrint(rmapx_f(xorg)); + ww = r.width() * xmag; } if (ymag < 0) { - y = lrint(double(r.y())/double(-ymag) - rmapy_f(yorg)) - ypos; - h = lrint(double(r.height()) / double(-ymag)); + //y = lrint(double(r.y())/double(-ymag) - rmapy_f(yorg)) - ypos; + y = double(r.y())/double(-ymag) - rmapy_f(yorg) - ypos; + //h = lrint(double(r.height()) / double(-ymag)); + h = double(r.height()) / double(-ymag); + yy = lrint(y); + hh = lrint(y + h) - yy; } else { - y = r.y()*ymag - ypos - lrint(rmapy_f(yorg)); - h = r.height() * ymag; + yy = r.y()*ymag - ypos - lrint(rmapy_f(yorg)); + hh = r.height() * ymag; } - return QRect(x, y, w, h); + return QRect(xx, yy, ww, hh); } QPoint View::map(const QPoint& p) const { + /* int x, y; if (xmag < 0) { x = lrint(double(p.x())/double(-xmag) - rmapx_f(xorg)) - xpos; @@ -718,6 +818,8 @@ QPoint View::map(const QPoint& p) const y = p.y()*ymag - ypos - lrint(rmapy_f(yorg)); } return QPoint(x, y); + */ + return QPoint(mapx(p.x()), mapy(p.y())); } int View::mapx(int x) const diff --git a/muse2/muse/widgets/view.h b/muse2/muse/widgets/view.h index ad0a6cf9..a932f173 100644 --- a/muse2/muse/widgets/view.h +++ b/muse2/muse/widgets/view.h @@ -50,6 +50,7 @@ class View : public QWidget { virtual void draw(QPainter&, const QRect&) {} virtual void drawOverlay(QPainter&) {} virtual QRect overlayRect() const { return QRect(0, 0, 0, 0); } + virtual void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster); virtual void pdraw(QPainter&, const QRect&); |