Skip to content
Open
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
6 changes: 2 additions & 4 deletions src/engraving/api/v1/elements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@ bool EngravingItem::up() const
return toChordRest(element())->ldata()->up;
} else if (element()->isStem()) {
return toStem(element())->up();
} else if (element()->isSlur()) {
return toSlur(element())->up();
} else if (element()->isTie()) {
return toTie(element())->up();
} else if (element()->isSlurTie()) {
return toSlurTie(element())->up();
} else if (element()->isSlurTieSegment()) {
return toSlurTieSegment(element())->slurTie()->up();
} else if (element()->isArticulation()) {
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/engravingobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class Score;
class Segment;
class Slur;
class SlurSegment;
class SlurTie;
class SlurTieSegment;
class Spacer;
class Spanner;
Expand Down Expand Up @@ -468,6 +469,7 @@ class EngravingObject
bool isRestFamily() const { return isRest() || isMMRest() || isMeasureRepeat(); }
bool isChordRest() const { return isRestFamily() || isChord(); }
bool isDurationElement() const { return isChordRest() || isTuplet(); }
bool isSlurTie() const { return isSlur() || isTie(); }
bool isSlurTieSegment() const { return isSlurSegment() || isTieSegment(); }
bool isSLineSegment() const;
bool isBox() const { return isVBox() || isHBox() || isTBox() || isFBox(); }
Expand Down Expand Up @@ -680,6 +682,7 @@ CONVERT(Slur)
CONVERT(SlurSegment)
CONVERT(Tie)
CONVERT(TieSegment)
CONVERT(SlurTie)
CONVERT(SlurTieSegment)
CONVERT(LaissezVibSegment)
CONVERT(PartialTieSegment)
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2740,7 +2740,7 @@ void Segment::addArticulationsToShape(const Chord* chord, Shape& shape)
Shape slurSegShape = slurSeg->shape();
// Semi-hack: we don't know the exact position at this stage, but we know that it
// must end approx on the center of the notehead
Note* note = slur->up() ? chord->upNote() : chord->downNote();
Note* note = slurSeg->up() ? chord->upNote() : chord->downNote();
double approxPosX = chord->x() + note->x() + 0.5 * note->headWidth() - slurSegShape.right();
slurSegShape.translateX(approxPosX);
shape.add(slurSegShape);
Expand Down
44 changes: 33 additions & 11 deletions src/engraving/dom/slurtie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ SlurTieSegment::SlurTieSegment(const ElementType& type, System* parent)
: SpannerSegment(type, parent)
{
setFlag(ElementFlag::ON_STAFF, true);
m_slurDirection = DirectionV::AUTO;
}

SlurTieSegment::SlurTieSegment(const SlurTieSegment& b)
: SpannerSegment(b)
{
m_slurDirection = b.m_slurDirection;
for (int i = 0; i < int(Grip::GRIPS); ++i) {
m_ups[i] = b.m_ups[i];
m_ups[i].p = PointF();
Expand Down Expand Up @@ -183,13 +185,15 @@ std::vector<PointF> SlurTieSegment::gripsPositions(const EditData&) const

bool SlurTieSegment::isUserModified() const
{
return SpannerSegment::isUserModified() || !(visible() && autoplace()
&& color() == configuration()->defaultColor()
&& offset().isNull()
&& ups(Grip::START).off.isNull()
&& ups(Grip::BEZIER1).off.isNull()
&& ups(Grip::BEZIER2).off.isNull()
&& ups(Grip::END).off.isNull());
return SpannerSegment::isUserModified()
|| !(visible() && autoplace()
&& color() == configuration()->defaultColor()
&& offset().isNull()
&& slurDirection() == propertyDefault(Pid::SLUR_DIRECTION).value<DirectionV>()
&& ups(Grip::START).off.isNull()
&& ups(Grip::BEZIER1).off.isNull()
&& ups(Grip::BEZIER2).off.isNull()
&& ups(Grip::END).off.isNull());
}

//---------------------------------------------------------
Expand Down Expand Up @@ -217,6 +221,14 @@ void SlurTieSegment::endDragGrip(EditData& ed)
triggerLayout();
}

bool SlurTieSegment::up() const
{
if (m_slurDirection == DirectionV::AUTO && slurTie()) {
return slurTie()->up();
}
return m_slurDirection != DirectionV::DOWN;
}

//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
Expand All @@ -225,8 +237,9 @@ PropertyValue SlurTieSegment::getProperty(Pid propertyId) const
{
switch (propertyId) {
case Pid::SLUR_STYLE_TYPE:
case Pid::SLUR_DIRECTION:
return slurTie()->getProperty(propertyId);
case Pid::SLUR_DIRECTION:
return m_slurDirection;
case Pid::SLUR_UOFF1:
return ups(Grip::START).off;
case Pid::SLUR_UOFF2:
Expand All @@ -248,8 +261,10 @@ bool SlurTieSegment::setProperty(Pid propertyId, const PropertyValue& v)
{
switch (propertyId) {
case Pid::SLUR_STYLE_TYPE:
case Pid::SLUR_DIRECTION:
return slurTie()->setProperty(propertyId, v);
case Pid::SLUR_DIRECTION:
setSlurDirection(v.value<DirectionV>());
break;
case Pid::SLUR_UOFF1:
ups(Grip::START).off = v.value<PointF>();
break;
Expand Down Expand Up @@ -300,6 +315,7 @@ void SlurTieSegment::reset()
undoResetProperty(Pid::SLUR_UOFF2);
undoResetProperty(Pid::SLUR_UOFF3);
undoResetProperty(Pid::SLUR_UOFF4);
undoResetProperty(Pid::SLUR_DIRECTION);
slurTie()->reset();
}

Expand All @@ -316,6 +332,7 @@ void SlurTieSegment::undoChangeProperty(Pid pid, const PropertyValue& val, Prope
undoPushProperty(Pid::SLUR_UOFF2);
undoPushProperty(Pid::SLUR_UOFF3);
undoPushProperty(Pid::SLUR_UOFF4);
undoPushProperty(Pid::SLUR_DIRECTION);
// other will be saved in base classes.
}
SpannerSegment::undoChangeProperty(pid, val, ps);
Expand Down Expand Up @@ -353,9 +370,14 @@ SlurTie::~SlurTie()
// undoSetSlurDirection
//---------------------------------------------------------

void SlurTie::undoSetSlurDirection(DirectionV d)
void SlurTie::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
{
undoChangeProperty(Pid::SLUR_DIRECTION, PropertyValue::fromValue<DirectionV>(d));
Spanner::undoChangeProperty(id, v, ps);
if (id == Pid::SLUR_DIRECTION) {
for (SpannerSegment* ss : spannerSegments()) {
ss->undoResetProperty(Pid::SLUR_DIRECTION);
}
}
}

//---------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion src/engraving/dom/slurtie.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ class SlurTieSegment : public SpannerSegment
const UP& ups(Grip i) const { return m_ups[int(i)]; }
UP& ups(Grip i) { return m_ups[int(i)]; }

DirectionV slurDirection() const { return m_slurDirection; }
void setSlurDirection(DirectionV d) { m_slurDirection = d; }
bool up() const;

bool needStartEditingAfterSelecting() const override { return true; }
int gripsCount() const override { return int(Grip::GRIPS); }
Grip initialEditModeGrip() const override { return Grip::END; }
Expand Down Expand Up @@ -144,6 +148,8 @@ class SlurTieSegment : public SpannerSegment
std::vector<LineF> gripAnchorLines(Grip grip) const override;

struct UP m_ups[int(Grip::GRIPS)];

DirectionV m_slurDirection = DirectionV::AUTO;
};

//-------------------------------------------------------------------
Expand All @@ -168,7 +174,6 @@ class SlurTie : public Spanner

DirectionV slurDirection() const { return m_slurDirection; }
void setSlurDirection(DirectionV d) { m_slurDirection = d; }
void undoSetSlurDirection(DirectionV d);

virtual bool contains(const PointF&) const { return false; } // not selectable

Expand All @@ -183,6 +188,7 @@ class SlurTie : public Spanner
PropertyValue getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const PropertyValue&) override;
PropertyValue propertyDefault(Pid id) const override;
void undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps = PropertyFlags::NOSTYLE) override;

void fixupSegments(unsigned nsegs);

Expand Down
20 changes: 0 additions & 20 deletions src/engraving/editing/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3271,26 +3271,6 @@ void Score::cmdMirrorNoteHead()
}
undoChangeUserMirror(note, d);
}
} else if (e->isHairpinSegment()) {
Hairpin* h = toHairpinSegment(e)->hairpin();
HairpinType st = h->hairpinType();
switch (st) {
case HairpinType::CRESC_HAIRPIN:
st = HairpinType::DIM_HAIRPIN;
break;
case HairpinType::DIM_HAIRPIN:
st = HairpinType::CRESC_HAIRPIN;
break;
case HairpinType::CRESC_LINE:
st = HairpinType::DIM_LINE;
break;
case HairpinType::DIM_LINE:
st = HairpinType::CRESC_LINE;
break;
case HairpinType::INVALID:
break;
}
h->undoChangeProperty(Pid::HAIRPIN_TYPE, int(st));
}
}
}
Expand Down
25 changes: 21 additions & 4 deletions src/engraving/editing/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2476,10 +2476,10 @@ void Score::cmdFlip()
tremolo->undoChangeProperty(Pid::STEM_DIRECTION, dir);
});
} else if (e->isSlurTieSegment()) {
auto slurTieSegment = toSlurTieSegment(e)->slurTie();
flipOnce(slurTieSegment, [slurTieSegment]() {
DirectionV dir = slurTieSegment->up() ? DirectionV::DOWN : DirectionV::UP;
slurTieSegment->undoChangeProperty(Pid::SLUR_DIRECTION, dir);
DirectionV dir = toSlurTieSegment(e)->up() ? DirectionV::DOWN : DirectionV::UP;
auto slurTie = toSlurTieSegment(e)->slurTie();
flipOnce(slurTie, [slurTie, dir]() {
slurTie->undoChangeProperty(Pid::SLUR_DIRECTION, dir);
});
} else if (e->isArticulationFamily()) {
auto artic = toArticulation(e);
Expand Down Expand Up @@ -2653,8 +2653,25 @@ void Score::cmdFlipHorizontally()
h->undoChangeProperty(Pid::HAIRPIN_TYPE, int(HairpinType::DIM_HAIRPIN));
} else if (h->hairpinType() == HairpinType::DIM_HAIRPIN) {
h->undoChangeProperty(Pid::HAIRPIN_TYPE, int(HairpinType::CRESC_HAIRPIN));
} else if (h->hairpinType() == HairpinType::CRESC_LINE) {
h->undoChangeProperty(Pid::HAIRPIN_TYPE, int(HairpinType::DIM_LINE));
} else if (h->hairpinType() == HairpinType::DIM_LINE) {
h->undoChangeProperty(Pid::HAIRPIN_TYPE, int(HairpinType::CRESC_LINE));
}
});
} else if (e->isSlurTieSegment()) {
SlurTieSegment* slurTieSegment = toSlurTieSegment(e);
DirectionV dir = slurTieSegment->up() ? DirectionV::DOWN : DirectionV::UP;
SlurTie* slurTie = slurTieSegment->slurTie();
if (slurTie->nsegments() > 1) {
flipOnce(slurTieSegment, [slurTieSegment, dir] {
slurTieSegment->undoChangeProperty(Pid::SLUR_DIRECTION, dir, PropertyFlags::NOSTYLE);
});
} else {
flipOnce(slurTie, [slurTie, dir] {
slurTie->undoChangeProperty(Pid::SLUR_DIRECTION, dir);
});
}
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/engraving/rendering/score/chordlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,12 @@ void ChordLayout::layoutTablature(Chord* item, LayoutContext& ctx)
bool shortStart = false; // whether tie should clear start note or not
Note* startNote = tie->startNote();
Chord* startChord = startNote ? startNote->chord() : nullptr;
const bool tieUp = !tie->segmentsEmpty() ? tie->frontSegment()->up() : tie->up();
if (startChord && startChord->measure() == item->measure() && startChord == prevChordRest(item)) {
double startNoteWidth = startNote->width();
// overlap into start chord?
// if in start chord, there are several notes or stem and tie in same direction
if (startChord->notes().size() > 1 || (startChord->stem() && startChord->up() == tie->up())) {
if (startChord->notes().size() > 1 || (startChord->stem() && startChord->up() == tieUp)) {
// clear start note (1/8 of fret mark width)
shortStart = true;
overlap -= startNoteWidth * 0.125;
Expand All @@ -402,7 +403,7 @@ void ChordLayout::layoutTablature(Chord* item, LayoutContext& ctx)
}
// overlap into end chord (this)?
// if several notes or neither stem or tie are up
if (item->notes().size() > 1 || (item->stem() && !item->up() && !tie->up())) {
if (item->notes().size() > 1 || (item->stem() && !item->up() && !tieUp)) {
// for positive offset:
// use available space
// for negative x offset:
Expand Down Expand Up @@ -1191,10 +1192,10 @@ void ChordLayout::layoutArticulations3(Chord* item, Slur* slur, LayoutContext& c
bool slurBelowArticulation = a->up() && !(ss->vStaffIdx() < item->vStaffIdx());
double vertClearance = slurBelowArticulation ? aShape.verticalClearance(sShape) : sShape.verticalClearance(aShape);
if (vertClearance < minDist) {
minDist += slur->up()
minDist += ss->up()
? std::max(aShape.minVerticalDistance(sShape), 0.0)
: std::max(sShape.minVerticalDistance(aShape), 0.0);
minDist *= slur->up() ? -1 : 1;
minDist *= ss->up() ? -1 : 1;
for (auto iter2 = iter; iter2 != item->articulations().end(); ++iter2) {
Articulation* aa = *iter2;
aa->mutldata()->moveY(minDist);
Expand Down Expand Up @@ -3209,7 +3210,7 @@ void ChordLayout::checkStartEndSlurs(Chord* chord, LayoutContext& ctx)
}
Slur* slur = toSlur(spanner);
SlurTieLayout::computeUp(slur, ctx);
if (slur->up()) {
if (!slur->segmentsEmpty() ? slur->frontSegment()->up() : slur->up()) {
chord->startEndSlurs().startUp = true;
} else {
chord->startEndSlurs().startDown = true;
Expand All @@ -3224,7 +3225,8 @@ void ChordLayout::checkStartEndSlurs(Chord* chord, LayoutContext& ctx)
if (!spanner->isSlur()) {
continue;
}
if (toSlur(spanner)->up()) {
Slur* slur = toSlur(spanner);
if (!slur->segmentsEmpty() ? slur->backSegment()->up() : slur->up()) {
chord->startEndSlurs().endUp = true;
} else {
chord->startEndSlurs().endDown = true;
Expand Down
Loading
Loading