Skip to content

Commit bf78ae1

Browse files
authored
Merge pull request #29775 from miiizen/27078-rehearsalMarkTempoChange
Move tempo changes if rehearsal mark on the same segment
2 parents 2f4fd3c + 5a1dbea commit bf78ae1

File tree

7 files changed

+144
-14
lines changed

7 files changed

+144
-14
lines changed

src/engraving/dom/gradualtempochange.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "gradualtempochange.h"
2424

25+
#include "dom/rehearsalmark.h"
26+
#include "dom/text.h"
2527
#include "measure.h"
2628
#include "score.h"
2729
#include "segment.h"
@@ -147,6 +149,8 @@ PropertyValue GradualTempoChange::getProperty(Pid id) const
147149
return tempoChangeFactor();
148150
case Pid::SNAP_AFTER:
149151
return snapToItemAfter();
152+
case Pid::TEMPO_ALIGN_RIGHT_OF_REHEARSAL_MARK:
153+
return m_alignRightOfRehearsalMark;
150154
default:
151155
return TextLineBase::getProperty(id);
152156
}
@@ -167,6 +171,9 @@ bool GradualTempoChange::setProperty(Pid id, const PropertyValue& val)
167171
case Pid::SNAP_AFTER:
168172
setSnapToItemAfter(val.toBool());
169173
break;
174+
case Pid::TEMPO_ALIGN_RIGHT_OF_REHEARSAL_MARK:
175+
m_alignRightOfRehearsalMark = val.toBool();
176+
break;
170177
default:
171178
if (!TextLineBase::setProperty(id, val)) {
172179
return false;
@@ -221,6 +228,9 @@ PropertyValue GradualTempoChange::propertyDefault(Pid propertyId) const
221228
case Pid::SNAP_AFTER:
222229
return true;
223230

231+
case Pid::TEMPO_ALIGN_RIGHT_OF_REHEARSAL_MARK:
232+
return true;
233+
224234
default:
225235
return TextLineBase::propertyDefault(propertyId);
226236
}
@@ -261,6 +271,62 @@ Sid GradualTempoChange::getPropertyStyle(Pid id) const
261271
return TextLineBase::getPropertyStyle(id);
262272
}
263273

274+
bool GradualTempoChange::adjustForRehearsalMark(bool start) const
275+
{
276+
const Segment* segment = start ? startSegment() : endSegment();
277+
if (!m_alignRightOfRehearsalMark || !segment) {
278+
return false;
279+
}
280+
281+
const RehearsalMark* rehearsalMark = toRehearsalMark(segment->findAnnotation(ElementType::REHEARSAL_MARK, track(), track()));
282+
if (!rehearsalMark) {
283+
return false;
284+
}
285+
RectF thisBbox = ldata()->bbox().translated(pos());
286+
RectF rehearsalMarkBbox = rehearsalMark ? rehearsalMark->ldata()->bbox().translated(rehearsalMark->pos()) : RectF();
287+
288+
const bool sameSide = placeAbove() == rehearsalMark->placeAbove();
289+
const bool collision = placeAbove() ? muse::RealIsEqualOrMore(rehearsalMarkBbox.bottom(), thisBbox.top()) : muse::RealIsEqualOrLess(
290+
rehearsalMarkBbox.top(), thisBbox.bottom());
291+
292+
return sameSide && collision;
293+
}
294+
295+
PointF GradualTempoChange::linePos(Grip grip, System** system) const
296+
{
297+
bool start = grip == Grip::START;
298+
PointF defaultPos = TextLineBase::linePos(grip, system);
299+
if (!adjustForRehearsalMark(start)) {
300+
return defaultPos;
301+
}
302+
303+
const Segment* segment = start ? startSegment() : endSegment();
304+
const RehearsalMark* rehearsalMark = toRehearsalMark(segment->findAnnotation(ElementType::REHEARSAL_MARK, track(), track()));
305+
RectF rehearsalMarkBbox = rehearsalMark ? rehearsalMark->ldata()->bbox().translated(rehearsalMark->pos()) : RectF();
306+
307+
PointF rehearsalMarkPos = segment->pos() + segment->measure()->pos();
308+
rehearsalMarkBbox.translate(rehearsalMarkPos);
309+
310+
Text* text = start ? toGradualTempoChangeSegment(frontSegment())->text() : toGradualTempoChangeSegment(backSegment())->endText();
311+
312+
const double sp = spatium();
313+
314+
double padding = sp;
315+
if (text) {
316+
const double fontSizeScaleFactor = text->size() / 10.0;
317+
padding = 0.5 * sp * fontSizeScaleFactor;
318+
}
319+
320+
padding *= start ? 1.0 : -1.0;
321+
double x = (start ? rehearsalMarkBbox.right() : rehearsalMarkBbox.left()) + padding;
322+
323+
*system = segment->measure()->system();
324+
325+
x = start ? std::max(x, defaultPos.x()) : x;
326+
327+
return PointF(x, 0.0);
328+
}
329+
264330
void GradualTempoChange::added()
265331
{
266332
requestToRebuildTempo();

src/engraving/dom/gradualtempochange.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class GradualTempoChange : public TextLineBase
5656
bool snapToItemAfter() const { return m_snapToItemAfter; }
5757
void setSnapToItemAfter(bool v) { m_snapToItemAfter = v; }
5858

59+
bool adjustForRehearsalMark(bool start) const;
60+
PointF linePos(Grip grip, System** system) const override;
61+
5962
protected:
6063
void added() override;
6164
void removed() override;
@@ -69,6 +72,8 @@ class GradualTempoChange : public TextLineBase
6972

7073
bool m_snapToItemAfter = true;
7174

75+
bool m_alignRightOfRehearsalMark = true;
76+
7277
friend class GradualTempoChangeSegment;
7378
};
7479

