Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/engraving/dom/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2720,6 +2720,9 @@ Ornament* Chord::findOrnament(bool forPlayback) const
}
}
if (forPlayback) {
// TODO: cleanup.
// We shouldn't do this kind of special cases, and the DOM shouldn't know anything about playback.
// This should be in a different function that returns the ornament from the Trill ending on this chord. [MS]
for (Spanner* spanner : m_endingSpanners) {
if (spanner->isTrill()) {
return toTrill(spanner)->ornament();
Expand Down
14 changes: 8 additions & 6 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,10 @@ std::vector<Rest*> Score::setRests(const Fraction& _tick, track_idx_t track, con
f = l;
}

// Don't fill with rests a non-zero voice, *unless* it has links in voice zero
bool emptyNonZeroVoice = track2voice(track) != 0 && !measure->hasVoice(track) && tick == measure->tick();
if (emptyNonZeroVoice && !staff->trackHasLinksInVoiceZero(track)) {
// Don't fill a full measure with rests on a non-zero voice, *unless* it has links in voice zero
bool fullMeasure = tick == measure->tick() && f == measure->stretchedLen(staff);
bool emptyNonZeroVoice = track2voice(track) != 0 && !measure->hasVoice(track);
if (emptyNonZeroVoice && fullMeasure && !staff->trackHasLinksInVoiceZero(track)) {
l -= f;
measure = measure->nextMeasure();
if (!measure) {
Expand All @@ -512,10 +513,9 @@ std::vector<Rest*> Score::setRests(const Fraction& _tick, track_idx_t track, con
}

if ((measure->timesig() == measure->ticks()) // not in pickup measure
&& (measure->tick() == tick)
&& (measure->stretchedLen(staff) == f)
&& fullMeasure
&& !tuplet
&& (useFullMeasureRest)) {
&& useFullMeasureRest) {
Rest* rest = addRest(tick, track, TDuration(DurationType::V_MEASURE), tuplet);
tick += rest->actualTicks();
rests.push_back(rest);
Expand All @@ -538,6 +538,8 @@ std::vector<Rest*> Score::setRests(const Fraction& _tick, track_idx_t track, con
Rest* rest = 0;
for (const TDuration& d : dList) {
rest = addRest(tick, track, d, tuplet);
// If we're filling an empty non-zero voice make these gaps
rest->setGap(emptyNonZeroVoice && !fullMeasure);
rests.push_back(rest);
tick += rest->actualTicks();
}
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ void LineSegment::rebaseAnchors(EditData& ed, Grip grip)

// don't change anchors on keyboard adjustment or if Ctrl is pressed
// (Ctrl+Left/Right is handled elsewhere!)
if (ed.key == Key_Left || ed.key == Key_Right || ed.modifiers & ControlModifier) {
if (ed.key == Key_Left || ed.key == Key_Right || ed.key == Key_Up || ed.key == Key_Down || ed.modifiers & ControlModifier) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ bool Measure::showMeasureNumberOnStaff(staff_idx_t staffIdx) const
return false;
}

return showMeasureNumber() && score()->staff(staffIdx)->shouldShowMeasureNumbers();
return showMeasureNumber() && score()->staff(staffIdx)->shouldShowMeasureNumbers() && !score()->allStavesInvisible();
}

//---------------------------------------------------------
Expand Down
11 changes: 11 additions & 0 deletions src/engraving/dom/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5874,6 +5874,17 @@ size_t Score::visibleStavesCount() const
return count;
}

bool Score::allStavesInvisible() const
{
for (const Staff* staff : m_staves) {
if (staff->show()) {
return false;
}
}

return true;
}

ShadowNote* Score::shadowNote() const
{
return m_shadowNote;
Expand Down
1 change: 1 addition & 0 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ class Score : public EngravingObject, public muse::Injectable
const std::vector<Staff*>& staves() const { return m_staves; }
size_t nstaves() const { return m_staves.size(); }
size_t visibleStavesCount() const;
bool allStavesInvisible() const;
size_t ntracks() const { return m_staves.size() * VOICES; }

staff_idx_t staffIdx(const Staff*) const;
Expand Down
32 changes: 18 additions & 14 deletions src/engraving/dom/segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2738,21 +2738,25 @@ void Segment::addArticulationsToShape(const Chord* chord, Shape& shape)
};

for (Articulation* art : chord->articulations()) {
if (art->isOrnament()) {
Chord* cueNoteChord = toOrnament(art)->cueNoteChord();
if (cueNoteChord && cueNoteChord->upNote()->visible()) {
shape.add(cueNoteChord->shape().translate(cueNoteChord->pos() + cueNoteChord->staffOffset()));
}
} else if (art->addToSkyline()) {
shape.add(art->shape().translated(art->pos() + chord->pos()));
if (art->isTapping()) {
if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurAbove()) {
addTappingHalfSlurToShape(halfSlur);
}
if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurBelow()) {
addTappingHalfSlurToShape(halfSlur);
}
if (art->isOrnament() || !art->addToSkyline()) {
continue;
}
shape.add(art->shape().translated(art->pos() + chord->pos()));
if (art->isTapping()) {
if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurAbove()) {
addTappingHalfSlurToShape(halfSlur);
}
if (TappingHalfSlur* halfSlur = toTapping(art)->halfSlurBelow()) {
addTappingHalfSlurToShape(halfSlur);
}
}
}

Ornament* ornament = chord->findOrnament();
if (ornament) {
Chord* cueNoteChord = ornament->cueNoteChord();
if (cueNoteChord && cueNoteChord->upNote()->addToSkyline()) {
shape.add(cueNoteChord->shape().translate(cueNoteChord->pos() + cueNoteChord->staffOffset()));
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion src/engraving/rendering/score/measurelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2435,13 +2435,25 @@ void MeasureLayout::addRepeatCourtesies(Measure* m, LayoutContext& ctx)
return;
}

bool hasCourtesies = false;
for (Measure* repeatStartMeasure : measures) {
if (repeatStartMeasure == m->nextMeasure()) {
// Follow section break courtesy property
const Measure* prevMeasure = repeatStartMeasure->prevMeasure();
const LayoutBreak* sectionBreak = prevMeasure ? prevMeasure->sectionBreakElement() : nullptr;
const bool sectionBreakHideCourtesies = sectionBreak && !sectionBreak->showCourtesy();

if (repeatStartMeasure == m->nextMeasure() || sectionBreakHideCourtesies) {
continue;
}
setCourtesyClef(m, repeatStartMeasure->tick(), m->endTick(), SegmentType::ClefRepeatAnnounce, ctx);
setCourtesyKeySig(m, repeatStartMeasure->tick(), m->endTick(), SegmentType::KeySigRepeatAnnounce, ctx);
setCourtesyTimeSig(m, repeatStartMeasure->tick(), m->endTick(), SegmentType::TimeSigRepeatAnnounce, ctx);

hasCourtesies = true;
}

if (!hasCourtesies) {
removeRepeatCourtesies(m);
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/engraving/rendering/score/measurenumberlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ void MeasureNumberLayout::layoutMeasureNumberBase(MeasureNumberBase* item, Measu
double yoff = 0.0;

// If there is only one line, the barline spans outside the staff lines, so the default position is not correct.
if (item->staff()->constStaffType(item->measure()->tick())->lines() == 1) {
staff_idx_t effectiveStaffIdx = item->effectiveStaffIdx();
Staff* staff = item->score()->staff(effectiveStaffIdx);
if (staff && staff->lines(item->tick()) == 1) {
yoff -= 2.0 * item->spatium();
}

Expand Down
2 changes: 1 addition & 1 deletion src/engraving/rendering/score/restlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ InterruptionPoints RestLayout::computeInterruptionPoints(const Measure* measure,
if (gapRest || hasMergedRest || invisible) {
for (voice_idx_t voice = 0; voice < VOICES; ++voice) {
interruptionPointSets[voice].insert(segment->rtick());
interruptionPointSets[voice].insert(segment->rtick() + segment->ticks());
interruptionPointSets[voice].insert(segment->rtick() + toChordRest(item)->actualTicks());
}
break;
}
Expand Down
192 changes: 192 additions & 0 deletions src/engraving/tests/voiceswitching_data/voiceswitching-2.mscx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="4.60">
<programVersion>4.7.0</programVersion>
<programRevision></programRevision>
<Score>
<eid>sFMlmwzzOnG_ILNRNamr+pG</eid>
<Division>480</Division>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<open>1</open>
<metaTag name="arranger"></metaTag>
<metaTag name="audioComUrl"></metaTag>
<metaTag name="composer">Composer / arranger</metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="creationDate">2025-10-27</metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="platform">Linux</metaTag>
<metaTag name="source"></metaTag>
<metaTag name="sourceRevisionId"></metaTag>
<metaTag name="subtitle">Subtitle</metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">Untitled score</metaTag>
<Order id="orchestral">
<name>Orchestral</name>
<instrument id="piano">
<family id="keyboards">Keyboards</family>
</instrument>
<section id="woodwind" brackets="true" barLineSpan="true" thinBrackets="true">
<family>flutes</family>
<family>oboes</family>
<family>clarinets</family>
<family>saxophones</family>
<family>bassoons</family>
<unsorted group="woodwinds"/>
</section>
<section id="brass" brackets="true" barLineSpan="true" thinBrackets="true">
<family>horns</family>
<family>trumpets</family>
<family>cornets</family>
<family>flugelhorns</family>
<family>trombones</family>
<family>tubas</family>
</section>
<section id="timpani" brackets="true" barLineSpan="true" thinBrackets="true">
<family>timpani</family>
</section>
<section id="percussion" brackets="true" barLineSpan="true" thinBrackets="true">
<family>keyboard-percussion</family>
<family>drums</family>
<family>unpitched-metal-percussion</family>
<family>unpitched-wooden-percussion</family>
<family>other-percussion</family>
</section>
<family>keyboards</family>
<family>harps</family>
<family>organs</family>
<family>synths</family>
<soloists/>
<section id="voices" brackets="true" barLineSpan="false" thinBrackets="true">
<family>voices</family>
<family>voice-groups</family>
</section>
<section id="strings" brackets="true" barLineSpan="true" thinBrackets="true">
<family>orchestral-strings</family>
</section>
<unsorted/>
</Order>
<Part id="1">
<Staff>
<eid>yLTbtpuYjrL_2Upa4+LsM9L</eid>
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<bracket type="1" span="2" col="2" visible="1"/>
<barLineSpan>1</barLineSpan>
</Staff>
<trackName>Piano</trackName>
<Instrument id="piano">
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<clef staff="2">F</clef>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>150</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="sforzatoStaccato">
<velocity>150</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="marcatoStaccato">
<velocity>120</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="marcatoTenuto">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
<synti>Fluid</synti>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure>
<eid>R0Ms9HgYTs_Z6F7QI7s5JN</eid>
<voice>
<KeySig>
<eid>D/xXUPh7WdE_reZf5mJn+rN</eid>
<concertKey>0</concertKey>
</KeySig>
<TimeSig>
<eid>EFsX1i3AOML_g3rEJvJe0FL</eid>
<sigN>4</sigN>
<sigD>4</sigD>
</TimeSig>
<Chord>
<eid>LhFBK1lGKgE_4Oqi75gCRpL</eid>
<durationType>quarter</durationType>
<Note>
<eid>kEiL+JIyKaB_Br8MHf3MwqC</eid>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<eid>NbZC+YdlrQE_aV2BwgrVuDN</eid>
<durationType>quarter</durationType>
<Note>
<eid>BCUbEFHVj2M_gg/VFZrm7sO</eid>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<eid>9XshPS74OBP_hssb+Zs/VLI</eid>
<durationType>quarter</durationType>
<Note>
<eid>1Pe/TGT9rzK_VdIu9Juc2F</eid>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<eid>UjXt9EC39YL_LJGi/kylO4C</eid>
<durationType>quarter</durationType>
<Note>
<eid>nBCZaNYI51D_PXlNUGn76+N</eid>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</voice>
</Measure>
</Staff>
</Score>
</museScore>
Loading
Loading