Skip to content

Commit e2d0b29

Browse files
committed
Find playable dynamic at hairpin end if snapped one isn't playable
1 parent c21bf56 commit e2d0b29

File tree

4 files changed

+18
-17
lines changed

4 files changed

+18
-17
lines changed

src/engraving/dom/hairpin.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,11 @@ EngravingItem* HairpinSegment::findElementToSnapBefore(bool ignoreInvisible) con
327327
return nullptr;
328328
}
329329

330-
EngravingItem* HairpinSegment::findElementToSnapAfter(bool ignoreInvisible) const
330+
EngravingItem* HairpinSegment::findElementToSnapAfter(bool ignoreInvisible, bool requirePlayable) const
331331
{
332332
// Note: we don't need to look for a hairpin after.
333333
// It is the next hairpin which looks for a hairpin before.
334-
return findEndDynamicOrExpression(ignoreInvisible);
334+
return findEndDynamicOrExpression(ignoreInvisible, requirePlayable);
335335
}
336336

337337
void HairpinSegment::endDragGrip(EditData& ed)
@@ -398,7 +398,7 @@ TextBase* HairpinSegment::findStartDynamicOrExpression(bool ignoreInvisible) con
398398
return dynamicsAndExpr.back();
399399
}
400400

401-
TextBase* HairpinSegment::findEndDynamicOrExpression(bool ignoreInvisible) const
401+
TextBase* HairpinSegment::findEndDynamicOrExpression(bool ignoreInvisible, bool requirePlayable) const
402402
{
403403
Fraction refTick = hairpin()->tick2();
404404
Measure* measure = score()->tick2measure(refTick - Fraction::eps());
@@ -424,6 +424,9 @@ TextBase* HairpinSegment::findEndDynamicOrExpression(bool ignoreInvisible) const
424424
if (ignoreInvisible && !item->addToSkyline()) {
425425
continue;
426426
}
427+
if (requirePlayable && (!item->isDynamic() || !toDynamic(item)->playDynamic())) {
428+
continue;
429+
}
427430
bool endsMatch = item->track() == hairpin()->track()
428431
&& item->placement() == placement()
429432
&& item->getProperty(Pid::VOICE_ASSIGNMENT) == hairpin()->getProperty(Pid::VOICE_ASSIGNMENT);

src/engraving/dom/hairpin.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ class HairpinSegment final : public TextLineBaseSegment
7070
bool hasVoiceAssignmentProperties() const override { return spanner()->hasVoiceAssignmentProperties(); }
7171

7272
EngravingItem* findElementToSnapBefore(bool ignoreInvisible = true) const;
73-
EngravingItem* findElementToSnapAfter(bool ignoreInvisible = true) const;
73+
EngravingItem* findElementToSnapAfter(bool ignoreInvisible = true, bool requirePlayable = false) const;
7474

7575
void endDragGrip(EditData& ed) override;
7676

7777
private:
7878
TextBase* findStartDynamicOrExpression(bool ignoreInvisible = true) const;
79-
TextBase* findEndDynamicOrExpression(bool ignoreInvisible = true) const;
79+
TextBase* findEndDynamicOrExpression(bool ignoreInvisible = true, bool requirePlayable = false) const;
8080

8181
void startDragGrip(EditData&) override;
8282
void dragGrip(EditData&) override;

src/engraving/dom/segment.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ EngravingItem* Segment::findAnnotation(ElementType type, track_idx_t minTrack, t
14131413
//---------------------------------------------------------
14141414
// findAnnotations
14151415
/// Returns the list of found annotations
1416-
/// or nullptr if nothing was found.
1416+
/// or an empty list if nothing was found.
14171417
//---------------------------------------------------------
14181418

14191419
std::vector<EngravingItem*> Segment::findAnnotations(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const

src/engraving/playback/playbackcontext.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,14 @@ static mu::engraving::DynamicType findNominalEndDynamicType(const Hairpin* hairp
9393
}
9494

9595
const track_idx_t trackIdx = hairpin->track();
96-
const EngravingItem* dynamic = endSegment->findAnnotation(ElementType::DYNAMIC, trackIdx, trackIdx);
97-
if (!dynamic || !dynamic->isDynamic() || !toDynamic(dynamic)->playDynamic()) {
98-
return mu::engraving::DynamicType::OTHER;
96+
const EngravingItemList dynamics = endSegment->findAnnotations(ElementType::DYNAMIC, trackIdx, trackIdx);
97+
for (const EngravingItem* dynamic : dynamics) {
98+
if (dynamic && dynamic->isDynamic() && toDynamic(dynamic)->playDynamic()) {
99+
return toDynamic(dynamic)->dynamicType();
100+
}
99101
}
100102

101-
return toDynamic(dynamic)->dynamicType();
103+
return mu::engraving::DynamicType::OTHER;
102104
}
103105

104106
const LineSegment* seg = hairpin->backSegment();
@@ -108,17 +110,13 @@ static mu::engraving::DynamicType findNominalEndDynamicType(const Hairpin* hairp
108110

109111
// Optimization: first check if there is a cached dynamic
110112
const EngravingItem* snappedItem = seg->ldata()->itemSnappedAfter();
111-
if (!snappedItem || !snappedItem->isDynamic()) {
112-
snappedItem = toHairpinSegment(seg)->findElementToSnapAfter(false /*ignoreInvisible*/);
113-
if (!snappedItem || !snappedItem->isDynamic()) {
113+
if (!snappedItem || !snappedItem->isDynamic() || !toDynamic(snappedItem)->playDynamic()) {
114+
snappedItem = toHairpinSegment(seg)->findElementToSnapAfter(false /*ignoreInvisible*/, true /* requirePlayable */);
115+
if (!snappedItem || !snappedItem->isDynamic() || !toDynamic(snappedItem)->playDynamic()) {
114116
return mu::engraving::DynamicType::OTHER;
115117
}
116118
}
117119

118-
if (!toDynamic(snappedItem)->playDynamic()) {
119-
return mu::engraving::DynamicType::OTHER;
120-
}
121-
122120
return toDynamic(snappedItem)->dynamicType();
123121
}
124122

0 commit comments

Comments
 (0)