diff --git a/src/engraving/dom/beam.cpp b/src/engraving/dom/beam.cpp index f117b8f2c9b9e..fdf7583854cf9 100644 --- a/src/engraving/dom/beam.cpp +++ b/src/engraving/dom/beam.cpp @@ -23,14 +23,11 @@ #include "beam.h" #include -#include #include #include "containers.h" #include "realfn.h" -#include "draw/types/brush.h" - #include "actionicon.h" #include "chord.h" #include "groups.h" @@ -74,13 +71,6 @@ Beam::Beam(const Beam& b) { m_elements = b.m_elements; m_id = b.m_id; - for (const BeamSegment* bs : b.m_beamSegments) { - m_beamSegments.push_back(new BeamSegment(*bs)); - } - m_direction = b.m_direction; - m_up = b.m_up; - m_userModified[0] = b.m_userModified[0]; - m_userModified[1] = b.m_userModified[1]; m_growLeft = b.m_growLeft; m_growRight = b.m_growRight; m_beamDist = b.m_beamDist; @@ -222,18 +212,19 @@ const Chord* Beam::findChordWithCustomStemDirection() const const BeamSegment* Beam::topLevelSegmentForElement(const ChordRest* element) const { - size_t segmentsSize = m_beamSegments.size(); + const std::vector& segments = beamSegments(); + size_t segmentsSize = segments.size(); IF_ASSERT_FAILED(segmentsSize > 0) { return nullptr; } - const BeamSegment* curSegment = m_beamSegments[0]; + const BeamSegment* curSegment = segments[0]; if (segmentsSize == 1) { return curSegment; } - for (const BeamSegment* segment : m_beamSegments) { + for (const BeamSegment* segment : segments) { if (segment->level <= curSegment->level) { continue; } @@ -322,7 +313,7 @@ void Beam::calcBeamBreaks(const ChordRest* cr, const ChordRest* prevCr, int leve void Beam::spatiumChanged(double oldValue, double newValue) { int idx = directionIdx(); - if (m_userModified[idx]) { + if (userModified()) { double diff = newValue / oldValue; for (BeamFragment* f : m_fragments) { f->py1[idx] = f->py1[idx] * diff; @@ -429,16 +420,16 @@ std::vector Beam::gripsPositions(const EditData& ed) const // setBeamDirection //--------------------------------------------------------- -void Beam::setBeamDirection(DirectionV d) +void Beam::setDirection(DirectionV d) { - if (m_direction == d || m_cross) { + if (direction() == d || m_cross) { return; } - m_direction = d; + doSetDirection(d); if (d != DirectionV::AUTO) { - m_up = d == DirectionV::UP; + setUp(d == DirectionV::UP); } for (ChordRest* e : elements()) { @@ -575,7 +566,7 @@ void Beam::setBeamPos(const PairF& bp) } BeamFragment* f = m_fragments.back(); int idx = directionIdx(); - m_userModified[idx] = true; + setUserModified(true); setGenerated(false); double _spatium = spatium(); @@ -594,7 +585,7 @@ void Beam::setNoSlope(bool b) // Make flat if usermodified if (m_noSlope) { int idx = directionIdx(); - if (m_userModified[idx]) { + if (userModified()) { BeamFragment* f = m_fragments.back(); f->py1[idx] = f->py2[idx] = (f->py1[idx] + f->py2[idx]) * 0.5; } @@ -603,8 +594,8 @@ void Beam::setNoSlope(bool b) void Beam::computeAndSetSlope() { - double xDiff = endAnchor().x() - startAnchor().x(); - double yDiff = endAnchor().y() - startAnchor().y(); + double xDiff = m_endAnchor.x() - m_startAnchor.x(); + double yDiff = m_endAnchor.y() - m_startAnchor.y(); if (std::abs(xDiff) < 0.5 * spatium()) { // Temporary safeguard: a beam this short is invalid, and exists only as a temporary state, // so don't try to compute the slope as it will be wrong. Needs a better solution in future. @@ -614,26 +605,6 @@ void Beam::computeAndSetSlope() } } -//--------------------------------------------------------- -// userModified -//--------------------------------------------------------- - -bool Beam::userModified() const -{ - int idx = directionIdx(); - return m_userModified[idx]; -} - -//--------------------------------------------------------- -// setUserModified -//--------------------------------------------------------- - -void Beam::setUserModified(bool val) -{ - int idx = directionIdx(); - m_userModified[idx] = val; -} - //--------------------------------------------------------- // getProperty //--------------------------------------------------------- @@ -641,10 +612,8 @@ void Beam::setUserModified(bool val) PropertyValue Beam::getProperty(Pid propertyId) const { switch (propertyId) { - case Pid::STEM_DIRECTION: return beamDirection(); case Pid::GROW_LEFT: return growLeft(); case Pid::GROW_RIGHT: return growRight(); - case Pid::USER_MODIFIED: return userModified(); case Pid::BEAM_POS: return PropertyValue::fromValue(beamPos()); case Pid::BEAM_NO_SLOPE: return noSlope(); case Pid::POSITION_LINKED_TO_MASTER: @@ -668,18 +637,12 @@ PropertyValue Beam::getProperty(Pid propertyId) const bool Beam::setProperty(Pid propertyId, const PropertyValue& v) { switch (propertyId) { - case Pid::STEM_DIRECTION: - setBeamDirection(v.value()); - break; case Pid::GROW_LEFT: setGrowLeft(v.toDouble()); break; case Pid::GROW_RIGHT: setGrowRight(v.toDouble()); break; - case Pid::USER_MODIFIED: - setUserModified(v.toBool()); - break; case Pid::BEAM_POS: if (userModified()) { setBeamPos(v.value()); @@ -717,11 +680,8 @@ bool Beam::setProperty(Pid propertyId, const PropertyValue& v) PropertyValue Beam::propertyDefault(Pid id) const { switch (id) { -// case Pid::SUB_STYLE: return int(TextStyleName::BEAM); - case Pid::STEM_DIRECTION: return DirectionV::AUTO; case Pid::GROW_LEFT: return 1.0; case Pid::GROW_RIGHT: return 1.0; - case Pid::USER_MODIFIED: return false; case Pid::BEAM_POS: return PropertyValue::fromValue(beamPos()); default: return BeamBase::propertyDefault(id); } @@ -888,8 +848,7 @@ void Beam::clearBeamSegments() chordRest->setBeamlet(nullptr); } - muse::DeleteAll(m_beamSegments); - m_beamSegments.clear(); + BeamBase::clearBeamSegments(); } //------------------------------------------------------- diff --git a/src/engraving/dom/beam.h b/src/engraving/dom/beam.h index d05dd76f6a8d1..d9e9d30dd81ec 100644 --- a/src/engraving/dom/beam.h +++ b/src/engraving/dom/beam.h @@ -23,8 +23,6 @@ #ifndef MU_ENGRAVING_BEAM_H #define MU_ENGRAVING_BEAM_H -#include - #include "beambase.h" #include "engravingitem.h" #include "property.h" @@ -39,46 +37,12 @@ class Beam; enum class ActionIconType; enum class SpannerSegmentType; -//--------------------------------------------------------- -// BeamFragment -// position of primary beam -// idx 0 - DirectionV::AUTO or DirectionV::DOWN -// 1 - DirectionV::UP -//--------------------------------------------------------- - -struct BeamFragment { - double py1[2]; - double py2[2]; -}; - -class BeamSegment -{ - OBJECT_ALLOCATOR(engraving, BeamSegment) -public: - LineF line; - int level = 0; - bool above = false; // above level 0 or below? (meaningless for level 0) - Fraction startTick; - Fraction endTick; - bool isBeamlet = false; - bool isBefore = false; - - Shape shape() const; - EngravingItem* parentElement = nullptr; - - BeamSegment(EngravingItem* b); -}; - struct TremAnchor { ChordRest* chord1 = nullptr; double y1 = 0.; double y2 = 0.; }; -enum class ChordBeamAnchorType { - Start, End, Middle -}; - //--------------------------------------------------------- // @@ Beam //--------------------------------------------------------- @@ -130,8 +94,7 @@ class Beam final : public BeamBase void setId(int i) const { m_id = i; } int id() const { return m_id; } - void setBeamDirection(DirectionV d); - DirectionV beamDirection() const { return m_direction; } + void setDirection(DirectionV d) override; void calcBeamBreaks(const ChordRest* chord, const ChordRest* prevChord, int level, bool& isBroken32, bool& isBroken64) const; @@ -145,9 +108,6 @@ class Beam final : public BeamBase void setGrowLeft(double val) { m_growLeft = val; } void setGrowRight(double val) { m_growRight = val; } - bool userModified() const; - void setUserModified(bool val); - PairF beamPos() const; void setBeamPos(const PairF& bp); double beamDist() const { return m_beamDist; } @@ -164,13 +124,6 @@ class Beam final : public BeamBase void computeAndSetSlope(); void setSlope(double val) { m_slope = val; } - const PointF& startAnchor() const { return m_startAnchor; } - PointF& startAnchor() { return m_startAnchor; } - void setStartAnchor(const PointF& p) { m_startAnchor = p; } - const PointF& endAnchor() const { return m_endAnchor; } - PointF& endAnchor() { return m_endAnchor; } - void setEndAnchor(const PointF& p) { m_endAnchor = p; } - PropertyValue getProperty(Pid propertyId) const override; bool setProperty(Pid propertyId, const PropertyValue&) override; PropertyValue propertyDefault(Pid id) const override; @@ -214,9 +167,7 @@ class Beam final : public BeamBase std::vector& beamFragments() { return m_fragments; } void addBeamFragment(BeamFragment* f) { m_fragments.push_back(f); } - const std::vector& beamSegments() const { return m_beamSegments; } - std::vector& beamSegments() { return m_beamSegments; } - void clearBeamSegments(); + void clearBeamSegments() override; const StaffType* tab() const { return m_tab; } void setTab(const StaffType* t) { m_tab = t; } @@ -230,8 +181,6 @@ class Beam final : public BeamBase const BeamSegment* topLevelSegmentForElement(const ChordRest* element) const; - inline int directionIdx() const { return (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; } - private: friend class Factory; @@ -247,10 +196,7 @@ class Beam final : public BeamBase void removeChordRest(ChordRest* a); std::vector m_elements; // must be sorted by tick - std::vector m_beamSegments; - DirectionV m_direction = DirectionV::AUTO; - bool m_userModified[2]{ false }; // 0: auto/down 1: up bool m_isGrace = false; bool m_cross = false; bool m_fullCross = false; @@ -260,8 +206,6 @@ class Beam final : public BeamBase double m_beamDist = 0.0; int m_beamSpacing = 3; // how far apart beams are spaced in quarter spaces double m_beamWidth = 0.0; // how wide each beam is - PointF m_startAnchor; - PointF m_endAnchor; // for tabs bool m_isBesideTabStaff = false; diff --git a/src/engraving/dom/beambase.cpp b/src/engraving/dom/beambase.cpp index 331a3bb8f4c66..6b6b32472e5d9 100644 --- a/src/engraving/dom/beambase.cpp +++ b/src/engraving/dom/beambase.cpp @@ -31,7 +31,14 @@ BeamBase::BeamBase(const ElementType& type, EngravingItem* parent, ElementFlags BeamBase::BeamBase(const BeamBase& b) : EngravingItem(b) { + for (const BeamSegment* bs : b.m_beamSegments) { + m_beamSegments.push_back(new BeamSegment(*bs)); + } _crossStaffMove = b._crossStaffMove; + m_direction = b.m_direction; + m_up = b.m_up; + m_userModified[0] = b.m_userModified[0]; + m_userModified[1] = b.m_userModified[1]; } void BeamBase::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps) @@ -51,6 +58,10 @@ PropertyValue BeamBase::getProperty(Pid propertyId) const switch (propertyId) { case Pid::BEAM_CROSS_STAFF_MOVE: return crossStaffMove(); + case Pid::STEM_DIRECTION: + return direction(); + case Pid::USER_MODIFIED: + return userModified(); default: return EngravingItem::getProperty(propertyId); } @@ -62,6 +73,12 @@ bool BeamBase::setProperty(Pid propertyId, const PropertyValue& v) case Pid::BEAM_CROSS_STAFF_MOVE: setCrossStaffMove(v.toInt()); break; + case Pid::STEM_DIRECTION: + setDirection(v.value()); + break; + case Pid::USER_MODIFIED: + setUserModified(v.toBool()); + break; default: if (!EngravingItem::setProperty(propertyId, v)) { return false; @@ -79,6 +96,10 @@ PropertyValue BeamBase::propertyDefault(Pid propertyId) const switch (propertyId) { case Pid::BEAM_CROSS_STAFF_MOVE: return 0; + case Pid::STEM_DIRECTION: + return DirectionV::AUTO; + case Pid::USER_MODIFIED: + return false; default: return EngravingItem::propertyDefault(propertyId); } @@ -100,3 +121,21 @@ bool BeamBase::acceptCrossStaffMove(int move) const int newCrossStaffIdx = defaultCrossStaffIdx() + move; return newCrossStaffIdx >= minCRMove() && newCrossStaffIdx <= maxCRMove() + 1; } + +bool BeamBase::userModified() const +{ + int idx = directionIdx(); + return m_userModified[idx]; +} + +void BeamBase::setUserModified(bool val) +{ + int idx = directionIdx(); + m_userModified[idx] = val; +} + +void BeamBase::clearBeamSegments() +{ + muse::DeleteAll(m_beamSegments); + m_beamSegments.clear(); +} diff --git a/src/engraving/dom/beambase.h b/src/engraving/dom/beambase.h index ff1618c99792a..30758addb25b5 100644 --- a/src/engraving/dom/beambase.h +++ b/src/engraving/dom/beambase.h @@ -34,6 +34,40 @@ enum class BeamType { TREMOLO }; +//--------------------------------------------------------- +// BeamFragment +// position of primary beam +// idx 0 - DirectionV::AUTO or DirectionV::DOWN +// 1 - DirectionV::UP +//--------------------------------------------------------- + +struct BeamFragment { + double py1[2]; + double py2[2]; +}; + +enum class ChordBeamAnchorType { + Start, End, Middle +}; + +class BeamSegment +{ + OBJECT_ALLOCATOR(engraving, BeamSegment) +public: + LineF line; + int level = 0; + bool above = false; // above level 0 or below? (meaningless for level 0) + Fraction startTick; + Fraction endTick; + bool isBeamlet = false; + bool isBefore = false; + + Shape shape() const; + EngravingItem* parentElement = nullptr; + + BeamSegment(EngravingItem* b); +}; + class BeamBase : public EngravingItem { OBJECT_ALLOCATOR(engraving, BeamBase) @@ -57,6 +91,26 @@ class BeamBase : public EngravingItem bool up() const { return m_up; } void setUp(bool v) { m_up = v; } + bool userModified() const; + void setUserModified(bool val); + + DirectionV direction() const { return m_direction; } + void doSetDirection(DirectionV val) { m_direction = val; } + virtual void setDirection(DirectionV v) = 0; + + inline int directionIdx() const { return (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; } + + const std::vector& beamSegments() const { return m_beamSegments; } + std::vector& beamSegments() { return m_beamSegments; } + virtual void clearBeamSegments(); + + const PointF& startAnchor() const { return m_startAnchor; } + PointF& startAnchor() { return m_startAnchor; } + void setStartAnchor(const PointF& p) { m_startAnchor = p; } + const PointF& endAnchor() const { return m_endAnchor; } + PointF& endAnchor() { return m_endAnchor; } + void setEndAnchor(const PointF& p) { m_endAnchor = p; } + void undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps = PropertyFlags::NOSTYLE) override; struct NotePosition { @@ -135,8 +189,14 @@ class BeamBase : public EngravingItem protected: BeamBase(const ElementType& type, EngravingItem* parent, ElementFlags flags = ElementFlag::NOTHING); BeamBase(const BeamBase&); + std::vector m_beamSegments; + PointF m_startAnchor; + PointF m_endAnchor; +private: bool m_up = true; + bool m_userModified[2]{ false }; // 0: auto/down 1: up + DirectionV m_direction = DirectionV::AUTO; }; } diff --git a/src/engraving/dom/tremolotwochord.cpp b/src/engraving/dom/tremolotwochord.cpp index 138e35c3932fd..ea072c22a337c 100644 --- a/src/engraving/dom/tremolotwochord.cpp +++ b/src/engraving/dom/tremolotwochord.cpp @@ -30,7 +30,6 @@ #include "rendering/score/beamtremololayout.h" -#include "beam.h" #include "chord.h" #include "stem.h" #include "system.h" @@ -120,7 +119,7 @@ PointF TremoloTwoChord::chordBeamAnchor(const ChordRest* chord, ChordBeamAnchorT RectF TremoloTwoChord::drag(EditData& ed) { - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; + int idx = directionIdx(); double dy = ed.pos.y() - ed.lastPos.y(); double y1 = m_beamFragment.py1[idx]; @@ -147,6 +146,9 @@ RectF TremoloTwoChord::drag(EditData& ed) void TremoloTwoChord::setTremoloType(TremoloType t) { + IF_ASSERT_FAILED(t >= TremoloType::C8) { + return; + } m_tremoloType = t; switch (tremoloType()) { case TremoloType::R16: @@ -206,26 +208,22 @@ PointF TremoloTwoChord::pagePos() const // setBeamDirection //--------------------------------------------------------- -void TremoloTwoChord::setBeamDirection(DirectionV d) +void TremoloTwoChord::setDirection(DirectionV d) { - if (m_direction == d) { + if (direction() == d) { return; } - m_direction = d; + doSetDirection(d); if (d != DirectionV::AUTO) { - m_up = d == DirectionV::UP; + setUp(d == DirectionV::UP); } - if (twoNotes()) { - if (m_chord1) { - m_chord1->setStemDirection(d); - } - if (m_chord2) { - m_chord2->setStemDirection(d); - } - } else { - chord()->setStemDirection(d); + if (m_chord1) { + m_chord1->setStemDirection(d); + } + if (m_chord2) { + m_chord2->setStemDirection(d); } } @@ -236,29 +234,10 @@ void TremoloTwoChord::setBeamDirection(DirectionV d) bool TremoloTwoChord::crossStaffBeamBetween() const { - if (!twoNotes()) { - return false; - } - return ((m_chord1->staffMove() > m_chord2->staffMove()) && m_chord1->up() && !m_chord2->up()) || ((m_chord1->staffMove() < m_chord2->staffMove()) && !m_chord1->up() && m_chord2->up()); } -void TremoloTwoChord::setUserModified(DirectionV d, bool val) -{ - switch (d) { - case DirectionV::AUTO: - m_userModified[0] = val; - break; - case DirectionV::DOWN: - m_userModified[0] = val; - break; - case DirectionV::UP: - m_userModified[1] = val; - break; - } -} - TDuration TremoloTwoChord::durationType() const { return m_durationType; @@ -300,8 +279,8 @@ Fraction TremoloTwoChord::tremoloLen() const void TremoloTwoChord::setBeamPos(const PairF& bp) { - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; - m_userModified[idx] = true; + int idx = directionIdx(); + setUserModified(true); setGenerated(false); double _spatium = spatium(); @@ -315,38 +294,18 @@ void TremoloTwoChord::setBeamPos(const PairF& bp) PairF TremoloTwoChord::beamPos() const { - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; + int idx = directionIdx(); double _spatium = spatium(); return PairF(m_beamFragment.py1[idx] / _spatium, m_beamFragment.py2[idx] / _spatium); } -//--------------------------------------------------------- -// userModified -//--------------------------------------------------------- - -bool TremoloTwoChord::userModified() const -{ - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; - return m_userModified[idx]; -} - -//--------------------------------------------------------- -// setUserModified -//--------------------------------------------------------- - -void TremoloTwoChord::setUserModified(bool val) -{ - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; - m_userModified[idx] = val; -} - //--------------------------------------------------------- // triggerLayout //--------------------------------------------------------- void TremoloTwoChord::triggerLayout() const { - if (twoNotes() && m_chord1 && m_chord2) { + if (m_chord1 && m_chord2) { toChordRest(m_chord1)->triggerLayout(); toChordRest(m_chord2)->triggerLayout(); } else { @@ -356,22 +315,22 @@ void TremoloTwoChord::triggerLayout() const bool TremoloTwoChord::needStartEditingAfterSelecting() const { - return twoNotes(); + return true; } int TremoloTwoChord::gripsCount() const { - return twoNotes() ? 3 : 0; + return 3; } Grip TremoloTwoChord::initialEditModeGrip() const { - return twoNotes() ? Grip::END : Grip::NO_GRIP; + return Grip::END; } Grip TremoloTwoChord::defaultGrip() const { - return twoNotes() ? Grip::MIDDLE : Grip::NO_GRIP; + return Grip::MIDDLE; } //--------------------------------------------------------- @@ -380,11 +339,7 @@ Grip TremoloTwoChord::defaultGrip() const std::vector TremoloTwoChord::gripsPositions(const EditData&) const { - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; - - if (!twoNotes()) { - return std::vector(); - } + int idx = directionIdx(); int y = pagePos().y(); double beamStartX = m_startAnchor.x() + m_chord1->pageX(); @@ -414,7 +369,7 @@ void TremoloTwoChord::endEdit(EditData& ed) void TremoloTwoChord::editDrag(EditData& ed) { - int idx = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; + int idx = directionIdx(); double dy = ed.delta.y(); double y1 = m_beamFragment.py1[idx]; double y2 = m_beamFragment.py2[idx]; @@ -462,8 +417,7 @@ String TremoloTwoChord::accessibleInfo() const bool TremoloTwoChord::customStyleApplicable() const { - return twoNotes() - && (durationType().type() == DurationType::V_HALF) + return (durationType().type() == DurationType::V_HALF) && (staffType()->group() != StaffGroup::TAB); } @@ -483,7 +437,7 @@ PropertyValue TremoloTwoChord::getProperty(Pid propertyId) const default: break; } - return EngravingItem::getProperty(propertyId); + return BeamBase::getProperty(propertyId); } //--------------------------------------------------------- @@ -501,12 +455,6 @@ bool TremoloTwoChord::setProperty(Pid propertyId, const PropertyValue& val) setTremoloStyle(TremoloStyle(val.toInt())); } break; - case Pid::STEM_DIRECTION: - setBeamDirection(val.value()); - break; - case Pid::USER_MODIFIED: - setUserModified(val.toBool()); - break; case Pid::BEAM_POS: if (userModified()) { setBeamPos(val.value()); @@ -516,7 +464,7 @@ bool TremoloTwoChord::setProperty(Pid propertyId, const PropertyValue& val) setPlayTremolo(val.toBool()); break; default: - return EngravingItem::setProperty(propertyId, val); + return BeamBase::setProperty(propertyId, val); } triggerLayout(); return true; @@ -534,7 +482,7 @@ PropertyValue TremoloTwoChord::propertyDefault(Pid propertyId) const case Pid::PLAY: return true; default: - return EngravingItem::propertyDefault(propertyId); + return BeamBase::propertyDefault(propertyId); } } @@ -565,8 +513,7 @@ void TremoloTwoChord::clearBeamSegments() } } - muse::DeleteAll(m_beamSegments); - m_beamSegments.clear(); + BeamBase::clearBeamSegments(); } int TremoloTwoChord::maxCRMove() const @@ -582,10 +529,7 @@ int TremoloTwoChord::minCRMove() const // used for palettes PainterPath TremoloTwoChord::basePath(double stretch) const { - if (isBuzzRoll()) { - return PainterPath(); - } - bool tradAlternate = twoNotes() && m_style == TremoloStyle::TRADITIONAL_ALTERNATE; + bool tradAlternate = m_style == TremoloStyle::TRADITIONAL_ALTERNATE; if (tradAlternate && muse::RealIsEqual(stretch, 0.)) { // this shape will have to be constructed after the stretch // is known @@ -598,7 +542,7 @@ PainterPath TremoloTwoChord::basePath(double stretch) const const double sp = spatium() * chordMag(); // overall width of two-note tremolos should not be changed if chordMag() isn't 1.0 - double w2 = sp * style().styleS(Sid::tremoloWidth).val() * .5 / (twoNotes() ? chordMag() : 1.0); + double w2 = sp * style().styleS(Sid::tremoloWidth).val() * .5 / chordMag(); double lw = sp * style().styleS(Sid::tremoloLineWidth).val(); double td = sp * style().styleS(Sid::tremoloDistance).val(); @@ -623,7 +567,7 @@ PainterPath TremoloTwoChord::basePath(double stretch) const ty += td; } - if (!explicitParent() || !twoNotes()) { + if (!explicitParent()) { // for the palette or for one-note tremolos Transform shearTransform; shearTransform.shear(0.0, -(lw / 2.0) / w2); @@ -635,11 +579,7 @@ PainterPath TremoloTwoChord::basePath(double stretch) const void TremoloTwoChord::computeShape() { - if (isBuzzRoll()) { - setbbox(symBbox(SymId::buzzRoll)); - } else { - m_path = basePath(); - setbbox(m_path.boundingRect()); - } + m_path = basePath(); + setbbox(m_path.boundingRect()); } } diff --git a/src/engraving/dom/tremolotwochord.h b/src/engraving/dom/tremolotwochord.h index a64ea4d5a28c1..708de9682e891 100644 --- a/src/engraving/dom/tremolotwochord.h +++ b/src/engraving/dom/tremolotwochord.h @@ -23,8 +23,6 @@ #ifndef MU_ENGRAVING_TREMOLOTWOCHORD_H #define MU_ENGRAVING_TREMOLOTWOCHORD_H -#include - #include "beambase.h" #include "engravingitem.h" @@ -58,11 +56,6 @@ class TremoloTwoChord final : public BeamBase void setTremoloType(TremoloType t); TremoloType tremoloType() const { return m_tremoloType; } - DirectionV direction() const { return m_direction; } - void setDirection(DirectionV val) { m_direction = val; } - - void setUserModified(DirectionV d, bool val); - double minHeight() const; void reset() override; @@ -71,8 +64,6 @@ class TremoloTwoChord final : public BeamBase double chordMag() const; RectF drag(EditData&) override; - void layout2(); - Chord* chord1() const { return m_chord1; } void setChord1(Chord* ch) { m_chord1 = ch; } Chord* chord2() const { return m_chord2; } @@ -88,16 +79,9 @@ class TremoloTwoChord final : public BeamBase TDuration durationType() const; void setDurationType(TDuration d); - bool userModified() const; - void setUserModified(bool val); - Fraction tremoloLen() const; - bool isBuzzRoll() const { return m_tremoloType == TremoloType::BUZZ_ROLL; } - bool twoNotes() const { return m_tremoloType >= TremoloType::C8; } // is it a two note tremolo? int lines() const { return m_lines; } - bool placeMidStem() const; - bool crossStaffBeamBetween() const; PointF pagePos() const override; ///< position in page coordinates @@ -106,7 +90,7 @@ class TremoloTwoChord final : public BeamBase TremoloStyle tremoloStyle() const { return m_style; } void setTremoloStyle(TremoloStyle v) { m_style = v; } - void setBeamDirection(DirectionV v); + void setDirection(DirectionV v) override; void setBeamFragment(const BeamFragment& bf) { m_beamFragment = bf; } const BeamFragment& beamFragment() const { return m_beamFragment; } BeamFragment& beamFragment() { return m_beamFragment; } @@ -120,7 +104,6 @@ class TremoloTwoChord final : public BeamBase bool setProperty(Pid propertyId, const PropertyValue&) override; PropertyValue propertyDefault(Pid propertyId) const override; - // only need grips for two-note trems bool needStartEditingAfterSelecting() const override; int gripsCount() const override; Grip initialEditModeGrip() const override; @@ -131,16 +114,7 @@ class TremoloTwoChord final : public BeamBase void endEdit(EditData&) override; void editDrag(EditData&) override; - const PointF& startAnchor() const { return m_startAnchor; } - PointF& startAnchor() { return m_startAnchor; } - void setStartAnchor(const PointF& p) { m_startAnchor = p; } - const PointF& endAnchor() const { return m_endAnchor; } - PointF& endAnchor() { return m_endAnchor; } - void setEndAnchor(const PointF& p) { m_endAnchor = p; } - - const std::vector& beamSegments() const { return m_beamSegments; } - std::vector& beamSegments() { return m_beamSegments; } - void clearBeamSegments(); + void clearBeamSegments() override; int maxCRMove() const override; int minCRMove() const override; @@ -160,18 +134,12 @@ class TremoloTwoChord final : public BeamBase void setBeamPos(const PairF& bp); - TremoloType m_tremoloType = TremoloType::R8; + TremoloType m_tremoloType = TremoloType::INVALID_TREMOLO; Chord* m_chord1 = nullptr; Chord* m_chord2 = nullptr; TDuration m_durationType; - bool m_userModified[2]{ false }; // 0: auto/down 1: up - DirectionV m_direction = DirectionV::AUTO; - std::vector m_beamSegments; bool m_playTremolo = true; - PointF m_startAnchor; - PointF m_endAnchor; - int m_lines = 0; // derived from _subtype TremoloStyle m_style = TremoloStyle::DEFAULT; // for _startAnchor and _slope, once we decide to change trems so that they can diff --git a/src/engraving/rendering/score/beamlayout.cpp b/src/engraving/rendering/score/beamlayout.cpp index 744d4c3696305..4a9a31b0cb0df 100644 --- a/src/engraving/rendering/score/beamlayout.cpp +++ b/src/engraving/rendering/score/beamlayout.cpp @@ -155,8 +155,8 @@ void BeamLayout::layout1(Beam* item, LayoutContext& ctx) } if (item->staff()->isDrumStaff(Fraction(0, 1))) { - if (item->beamDirection() != DirectionV::AUTO) { - item->setUp(item->beamDirection() == DirectionV::UP); + if (item->direction() != DirectionV::AUTO) { + item->setUp(item->direction() == DirectionV::UP); } else if (item->isGrace()) { item->setUp(true); } else { @@ -224,8 +224,8 @@ void BeamLayout::layout1(Beam* item, LayoutContext& ctx) Measure* measure = firstNote->measure(); bool hasMultipleVoices = measure->hasVoices(firstNote->staffIdx(), item->tick(), item->ticks()); if (computeUpForMovedCross(item)) { - } else if (item->beamDirection() != DirectionV::AUTO) { - item->setUp(item->beamDirection() == DirectionV::UP); + } else if (item->direction() != DirectionV::AUTO) { + item->setUp(item->direction() == DirectionV::UP); } else if (item->maxCRMove() > 0) { item->setUp(false); } else if (item->minCRMove() < 0) { @@ -265,7 +265,7 @@ void BeamLayout::layout1(Beam* item, LayoutContext& ctx) if (item->minCRMove() == item->maxCRMove() && item->minCRMove() != 0) { isEntirelyMoved = true; item->setStaffIdx(staffIdx); - if (item->beamDirection() == DirectionV::AUTO) { + if (item->direction() == DirectionV::AUTO) { item->setUp(item->maxCRMove() > 0); } } else if (item->elements().size()) { @@ -1489,7 +1489,6 @@ void BeamLayout::setTremAnchors(Beam* item, const LayoutContext& ctx) // there is an inset tremolo here! // figure out up / down bool tremUp = t->up(); - //int fragmentIndex = (m_direction == DirectionV::AUTO || m_direction == DirectionV::DOWN) ? 0 : 1; if (item->userModified()) { tremUp = c->up(); } else if (item->cross() && t->chord1()->staffMove() == t->chord2()->staffMove()) { diff --git a/src/engraving/rendering/score/tremololayout.cpp b/src/engraving/rendering/score/tremololayout.cpp index e381df682c1d9..f24bdcfc8f9ae 100644 --- a/src/engraving/rendering/score/tremololayout.cpp +++ b/src/engraving/rendering/score/tremololayout.cpp @@ -55,18 +55,6 @@ void TremoloLayout::layout(TremoloTwoChord* item, const LayoutContext& ctx) } else { // center tremolo above note x = anchor1->x() + anchor1->headWidth() * 0.5; - if (!item->twoNotes()) { - bool hasMirroredNote = false; - for (Note* n : item->chord1()->notes()) { - if (n->ldata()->mirror.value()) { - hasMirroredNote = true; - break; - } - } - if (hasMirroredNote) { - x = item->chord1()->stemPosX(); - } - } y = anchor1->y(); h = (ctx.conf().styleMM(Sid::tremoloNoteSidePadding).val() + item->ldata()->bbox().height()) * item->chord1()->intrinsicMag(); } @@ -187,7 +175,7 @@ void TremoloLayout::layoutTwoNotesTremolo(TremoloTwoChord* item, const LayoutCon if (item->chord1()->beam() && item->chord1()->beam() == item->chord2()->beam()) { Beam* beam = item->chord1()->beam(); item->setUp(beam->up()); - item->setDirection(beam->beamDirection()); + item->doSetDirection(beam->direction()); // stem stuff is already taken care of by the beams } else if (!item->userModified()) { // user modified trems will be dealt with later @@ -233,7 +221,7 @@ void TremoloLayout::layoutTwoNotesTremolo(TremoloTwoChord* item, const LayoutCon // deal with manual adjustments here and return PropertyValue val = item->getProperty(Pid::PLACEMENT); if (item->userModified()) { - int idx = (item->direction() == DirectionV::AUTO || item->direction() == DirectionV::DOWN) ? 0 : 1; + int idx = item->directionIdx(); double startY = item->beamFragment().py1[idx]; double endY = item->beamFragment().py2[idx]; if (ctx.conf().styleB(Sid::snapCustomBeamsToGrid)) { @@ -280,7 +268,7 @@ void TremoloLayout::layoutTwoNotesTremolo(TremoloTwoChord* item, const LayoutCon item->setStartAnchor(item->ldata()->startAnchor); item->setEndAnchor(item->ldata()->endAnchor); - int idx = (item->direction() == DirectionV::AUTO || item->direction() == DirectionV::DOWN) ? 0 : 1; + int idx = item->directionIdx(); item->beamFragment().py1[idx] = item->startAnchor().y() - item->pagePos().y(); item->beamFragment().py2[idx] = item->endAnchor().y() - item->pagePos().y(); createBeamSegments(item, ctx); @@ -327,10 +315,6 @@ void TremoloLayout::createBeamSegments(TremoloTwoChord* item, const LayoutContex item->clearBeamSegments(); - if (!item->twoNotes()) { - return; - } - bool _isGrace = item->chord1()->isGrace(); const PointF pagePos = item->pagePos(); PointF startAnchor = item->ldata()->startAnchor - PointF(0.0, pagePos.y()); diff --git a/src/engraving/rw/read400/tread.cpp b/src/engraving/rw/read400/tread.cpp index 5516cea9fb11d..7a9e488318677 100644 --- a/src/engraving/rw/read400/tread.cpp +++ b/src/engraving/rw/read400/tread.cpp @@ -1567,7 +1567,7 @@ void TRead::read(Beam* b, XmlReader& e, ReadContext& ctx) b->setGrowRight(e.readDouble()); } else if (tag == "Fragment") { BeamFragment* f = new BeamFragment; - int idx = (b->beamDirection() == DirectionV::AUTO || b->beamDirection() == DirectionV::DOWN) ? 0 : 1; + int idx = (b->direction() == DirectionV::AUTO || b->direction() == DirectionV::DOWN) ? 0 : 1; b->setUserModified(true); double _spatium = b->spatium(); while (e.readNextStartElement()) { @@ -4153,8 +4153,8 @@ void TRead::read(TremoloCompat& t, XmlReader& e, ReadContext& ctx) } else if (tag == "Fragment") { if (t.two) { BeamFragment f = BeamFragment(); - int idx = (t.two->direction() == DirectionV::AUTO || t.two->direction() == DirectionV::DOWN) ? 0 : 1; - t.two->setUserModified(t.two->direction(), true); + int idx = t.two->directionIdx(); + t.two->setUserModified(true); double _spatium = t.two->spatium(); while (e.readNextStartElement()) { const AsciiStringView tag1(e.name()); diff --git a/src/engraving/rw/read410/tread.cpp b/src/engraving/rw/read410/tread.cpp index 1e00243749a03..0f78597c5ead1 100644 --- a/src/engraving/rw/read410/tread.cpp +++ b/src/engraving/rw/read410/tread.cpp @@ -1758,7 +1758,7 @@ void TRead::read(Beam* b, XmlReader& e, ReadContext& ctx) b->setGrowRight(e.readDouble()); } else if (tag == "Fragment") { BeamFragment* f = new BeamFragment; - int idx = (b->beamDirection() == DirectionV::AUTO || b->beamDirection() == DirectionV::DOWN) ? 0 : 1; + int idx = b->directionIdx(); b->setUserModified(true); double _spatium = b->spatium(); while (e.readNextStartElement()) { @@ -4563,8 +4563,8 @@ void TRead::read(compat::TremoloCompat* tc, XmlReader& e, ReadContext& ctx) } else if (tag == "Fragment") { if (tc->two) { BeamFragment f = BeamFragment(); - int idx = (tc->two->direction() == DirectionV::AUTO || tc->two->direction() == DirectionV::DOWN) ? 0 : 1; - tc->two->setUserModified(tc->two->direction(), true); + int idx = tc->two->directionIdx(); + tc->two->setUserModified(true); double _spatium = tc->two->spatium(); while (e.readNextStartElement()) { const AsciiStringView tag1(e.name()); diff --git a/src/engraving/rw/write/twrite.cpp b/src/engraving/rw/write/twrite.cpp index 924eacc07307e..9a3483751b55c 100644 --- a/src/engraving/rw/write/twrite.cpp +++ b/src/engraving/rw/write/twrite.cpp @@ -3024,7 +3024,7 @@ void TWrite::write(const TremoloTwoChord* item, XmlWriter& xml, WriteContext& ct writeItemProperties(item, xml, ctx); // write manual adjustments to file - int idx = (item->direction() == DirectionV::AUTO || item->direction() == DirectionV::DOWN) ? 0 : 1; + int idx = item->directionIdx(); if (item->userModified()) { double _spatium = item->spatium(); diff --git a/src/engraving/tests/beam_tests.cpp b/src/engraving/tests/beam_tests.cpp index 3ddaabf61ff54..c86316b42a536 100644 --- a/src/engraving/tests/beam_tests.cpp +++ b/src/engraving/tests/beam_tests.cpp @@ -193,7 +193,7 @@ TEST_F(Engraving_BeamTests, beamStemDir) Measure* m1 = score->firstMeasure(); ChordRest* cr = toChordRest(m1->findSegment(SegmentType::ChordRest, m1->tick())->element(0)); - cr->beam()->setBeamDirection(DirectionV::UP); + cr->beam()->setDirection(DirectionV::UP); score->update(); score->doLayout(); @@ -223,7 +223,7 @@ TEST_F(Engraving_BeamTests, flipBeamStemDir) score->startCmd(); score->cmdFlip(); score->endCmd(); - cr->beam()->setBeamDirection(DirectionV::DOWN); + cr->beam()->setDirection(DirectionV::DOWN); score->update(); score->doLayout(); diff --git a/src/importexport/musicxml/internal/musicxml/importmxmlpass2.cpp b/src/importexport/musicxml/internal/musicxml/importmxmlpass2.cpp index fa0c364b7776f..d862d733283b1 100644 --- a/src/importexport/musicxml/internal/musicxml/importmxmlpass2.cpp +++ b/src/importexport/musicxml/internal/musicxml/importmxmlpass2.cpp @@ -2279,7 +2279,7 @@ static void handleBeamAndStemDir(ChordRest* cr, const BeamMode bm, const Directi // create a new beam beam = Factory::createBeam(cr->score()->dummy()->system()); beam->setTrack(cr->track()); - beam->setBeamDirection(sd); + beam->setDirection(sd); } // add ChordRest to beam if (beam) {