void Tie::slurPos(SlurPos* sp) { qreal hw = startNote()->headWidth(); qreal __up = _up ? -1.0 : 1.0; qreal _spatium = spatium(); Chord* sc = startNote()->chord(); Q_ASSERT(sc); sp->system1 = sc->measure()->system(); if (!sp->system1) { Measure* m = sc->measure(); qDebug("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount()); } Q_ASSERT(sp->system1); qreal xo; qreal yo; bool shortStart = false; // determine attachment points // similar code is used in Chord::layoutPitched() // to allocate extra space to enforce minTieLength // so keep these in sync //------p1 if ((sc->notes().size() > 1) || (sc->stem() && (sc->up() == _up))) { xo = startNote()->x() + hw * 1.12; yo = startNote()->pos().y() + hw * .3 * __up; shortStart = true; } else { xo = startNote()->x() + hw * 0.65; yo = startNote()->pos().y() + _spatium * .75 * __up; } sp->p1 = sc->pagePos() - sp->system1->pagePos() + QPointF(xo, yo); //------p2 if (endNote() == 0) { sp->p2 = sp->p1 + QPointF(_spatium * 3, 0.0); sp->system2 = sp->system1; return; } Chord* ec = endNote()->chord(); sp->system2 = ec->measure()->system(); if ((ec->notes().size() > 1) || (ec->stem() && !ec->up() && !_up)) xo = endNote()->x() - hw * 0.12; else if (shortStart) xo = endNote()->x() + hw * 0.15; else xo = endNote()->x() + hw * 0.35; sp->p2 = ec->pagePos() - sp->system2->pagePos() + QPointF(xo, yo); }
//--------------------------------------------------------- // oscColorNote //--------------------------------------------------------- void MuseScore::oscColorNote(QVariantList list) { qDebug() << list; if(!cs) return; if (list.length() != 2 && list.length() != 3) return; int tick; int pitch; QColor noteColor("red"); //default to red bool ok; tick = list[0].toInt(&ok); if (!ok) return; pitch = list[1].toInt(&ok); if (!ok) return; if(list.length() == 3 && list[2].canConvert(QVariant::String)) { QColor color(list[2].toString()); if(color.isValid()) noteColor = color; } Measure* measure = cs->tick2measure(tick); if(!measure) return; Segment* s = measure->findSegment(Segment::SegChordRest, tick); if (!s) return; //get all chords in segment... int n = cs->nstaves() * VOICES; for (int i = 0; i < n; i++) { Element* e = s->element(i); if (e && e->isChordRest()) { ChordRest* cr = static_cast<ChordRest*>(e); if(cr->type() == Element::CHORD) { Chord* chord = static_cast<Chord*>(cr); for (int idx = 0; idx < chord->notes().length(); idx++) { Note* note = chord->notes()[idx]; if (note->pitch() == pitch) { cs->startCmd(); cs->undo(new ChangeProperty(note, P_COLOR, noteColor)); cs->endCmd(); cs->end(); return; } } } } } }
Note* searchTieNote114(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->staff()->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; while ((seg = seg->next1(Segment::SegChordRest))) { for (int track = strack; track < etrack; ++track) { Chord* c = static_cast<Chord*>(seg->element(track)); if (c == 0 || (c->type() != Element::CHORD) || (c->track() != chord->track())) continue; int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
Element* Score::downAlt(Element* element) { Element* re = 0; if (element->type() == Element::REST) re = nextTrack(static_cast<Rest*>(element)); else if (element->type() == Element::NOTE) { Chord* chord = static_cast<Note*>(element)->chord(); const QList<Note*>& notes = chord->notes(); int idx = notes.indexOf(static_cast<Note*>(element)); if (idx > 0) { --idx; re = notes.value(idx); } else { re = nextTrack(chord); if (re->track() == chord->track()) re = element; } } if (re == 0) return 0; if (re->type() == Element::CHORD) re = static_cast<Chord*>(re)->notes().back(); return re; }
Element* Score::upAlt(Element* element) { Element* re = 0; if (element->type() == Element::Type::REST) re = prevTrack(static_cast<Rest*>(element)); else if (element->type() == Element::Type::NOTE) { Chord* chord = static_cast<Note*>(element)->chord(); const QList<Note*>& notes = chord->notes(); int idx = notes.indexOf(static_cast<Note*>(element)); if (idx < notes.size()-1) { ++idx; re = notes.value(idx); } else { re = prevTrack(chord); if (re->track() == chord->track()) re = element; } } if (re == 0) return 0; if (re->type() == Element::Type::CHORD) re = static_cast<Chord*>(re)->notes().front(); return re; }
void Ambitus::updateRange() { if (!segment()) return; Chord* chord; int firstTrack = track(); int lastTrack = firstTrack + VOICES-1; int pitchTop = -1000; int pitchBottom = 1000; int tpcTop = 0; // Initialized to prevent warning int tpcBottom = 0; // Initialized to prevent warning int trk; Measure* meas = segment()->measure(); Segment* segm = meas->findSegment(SegmentType::ChordRest, segment()->tick()); bool stop = meas->sectionBreak(); while (segm) { // moved to another measure? if (segm->measure() != meas) { // if section break has been found, stop here if (stop) break; // update meas and stop condition meas = segm->measure(); stop = meas->sectionBreak(); } // scan all relevant tracks of this segment for chords for (trk = firstTrack; trk <= lastTrack; trk++) { Element* e = segm->element(trk); if (!e || !e->isChord()) continue; chord = toChord(e); // update pitch range (with associated tpc's) for (Note* n : chord->notes()) { if (!n->play()) // skip notes which are not to be played continue; int pitch = n->ppitch(); if (pitch > pitchTop) { pitchTop = pitch; tpcTop = n->tpc(); } if (pitch < pitchBottom) { pitchBottom = pitch; tpcBottom = n->tpc(); } } } segm = segm->nextCR(); } if (pitchTop > -1000) { // if something has been found, update this _topPitch = pitchTop; _bottomPitch = pitchBottom; _topTpc = tpcTop; _bottomTpc = tpcBottom; } }
void Fingering::layout() { TextBase::layout(); if (autoplace() && note()) { Chord* chord = note()->chord(); Staff* staff = chord->staff(); Part* part = staff->part(); int n = part->nstaves(); bool voices = chord->measure()->hasVoices(staff->idx()); bool below = voices ? !chord->up() : (n > 1) && (staff->rstaff() == n-1); bool tight = voices && !chord->beam(); qreal x = 0.0; qreal y = 0.0; qreal headWidth = note()->bboxRightPos(); qreal headHeight = note()->headHeight(); qreal fh = headHeight; // TODO: fingering number height if (chord->notes().size() == 1) { x = headWidth * .5; if (below) { // place fingering below note y = fh + spatium() * .4; if (tight) { y += 0.5 * spatium(); if (chord->stem()) x += 0.5 * spatium(); } else if (chord->stem() && !chord->up()) { // on stem side y += chord->stem()->height(); x -= spatium() * .4; } } else { // place fingering above note y = -headHeight - spatium() * .4; if (tight) { y -= 0.5 * spatium(); if (chord->stem()) x -= 0.5 * spatium(); } else if (chord->stem() && chord->up()) { // on stem side y -= chord->stem()->height(); x += spatium() * .4; } } } else { x -= spatium(); } setUserOff(QPointF(x, y)); } }
void Tie::slurPos(SlurPos* sp) { Note* note1 = static_cast<Note*>(startElement()); qreal hw = note1->headWidth(); qreal __up = _up ? -1.0 : 1.0; qreal _spatium = spatium(); Chord* sc = note1->chord(); sp->system1 = sc->measure()->system(); qreal xo; qreal yo; //------p1 if ((sc->notes().size() > 1) || (sc->stem() && (sc->up() == _up))) { xo = note1->x() + hw * 1.12; yo = note1->pos().y() + hw * .3 * __up; } else { xo = note1->x() + hw * 0.85; yo = note1->pos().y() + _spatium * .75 * __up; } sp->p1 = sc->pagePos() - sp->system1->pagePos() + QPointF(xo, yo); //------p2 Note* note2 = static_cast<Note*>(endElement()); if (note2 == 0) { sp->p2 = sp->p1 + QPointF(_spatium * 3, 0.0); sp->system2 = sp->system1; return; } Chord* ec = note2->chord(); sp->system2 = ec->measure()->system(); if ((ec->notes().size() > 1) || (ec->stem() && !ec->up() && !_up)) xo = note2->x() - hw * 0.12; else xo = note2->x() + hw * 0.15; sp->p2 = ec->pagePos() - sp->system2->pagePos() + QPointF(xo, yo); }
void TestNote::grace() { Score* score = readScore(DIR + "grace.mscx"); score->doLayout(); Chord* chord = score->firstMeasure()->findChord(0, 0); Note* note = chord->upNote(); // create score->setGraceNote(chord, note->pitch(), NoteType::APPOGGIATURA, MScore::division/2); Chord* gc = chord->graceNotes().first(); Note* gn = gc->notes().first(); // Note* n = static_cast<Note*>(writeReadElement(gn)); // QCOMPARE(n->noteType(), NoteType::APPOGGIATURA); // delete n; // tie score->startCmd(); score->select(gn); score->cmdAddTie(); score->endCmd(); // n = static_cast<Note*>(writeReadElement(gn)); // QVERIFY(n->tieFor() != 0); // delete n; // tremolo score->startCmd(); Tremolo* tr = new Tremolo(score); tr->setTremoloType(TremoloType::R16); tr->setParent(gc); tr->setTrack(gc->track()); score->undoAddElement(tr); score->endCmd(); // Chord* c = static_cast<Chord*>(writeReadElement(gc)); // QVERIFY(c->tremolo() != 0); // delete c; // articulation score->startCmd(); Articulation* ar = new Articulation(score); ar->setArticulationType(ArticulationType::Sforzatoaccent); ar->setParent(gc); ar->setTrack(gc->track()); score->undoAddElement(ar); score->endCmd(); // c = static_cast<Chord*>(writeReadElement(gc)); // QVERIFY(c->articulations().size() == 1); // delete c; QVERIFY(saveCompareScore(score, "grace-test.mscx", DIR + "grace-ref.mscx")); }
bool isTied(const Segment *seg, int strack, int voice, Ms::Tie*(Note::*tieFunc)() const) { ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice)); if (cr && cr->type() == Element::Type::CHORD) { Chord *chord = static_cast<Chord *>(cr); const auto ¬es = chord->notes(); for (const Note *note: notes) { if ((note->*tieFunc)()) return true; } } return false; }
Note* searchTieNote(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->staff()->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; if (chord->isGraceBefore()) { chord = static_cast<Chord*>(chord->parent()); note2 = chord->findNote(note->pitch()); return note2; } QList<Chord*> gna; if (chord->getGraceNotesAfter(&gna)) { chord = gna[0]; note2 = chord->findNote(note->pitch()); return note2; } while ((seg = seg->next1(Segment::Type::ChordRest))) { for (int track = strack; track < etrack; ++track) { Chord* c = static_cast<Chord*>(seg->element(track)); if (c == 0 || c->type() != Element::Type::CHORD) continue; int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
Note* searchTieNote(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; if (chord->isGraceBefore()) { // grace before // try to tie to note in parent chord chord = toChord(chord->parent()); note2 = chord->findNote(note->pitch()); if (note2) return note2; } else if (chord->isGraceAfter()) { // grace after // we will try to tie to note in next normal chord, below // meanwhile, set chord to parent chord so the endTick calculation will make sense chord = toChord(chord->parent()); } else { // normal chord // try to tie to grace note after if present QVector<Chord*> gna = chord->graceNotesAfter(); if (!gna.empty()) { Chord* gc = gna[0]; note2 = gc->findNote(note->pitch()); if (note2) return note2; } } // at this point, chord is a regular chord, not a grace chord // and we are looking for a note in the *next* chord (grace or regular) // calculate end of current note duration // but err on the safe side in case there is roundoff in tick count int endTick = chord->tick() + chord->actualTicks() - 1; while ((seg = seg->next1(Segment::Type::ChordRest))) { // skip ahead to end of current note duration as calculated above // but just in case, stop if we find element in current track if (seg->tick() < endTick && !seg->element(chord->track())) continue; for (int track = strack; track < etrack; ++track) { Element* e = seg->element(track); if (e == 0 || !e->isChord()) continue; Chord* c = toChord(e); // if there are grace notes before, try to tie to first one QVector<Chord*> gnb = c->graceNotesBefore(); if (!gnb.empty()) { Chord* gc = gnb[0]; Note* gn2 = gc->findNote(note->pitch()); if (gn2) return gn2; } int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
void Fingering::layout() { if (parent()) { Fraction tick = parent()->tick(); const Staff* st = staff(); if (st && st->isTabStaff(tick) && !st->staffType(tick)->showTabFingering()) { setbbox(QRectF()); return; } } TextBase::layout(); rypos() = 0.0; // handle placement below if (autoplace() && note()) { Note* n = note(); Chord* chord = n->chord(); bool voices = chord->measure()->hasVoices(chord->staffIdx()); bool tight = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER; qreal headWidth = n->bboxRightPos(); // update offset after drag qreal rebase = 0.0; if (offsetChanged() != OffsetChange::NONE) rebase = rebaseOffset(); // temporarily exclude self from chord shape setAutoplace(false); if (layoutType() == ElementType::CHORD) { Stem* stem = chord->stem(); Segment* s = chord->segment(); Measure* m = s->measure(); qreal sp = spatium(); qreal md = minDistance().val() * sp; SysStaff* ss = m->system()->staff(chord->vStaffIdx()); Staff* vStaff = chord->staff(); // TODO: use current height at tick if (n->mirror()) rxpos() -= n->ipos().x(); rxpos() += headWidth * .5; if (placeAbove()) { if (tight) { if (chord->stem()) rxpos() -= 0.8 * sp; rypos() -= 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(false); sk.add(r.x(), r.bottom(), r.width()); qreal d = sk.minDistance(ss->skyline().north()); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd -= d + height() * .25; // force extra space above staff & chord (but not other fingerings) qreal top; if (chord->up() && chord->beam() && stem) { top = stem->y() + stem->bbox().top(); } else { Note* un = chord->upNote(); top = qMin(0.0, un->y() + un->bbox().top()); } top -= md; qreal diff = (bbox().bottom() + ipos().y() + yd + n->y()) - top; if (diff > 0.0) yd -= diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } else { if (tight) { if (chord->stem()) rxpos() += 0.8 * sp; rypos() += 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(true); sk.add(r.x(), r.top(), r.width()); qreal d = ss->skyline().south().minDistance(sk); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd += d + height() * .25; // force extra space below staff & chord (but not other fingerings) qreal bottom; if (!chord->up() && chord->beam() && stem) { bottom = stem->y() + stem->bbox().bottom(); } else { Note* dn = chord->downNote(); bottom = qMax(vStaff->height(), dn->y() + dn->bbox().bottom()); } bottom += md; qreal diff = bottom - (bbox().top() + ipos().y() + yd + n->y()); if (diff > 0.0) yd += diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } } else if (tid() == Tid::LH_GUITAR_FINGERING) { // place to left of note qreal left = n->shape().left(); if (left - n->x() > 0.0) rxpos() -= left; else rxpos() -= n->x(); } // for other fingering styles, do not autoplace // restore autoplace setAutoplace(true); } else if (offsetChanged() != OffsetChange::NONE) { // rebase horizontally too, as autoplace may have adjusted it rebaseOffset(false); } setOffsetChanged(false); }
void Palette::mouseDoubleClickEvent(QMouseEvent* ev) { int i = idx(ev->pos()); if (i == -1) return; Score* score = mscore->currentScore(); if (score == 0) return; const Selection& sel = score->selection(); if (sel.state() == SEL_NONE) return; Element* element = 0; if (i < size() && cells[i]) element = cells[i]->element; if (element == 0) return; ScoreView* viewer = mscore->currentScoreView(); if (viewer->mscoreState() != STATE_EDIT && viewer->mscoreState() != STATE_LYRICS_EDIT && viewer->mscoreState() != STATE_HARMONY_FIGBASS_EDIT && viewer->mscoreState() != STATE_TEXT_EDIT) { // Already in startCmd in this case score->startCmd(); } if (sel.state() == SEL_LIST) { foreach(Element* e, sel.elements()) applyDrop(score, viewer, e, element); } else if (sel.state() == SEL_RANGE) { // TODO: check for other element types: if (element->type() == Element::BAR_LINE) { // TODO: apply to multiple measures Measure* m = sel.startSegment()->measure(); QRectF r = m->staffabbox(sel.staffStart()); QPointF pt(r.x() + r.width() * .5, r.y() + r.height() * .5); applyDrop(score, viewer, m, element, pt); } else { int track1 = sel.staffStart() * VOICES; int track2 = sel.staffEnd() * VOICES; Segment* startSegment = sel.startSegment(); Segment* endSegment = sel.endSegment(); //keep it, it could change during the loop for (Segment* s = startSegment; s && s != endSegment; s = s->next1()) { for (int track = track1; track < track2; ++track) { Element* e = s->element(track); if (e == 0) continue; if (e->type() == Element::CHORD) { Chord* chord = static_cast<Chord*>(e); foreach(Note* n, chord->notes()) applyDrop(score, viewer, n, element); } else { // do not apply articulation to barline in a range selection if(e->type() != Element::BAR_LINE || element->type() != Element::ARTICULATION) applyDrop(score, viewer, e, element); } } } } } else qDebug("unknown selection state\n"); if (viewer->mscoreState() != STATE_EDIT && viewer->mscoreState() != STATE_LYRICS_EDIT && viewer->mscoreState() != STATE_HARMONY_FIGBASS_EDIT && viewer->mscoreState() != STATE_TEXT_EDIT) { //Already in startCmd mode in this case score->endCmd(); } mscore->endCmd(); }
void Tie::slurPos(SlurPos* sp) { bool useTablature = staff() != nullptr && staff()->isTabStaff(); StaffType* stt = nullptr; if (useTablature) stt = staff()->staffType(); qreal _spatium = spatium(); qreal hw = startNote()->tabHeadWidth(stt); // if stt == 0, defaults to headWidth() qreal __up = _up ? -1.0 : 1.0; // y offset for ties inside chord margins (typically multi-note chords): lined up with note top or bottom margin // or outside (typically single-note chord): overlaps note and is above/below it // Outside: Tab: uses font size and may be asymmetric placed above/below line (frets ON or ABOVE line) // Std: assumes notehead is 1 sp high, 1/2 sp above and 1/2 below line; add 1/4 sp to it // Inside: Tab: 1/2 of Outside offset // Std: use a fixed pecentage of note width qreal yOffOutside = useTablature ? (_up ? stt->fretBoxY() : stt->fretBoxY() + stt->fretBoxH()) * magS() : 0.75 * _spatium * __up; qreal yOffInside = useTablature ? yOffOutside * 0.5 : hw * .3 * __up; Chord* sc = startNote()->chord(); Q_ASSERT(sc); sp->system1 = sc->measure()->system(); if (!sp->system1) { Measure* m = sc->measure(); qDebug("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount()); } Q_ASSERT(sp->system1); qreal xo; qreal yo; bool shortStart = false; // determine attachment points // similar code is used in Chord::layoutPitched() // to allocate extra space to enforce minTieLength // so keep these in sync //------p1 if ((sc->notes().size() > 1) || (sc->stem() && (sc->up() == _up))) { xo = startNote()->x() + hw * 1.12; yo = startNote()->pos().y() + yOffInside; shortStart = true; } else { xo = startNote()->x() + hw * 0.65; yo = startNote()->pos().y() + yOffOutside; } sp->p1 = sc->pagePos() - sp->system1->pagePos() + QPointF(xo, yo); //------p2 if (endNote() == 0) { sp->p2 = sp->p1 + QPointF(_spatium * 3, 0.0); sp->system2 = sp->system1; return; } Chord* ec = endNote()->chord(); sp->system2 = ec->measure()->system(); if (!sp->system2) { qDebug("Tie::slurPos no system2"); sp->system2 = sp->system1; } hw = endNote()->tabHeadWidth(stt); if ((ec->notes().size() > 1) || (ec->stem() && !ec->up() && !_up)) xo = endNote()->x() - hw * 0.12; else if (shortStart) xo = endNote()->x() + hw * 0.15; else xo = endNote()->x() + hw * 0.35; sp->p2 = ec->pagePos() - sp->system2->pagePos() + QPointF(xo, yo); }