src/engraving/rendering/score/tlayout.cpp

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,25 +3012,63 @@ void TLayout::layoutGraceNotesGroup2(const GraceNotesGroup* item, GraceNotesGrou
30123012
ldata->setShape(shape);
30133013
}
30143014

3015-
void TLayout::layoutGradualTempoChangeSegment(GradualTempoChangeSegment* item, LayoutContext& ctx)
3015+
void TLayout::manageTempoChangeSnapping(GradualTempoChangeSegment* item, LayoutContext& ctx)
30163016
{
3017-
LAYOUT_CALL_ITEM(item);
3018-
30193017
GradualTempoChangeSegment::LayoutData* ldata = item->mutldata();
30203018

30213019
ldata->disconnectSnappedItems();
3022-
3023-
layoutTextLineBaseSegment(item, ctx);
3024-
30253020
GradualTempoChangeSegment* tempoChangeSegmentSnappedBefore = item->findElementToSnapBefore();
30263021
if (tempoChangeSegmentSnappedBefore) {
30273022
ldata->connectItemSnappedBefore(tempoChangeSegmentSnappedBefore);
3023+
doLayoutGradualTempoChangeSegment(tempoChangeSegmentSnappedBefore, ctx);
30283024
}
30293025

30303026
TempoText* tempoTextSnappedAfter = item->findElementToSnapAfter();
30313027
if (tempoTextSnappedAfter) {
30323028
ldata->connectItemSnappedAfter(tempoTextSnappedAfter);
30333029
}
3030+
}
3031+
3032+
void TLayout::doLayoutGradualTempoChangeSegment(GradualTempoChangeSegment* item, LayoutContext& ctx)
3033+
{
3034+
GradualTempoChangeSegment::LayoutData* ldata = item->mutldata();
3035+
3036+
auto extendLineToSnappedItemAfter = [item](EngravingItem* itemAfter) {
3037+
assert(itemAfter->isGradualTempoChangeSegment() || itemAfter->isTempoText());
3038+
if (item->tempoChange()->adjustForRehearsalMark(false)
3039+
|| itemAfter->findAncestor(ElementType::SYSTEM) != item->system()) {
3040+
return;
3041+
}
3042+
3043+
double xItemPos = itemAfter->pageX() - item->system()->pageX();
3044+
double itemLeftEdge = xItemPos + itemAfter->ldata()->bbox().left();
3045+
3046+
double padding = item->spatium();
3047+
if (itemAfter->isTempoText()) {
3048+
const double fontSizeScaleFactor = toTempoText(itemAfter)->size() / 10.0;
3049+
padding = 0.5 * item->spatium() * fontSizeScaleFactor;
3050+
} else if (itemAfter->isGradualTempoChangeSegment()) {
3051+
Text* startText = toGradualTempoChangeSegment(itemAfter)->text();
3052+
if (startText) {
3053+
const double fontSizeScaleFactor = startText->size() / 10.0;
3054+
padding = 0.5 * item->spatium() * fontSizeScaleFactor;
3055+
}
3056+
}
3057+
3058+
double maxTempoLineEnd = itemLeftEdge - padding;
3059+
double xEndDiff = maxTempoLineEnd - (item->pos().x() + item->pos2().x());
3060+
item->rxpos2() += xEndDiff;
3061+
};
3062+
3063+
if (ldata->itemSnappedAfter() && ldata->itemSnappedAfter()->isTempoText()) {
3064+
TempoText* tempoTextSnappedAfter = toTempoText(ldata->itemSnappedAfter());
3065+
extendLineToSnappedItemAfter(tempoTextSnappedAfter);
3066+
} else if (ldata->itemSnappedAfter() && ldata->itemSnappedAfter()->isGradualTempoChangeSegment()) {
3067+
GradualTempoChangeSegment* tempoChangeSegmentSnappedAfter = toGradualTempoChangeSegment(ldata->itemSnappedAfter());
3068+
extendLineToSnappedItemAfter(tempoChangeSegmentSnappedAfter);
3069+
}
3070+
3071+
mu::engraving::rendering::score::TLayout::layoutTextLineBaseSegment(item, ctx);
30343072

30353073
if (item->isStyled(Pid::OFFSET)) {
30363074
item->roffset() = item->tempoChange()->propertyDefault(Pid::OFFSET).value<PointF>();
@@ -3042,6 +3080,15 @@ void TLayout::layoutGradualTempoChangeSegment(GradualTempoChangeSegment* item, L
30423080
Autoplace::autoplaceSpannerSegment(item, ldata, ctx.conf().spatium());
30433081
}
30443082

3083+
void TLayout::layoutGradualTempoChangeSegment(GradualTempoChangeSegment* item, LayoutContext& ctx)
3084+
{
3085+
LAYOUT_CALL_ITEM(item);
3086+
3087+
manageTempoChangeSnapping(item, ctx);
3088+
3089+
doLayoutGradualTempoChangeSegment(item, ctx);
3090+
}
3091+
30453092
void TLayout::layoutGradualTempoChange(GradualTempoChange* item, LayoutContext& ctx)
30463093
{
30473094
LAYOUT_CALL_ITEM(item);
@@ -5876,16 +5923,10 @@ void TLayout::layoutTempoText(const TempoText* item, TempoText::LayoutData* ldat
58765923
Segment* s = item->segment();
58775924

58785925
RehearsalMark* rehearsalMark = toRehearsalMark(s->findAnnotation(ElementType::REHEARSAL_MARK, item->track(), item->track()));
5879-
RectF rehearsMarkBbox = rehearsalMark ? rehearsalMark->ldata()->bbox().translated(rehearsalMark->pos()) : RectF();
5926+
RectF rehearsalMarkBbox = rehearsalMark ? rehearsalMark->ldata()->bbox().translated(rehearsalMark->pos()) : RectF();
58805927
RectF thisBbox = ldata->bbox().translated(item->pos());
58815928

5882-
if (rehearsalMark && rehearsMarkBbox.bottom() > thisBbox.top()
5883-
&& item->getProperty(Pid::TEMPO_ALIGN_RIGHT_OF_REHEARSAL_MARK).toBool()) {
5884-
double rightEdge = rehearsMarkBbox.right();
5885-
const double padding = 0.5 * item->fontMetrics().xHeight();
5886-
double curX = ldata->pos().x();
5887-
ldata->setPosX(std::max(curX, rightEdge + padding));
5888-
} else if (s->rtick().isZero()) {
5929+
if (s->rtick().isZero()) {
58895930
Segment* p = item->segment()->prev(SegmentType::TimeSig);
58905931
if (p && !p->allElementsInvisible()) {
58915932
ldata->moveX(-(s->x() - p->x()));
@@ -5895,6 +5936,21 @@ void TLayout::layoutTempoText(const TempoText* item, TempoText::LayoutData* ldat
58955936
}
58965937
}
58975938
}
5939+
5940+
if (rehearsalMark) {
5941+
const bool sameSide = item->placeAbove() == rehearsalMark->placeAbove();
5942+
const bool collision
5943+
= item->placeAbove() ? muse::RealIsEqualOrMore(rehearsalMarkBbox.bottom(), thisBbox.top()) : muse::RealIsEqualOrLess(
5944+
rehearsalMarkBbox.top(), thisBbox.bottom());
5945+
5946+
if (sameSide && collision && item->getProperty(Pid::TEMPO_ALIGN_RIGHT_OF_REHEARSAL_MARK).toBool()) {
5947+
double rightEdge = rehearsalMarkBbox.right();
5948+
const double fontSizeScaleFactor = item->size() / 10.0;
5949+
const double padding = 0.5 * item->spatium() * fontSizeScaleFactor;
5950+
double curX = ldata->pos().x();
5951+
ldata->setPosX(std::max(curX, rightEdge + padding));
5952+
}
5953+
}
58985954
Autoplace::autoplaceSegmentElement(item, ldata);
58995955
}
59005956

src/engraving/rendering/score/tlayout.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ class TLayout
402402
static void manageHairpinSnapping(HairpinSegment* item, LayoutContext& ctx);
403403

404404
static void checkRehearsalMarkVSBigTimeSig(const RehearsalMark* item, RehearsalMark::LayoutData* ldata);
405+
406+
static void manageTempoChangeSnapping(GradualTempoChangeSegment* item, LayoutContext& ctx);
407+
static void doLayoutGradualTempoChangeSegment(GradualTempoChangeSegment* item, LayoutContext& ctx);
405408
};
406409
}
407410

21 KB
Binary file not shown.

vtest/scores/tempoText-2.mscz

21.3 KB
Binary file not shown.

vtest/scores/tie-26.mscz

26.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)