Skip to content

Commit

Permalink
Merge pull request #2164 from MarcSabatella/73051-spanner-edit-voices
Browse files Browse the repository at this point in the history
fix #73051: editing spanner length with multiple voices and/or tuplets
  • Loading branch information
lasconic committed Aug 18, 2015
2 parents 53f89d9 + ed6aa2e commit 24b0bc8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 18 deletions.
34 changes: 20 additions & 14 deletions libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3584,36 +3584,42 @@ ChordRest* Score::findCR(int tick, int track) const

//---------------------------------------------------------
// findCRinStaff
// find chord/rest <= tick in staff
// prefer shortest duration (so it does not overlap next chordrest segment)
// find last chord/rest on staff that ends before tick
//---------------------------------------------------------

ChordRest* Score::findCRinStaff(int tick, int track) const
ChordRest* Score::findCRinStaff(int tick, int staffIdx) const
{
Measure* m = tick2measureMM(tick);
int ptick = tick - 1;
Measure* m = tick2measureMM(ptick);
if (!m) {
qDebug("findCRinStaff: no measure for tick %d", tick);
qDebug("findCRinStaff: no measure for tick %d", ptick);
return nullptr;
}
// attach to first rest all spanner when mmRest
if (m->isMMRest())
tick = m->tick();
ptick = m->tick();
Segment* s = m->first(Segment::Type::ChordRest);
int strack = (track / VOICES) * VOICES;
int strack = staffIdx * VOICES;
int etrack = strack + VOICES;
int actualTrack = strack;

int lastTick = -1;
for (Segment* ns = s; ; ns = ns->next(Segment::Type::ChordRest)) {
if (ns == 0 || ns->tick() > tick)
if (ns == 0 || ns->tick() > ptick)
break;
// found a segment; now find shortest chordrest on this staff (if any)
ChordRest* shortestCR = 0;
// found a segment; now find longest cr on this staff that does not overlap tick
for (int t = strack; t < etrack; ++t) {
ChordRest* cr = static_cast<ChordRest*>(ns->element(t));
if (cr && (!shortestCR || cr->actualTicks() < shortestCR->actualTicks())) {
shortestCR = cr;
s = ns;
actualTrack = t;
if (cr) {
int endTick = cr->tick() + cr->actualTicks();
// allow fudge factor for tuplets
// TODO: replace with fraction-based calculation
int fudge = cr->tuplet() ? 5 : 0;
if (endTick + fudge >= lastTick && endTick - fudge <= tick) {
s = ns;
actualTrack = t;
lastTick = endTick;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion libmscore/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ class Score : public QObject {
Hairpin* addHairpin(bool crescendo, int tickStart, int tickEnd, int track);

ChordRest* findCR(int tick, int track) const;
ChordRest* findCRinStaff(int tick, int track) const;
ChordRest* findCRinStaff(int tick, int staffIdx) const;
void layoutSpanner();
void insertTime(int tickPos, int tickLen);

Expand Down
11 changes: 8 additions & 3 deletions libmscore/spanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,14 +534,19 @@ void Spanner::computeEndElement()
{
switch (_anchor) {
case Anchor::SEGMENT: {
_endElement = score()->findCRinStaff(tick2() - 1, track2());
// find last cr on this staff that ends before tick2
_endElement = score()->findCRinStaff(tick2(), track2() / VOICES);
if (!_endElement) {
qDebug("%s no end element for tick %d", name(), tick2());
return;
}
if (!endCR()->measure()->isMMRest()) {
int nticks = endCR()->tick() + endCR()->actualTicks() - _tick;
if (_ticks != nticks) {
ChordRest* cr = endCR();
int nticks = cr->tick() + cr->actualTicks() - _tick;
// allow fudge factor for tuplets
// TODO: replace with fraction-based calculation
int fudge = cr->tuplet() ? 5 : 0;
if (qAbs(_ticks - nticks) > fudge) {
qDebug("%s ticks changed, %d -> %d", name(), _ticks, nticks);
setTicks(nticks);
if (type() == Element::Type::OTTAVA)
Expand Down

0 comments on commit 24b0bc8

Please sign in to comment.