grace notes code restructure
This commit is contained in:
parent
061527a7ee
commit
74ac594483
11 changed files with 154 additions and 106 deletions
|
@ -1165,20 +1165,17 @@ void LayoutChords::layoutChords3(const MStyle& style, std::vector<Note*>& notes,
|
|||
|
||||
/* updateGraceNotes()
|
||||
* Processes a full measure, making sure that all grace notes are
|
||||
* attacched to the correct segment.
|
||||
* attacched to the correct segment. Has to be performed after
|
||||
* all the segments are known.
|
||||
* */
|
||||
void LayoutChords::updateGraceNotes(Measure* measure)
|
||||
{
|
||||
Score* score = measure->score();
|
||||
for (Segment& s : measure->segments()) { // Clean everything
|
||||
for (unsigned track = 0; track < score->staves().size() * VOICES; ++track) {
|
||||
if (!s.graceNotesBefore(track).empty()) {
|
||||
s.graceNotesBefore(track).clear();
|
||||
s.createShape(track2staff(track));
|
||||
}
|
||||
if (!s.graceNotesAfter(track).empty()) {
|
||||
s.graceNotesAfter(track).clear();
|
||||
s.createShape(track2staff(track));
|
||||
EngravingItem* item = s.preAppendedItem(track);
|
||||
if (item && item->isGraceNotesGroup()) {
|
||||
s.clearPreAppended(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1189,39 +1186,65 @@ void LayoutChords::updateGraceNotes(Measure* measure)
|
|||
}
|
||||
for (auto el : s.elist()) {
|
||||
if (el && el->isChord()) {
|
||||
toChord(el)->attachGraceNotes();
|
||||
appendGraceNotes(toChord(el));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* layoutGraceNotes()
|
||||
* Needs to be called when creating the segment shape. Make sure it is called *last*,
|
||||
* so that grace notes can be correctly padded against the segment shape.*/
|
||||
void LayoutChords::layoutGraceNotes(Segment* seg, int staffIdx)
|
||||
void LayoutChords::appendGraceNotes(Chord* chord)
|
||||
{
|
||||
Score* score = seg->score();
|
||||
seg->createShape(staffIdx);
|
||||
Shape& segShape = seg->staffShape(staffIdx);
|
||||
int startTrack = staff2track(staffIdx, 0);
|
||||
int endTrack = startTrack + VOICES;
|
||||
for (int track = startTrack; track < endTrack; ++track) {
|
||||
if (seg->graceNotesBefore(track).empty() && seg->graceNotesAfter(track).empty()) {
|
||||
continue;
|
||||
Segment* segment = chord->segment();
|
||||
Measure* measure = chord->measure();
|
||||
int track = chord->track();
|
||||
int staffIdx = chord->staffIdx();
|
||||
GraceNotesGroup& gnb = chord->graceNotesBefore();
|
||||
GraceNotesGroup& gna = chord->graceNotesAfter();
|
||||
|
||||
//Attach graceNotesBefore of this chord to *this* segment
|
||||
if (!gnb.empty()) {
|
||||
// If this segment already contains grace notes in the same voice (could happen if a
|
||||
// previous chord has appended grace-notes-after here) put them in the same vector.
|
||||
EngravingItem* item = segment->preAppendedItem(track);
|
||||
if (item && item->isGraceNotesGroup()) {
|
||||
GraceNotesGroup* gng = toGraceNotesGroup(item);
|
||||
gng->insert(gng->end(), gnb.begin(), gnb.end());
|
||||
} else {
|
||||
segment->preAppend(&gnb, track);
|
||||
}
|
||||
if (!score->staves().at(staffIdx)->visible()) {
|
||||
continue;
|
||||
segment->createShape(staffIdx);
|
||||
}
|
||||
|
||||
//Attach graceNotesAfter of this chord to the *following* segment
|
||||
if (!gna.empty()) {
|
||||
Segment* followingSeg = measure->tick2segment(segment->tick() + chord->actualTicks(), SegmentType::All);
|
||||
while (followingSeg && !followingSeg->hasElements(staff2track(staffIdx), staff2track(staffIdx) + 3)) {
|
||||
// If there is nothing on this staff, go to next segment
|
||||
followingSeg = followingSeg->next();
|
||||
}
|
||||
// Collect grace-after and grace-before in a single vector
|
||||
std::vector<Chord*> gnCollector = seg->graceNotesAfter(track);
|
||||
gnCollector.insert(gnCollector.end(), seg->graceNotesBefore(track).begin(), seg->graceNotesBefore(track).end());
|
||||
// Compute grace notes spacing
|
||||
for (auto gn = gnCollector.rbegin(); gn != gnCollector.rend(); ++gn) { // Start layout from the last note
|
||||
Chord* GN = *gn;
|
||||
double offset = -GN->shape().minHorizontalDistance(segShape, score); // Pad the grace note against the segment shape
|
||||
segShape.add(GN->shape().translated(mu::PointF(offset, 0.0))); // Add grace note shape to segment shape
|
||||
double xpos = offset - GN->parentItem()->rxoffset() - GN->parentItem()->rxpos();
|
||||
GN->setPos(xpos, 0); // Set grace note position
|
||||
if (followingSeg) {
|
||||
followingSeg->preAppend(&gna, track);
|
||||
followingSeg->createShape(staffIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Grace-notes-after have the special property of belonging to
|
||||
* a segment but being pre-appended to another. This repositioning
|
||||
* is needed and must be called AFTER horizontal spacing is calculated. */
|
||||
void LayoutChords::repositionGraceNotesAfter(Segment* segment)
|
||||
{
|
||||
int tracks = segment->score()->staves().size() * VOICES;
|
||||
for (int track = 0; track < tracks; track++) {
|
||||
EngravingItem* item = segment->preAppendedItem(track);
|
||||
if (!item || !item->isGraceNotesGroup()) {
|
||||
continue;
|
||||
}
|
||||
GraceNotesGroup* gng = toGraceNotesGroup(item);
|
||||
for (Chord* chord : *gng) {
|
||||
double offset = segment->rxpos() - chord->parentItem()->parentItem()->rxpos();
|
||||
// Difference between the segment they "belong" and the segment they are "appended" to.
|
||||
chord->setPos(chord->pos().x() + offset, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ class Note;
|
|||
class Staff;
|
||||
class MStyle;
|
||||
class Measure;
|
||||
class Chord;
|
||||
}
|
||||
|
||||
namespace mu::engraving {
|
||||
|
@ -45,7 +46,8 @@ public:
|
|||
static qreal layoutChords2(std::vector<Ms::Note*>& notes, bool up);
|
||||
static void layoutChords3(const Ms::MStyle& style, std::vector<Ms::Note*>&, const Ms::Staff*, Ms::Segment*);
|
||||
static void updateGraceNotes(Ms::Measure* measure);
|
||||
static void layoutGraceNotes(Ms::Segment* seg, int staffIdx);
|
||||
static void repositionGraceNotesAfter(Ms::Segment* segment);
|
||||
static void appendGraceNotes(Ms::Chord* chord);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2006,28 +2006,6 @@ void Chord::scanElements(void* data, void (* func)(void*, EngravingItem*), bool
|
|||
ChordRest::scanElements(data, func, all);
|
||||
}
|
||||
|
||||
void Chord::attachGraceNotes()
|
||||
{
|
||||
//Attach graceNotesBefore of this chord to *this* segment
|
||||
if (!graceNotesBefore().empty()) {
|
||||
segment()->attachGraceNotesBefore(graceNotesBefore(), track());
|
||||
LayoutChords::layoutGraceNotes(segment(), staffIdx());
|
||||
}
|
||||
|
||||
//Attach graceNotesAfter of this chord to the *following* segment
|
||||
if (!graceNotesAfter().empty()) {
|
||||
Segment* followingSeg = measure()->tick2segment(segment()->tick() + actualTicks(), SegmentType::All);
|
||||
while (followingSeg && !followingSeg->hasElements(staff2track(staffIdx()), staff2track(staffIdx()) + 3)) {
|
||||
// If there is nothing on this staff, go to next segment
|
||||
followingSeg = followingSeg->next();
|
||||
}
|
||||
if (followingSeg) {
|
||||
followingSeg->attachGraceNotesAfter(graceNotesAfter(), track());
|
||||
LayoutChords::layoutGraceNotes(followingSeg, staffIdx());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// layoutPitched
|
||||
//---------------------------------------------------------
|
||||
|
@ -3307,9 +3285,9 @@ Measure* Chord::measure() const
|
|||
// graceNotesBefore
|
||||
//---------------------------------------------------------
|
||||
|
||||
std::vector<Chord*> Chord::graceNotesBefore() const
|
||||
GraceNotesGroup& Chord::graceNotesBefore() const
|
||||
{
|
||||
std::vector<Chord*> cl;
|
||||
_graceNotesBefore.clear();
|
||||
for (Chord* c : _graceNotes) {
|
||||
Q_ASSERT(c->noteType() != NoteType::NORMAL && c->noteType() != NoteType::INVALID);
|
||||
if (c->noteType() & (
|
||||
|
@ -3318,27 +3296,27 @@ std::vector<Chord*> Chord::graceNotesBefore() const
|
|||
| NoteType::GRACE4
|
||||
| NoteType::GRACE16
|
||||
| NoteType::GRACE32)) {
|
||||
cl.push_back(c);
|
||||
_graceNotesBefore.push_back(c);
|
||||
}
|
||||
}
|
||||
return cl;
|
||||
return _graceNotesBefore;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// graceNotesAfter
|
||||
//---------------------------------------------------------
|
||||
|
||||
std::vector<Chord*> Chord::graceNotesAfter() const
|
||||
GraceNotesGroup& Chord::graceNotesAfter() const
|
||||
{
|
||||
std::vector<Chord*> cl;
|
||||
_graceNotesAfter.clear();
|
||||
for (int i = static_cast<int>(_graceNotes.size()) - 1; i >= 0; i--) {
|
||||
Chord* c = _graceNotes[i];
|
||||
Q_ASSERT(c->noteType() != NoteType::NORMAL && c->noteType() != NoteType::INVALID);
|
||||
if (c->noteType() & (NoteType::GRACE8_AFTER | NoteType::GRACE16_AFTER | NoteType::GRACE32_AFTER)) {
|
||||
cl.push_back(c);
|
||||
_graceNotesAfter.push_back(c);
|
||||
}
|
||||
}
|
||||
return cl;
|
||||
return _graceNotesAfter;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -4119,4 +4097,33 @@ void Chord::setNoteEventLists(std::vector<NoteEventList>& ell)
|
|||
notes()[i]->setPlayEvents(ell[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
// GRACE NOTES
|
||||
//---------------------------------
|
||||
|
||||
GraceNotesGroup::GraceNotesGroup(Chord* c)
|
||||
: EngravingItem(ElementType::GRACE_NOTES_GROUP, c), _parent(c) {}
|
||||
|
||||
void GraceNotesGroup::layout()
|
||||
{
|
||||
_shape.clear();
|
||||
for (int i = this->size() - 1; i >= 0; --i) {
|
||||
Chord* chord = this->at(i);
|
||||
Shape chordShape = chord->shape();
|
||||
double offset;
|
||||
offset = -std::max(chordShape.minHorizontalDistance(_shape, score()), 0.0);
|
||||
_shape.add(chordShape.translated(mu::PointF(offset, 0.0)));
|
||||
double xpos = offset - parent()->rxoffset() - parent()->rxpos();
|
||||
chord->setPos(xpos, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void GraceNotesGroup::setPos(qreal x, qreal y)
|
||||
{
|
||||
for (unsigned i = 0; i < this->size(); ++i) {
|
||||
Chord* chord = this->at(i);
|
||||
chord->setPos(chord->pos().x() + x, chord->pos().y() + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,22 @@ enum class TremoloChordType : char {
|
|||
TremoloSingle, TremoloFirstNote, TremoloSecondNote
|
||||
};
|
||||
|
||||
class GraceNotesGroup final : public std::vector<Chord*>, public EngravingItem
|
||||
{
|
||||
public:
|
||||
GraceNotesGroup* clone() const override { return new GraceNotesGroup(*this); }
|
||||
GraceNotesGroup(Chord* c);
|
||||
|
||||
Chord* parent() const { return _parent; }
|
||||
Shape shape() const { return _shape; }
|
||||
void layout() override;
|
||||
void setPos(qreal x, qreal y) override;
|
||||
|
||||
private:
|
||||
Chord* _parent = nullptr;
|
||||
Shape _shape;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
// @@ Chord
|
||||
/// Graphic representation of a chord.
|
||||
|
@ -80,7 +96,9 @@ class Chord final : public ChordRest
|
|||
Arpeggio* _arpeggio = nullptr;
|
||||
Tremolo* _tremolo = nullptr;
|
||||
bool _endsGlissando; ///< true if this chord is the ending point of a glissando (needed for layout)
|
||||
std::vector<Chord*> _graceNotes;
|
||||
std::vector<Chord*> _graceNotes; // storage for all grace notes
|
||||
mutable GraceNotesGroup _graceNotesBefore = GraceNotesGroup(this); // will store before-chord grace notes
|
||||
mutable GraceNotesGroup _graceNotesAfter = GraceNotesGroup(this); // will store after-chord grace notes
|
||||
size_t _graceIndex; ///< if this is a grace note, index in parent list
|
||||
|
||||
DirectionV _stemDirection;
|
||||
|
@ -210,12 +228,11 @@ public:
|
|||
const std::vector<Chord*>& graceNotes() const { return _graceNotes; }
|
||||
std::vector<Chord*>& graceNotes() { return _graceNotes; }
|
||||
|
||||
std::vector<Chord*> graceNotesBefore() const;
|
||||
std::vector<Chord*> graceNotesAfter() const;
|
||||
GraceNotesGroup& graceNotesBefore() const;
|
||||
GraceNotesGroup& graceNotesAfter() const;
|
||||
|
||||
size_t graceIndex() const { return _graceIndex; }
|
||||
void setGraceIndex(size_t val) { _graceIndex = val; }
|
||||
void attachGraceNotes();
|
||||
|
||||
int upLine() const override;
|
||||
int downLine() const override;
|
||||
|
|
|
@ -328,8 +328,8 @@ public:
|
|||
virtual const mu::PointF pos() const { return _pos + _offset; }
|
||||
virtual qreal x() const { return _pos.x() + _offset.x(); }
|
||||
virtual qreal y() const { return _pos.y() + _offset.y(); }
|
||||
void setPos(qreal x, qreal y) { _pos.setX(x), _pos.setY(y); }
|
||||
void setPos(const mu::PointF& p) { _pos = p; }
|
||||
virtual void setPos(qreal x, qreal y) { _pos.setX(x), _pos.setY(y); }
|
||||
virtual void setPos(const mu::PointF& p) { _pos = p; }
|
||||
mu::PointF& rpos() { return _pos; }
|
||||
qreal& rxpos() { return _pos.rx(); }
|
||||
qreal& rypos() { return _pos.ry(); }
|
||||
|
|
|
@ -76,6 +76,7 @@ class StaffText;
|
|||
class Ottava;
|
||||
class Note;
|
||||
class Chord;
|
||||
class GraceNotesGroup;
|
||||
class Rest;
|
||||
class MMRest;
|
||||
class LayoutBreak;
|
||||
|
@ -401,6 +402,7 @@ public:
|
|||
CONVERT(BagpipeEmbellishment, BAGPIPE_EMBELLISHMENT)
|
||||
CONVERT(Lasso, LASSO)
|
||||
CONVERT(Sticking, STICKING)
|
||||
CONVERT(GraceNotesGroup, GRACE_NOTES_GROUP)
|
||||
#undef CONVERT
|
||||
|
||||
virtual bool isEngravingItem() const { return false; } // overridden in element.h
|
||||
|
@ -716,6 +718,7 @@ CONVERT(Part)
|
|||
CONVERT(Lasso)
|
||||
CONVERT(BagpipeEmbellishment)
|
||||
CONVERT(Sticking)
|
||||
CONVERT(GraceNotesGroup)
|
||||
#undef CONVERT
|
||||
}
|
||||
|
||||
|
|
|
@ -222,6 +222,7 @@ static const ElementName elementNames[] = {
|
|||
{ ElementType::OSSIA, "Ossia", QT_TRANSLATE_NOOP("elementName", "Ossia") },
|
||||
{ ElementType::BAGPIPE_EMBELLISHMENT,"BagpipeEmbellishment", QT_TRANSLATE_NOOP("elementName", "Bagpipe embellishment") },
|
||||
{ ElementType::STICKING, "Sticking", QT_TRANSLATE_NOOP("elementName", "Sticking") },
|
||||
{ ElementType::GRACE_NOTES_GROUP, "GraceNotesGroup", QT_TRANSLATE_NOOP("elementName", "Grace notes group")},
|
||||
{ ElementType::ROOT_ITEM, "RootItem", QT_TRANSLATE_NOOP("elementName", "Root item") },
|
||||
{ ElementType::DUMMY, "Dummy", QT_TRANSLATE_NOOP("elementName", "Dummy") },
|
||||
};
|
||||
|
@ -363,6 +364,7 @@ EngravingItem* Factory::doCreateItem(ElementType type, EngravingItem* parent)
|
|||
case ElementType::SCORE:
|
||||
case ElementType::BRACKET_ITEM:
|
||||
case ElementType::OSSIA:
|
||||
case ElementType::GRACE_NOTES_GROUP:
|
||||
case ElementType::ROOT_ITEM:
|
||||
case ElementType::DUMMY:
|
||||
break;
|
||||
|
|
|
@ -3220,7 +3220,7 @@ void Measure::layoutMeasureElements()
|
|||
}
|
||||
|
||||
// After the rest of the spacing is calculated we position grace-notes-after.
|
||||
s.positionGraceNotesAfter();
|
||||
LayoutChords::repositionGraceNotesAfter(&s);
|
||||
|
||||
for (EngravingItem* e : s.elist()) {
|
||||
if (!e) {
|
||||
|
@ -3642,11 +3642,6 @@ qreal Measure::createEndBarLines(bool isLastMeasureInSystem)
|
|||
}
|
||||
}
|
||||
|
||||
// May have grace notes attached to it so we need to lay them out
|
||||
for (unsigned stfIdx = 0; stfIdx < score()->staves().size(); ++stfIdx) {
|
||||
LayoutChords::layoutGraceNotes(seg, stfIdx);
|
||||
}
|
||||
|
||||
// fix segment layout
|
||||
Segment* s = seg->prevActive();
|
||||
if (s) {
|
||||
|
@ -4572,7 +4567,7 @@ void Measure::stretchMeasureInPracticeMode(qreal targetWidth)
|
|||
continue;
|
||||
}
|
||||
// After the rest of the spacing is calculated we position grace-notes-after.
|
||||
s.positionGraceNotesAfter();
|
||||
LayoutChords::repositionGraceNotesAfter(&s);
|
||||
for (EngravingItem* e : s.elist()) {
|
||||
if (!e) {
|
||||
continue;
|
||||
|
|
|
@ -236,10 +236,9 @@ void Segment::init()
|
|||
size_t staves = score()->nstaves();
|
||||
size_t tracks = staves * VOICES;
|
||||
_elist.assign(tracks, 0);
|
||||
_preAppendedItems.assign(tracks, 0);
|
||||
_dotPosX.assign(staves, 0.0);
|
||||
_shapes.assign(staves, Shape());
|
||||
_graceNotesBefore.assign(tracks, std::vector<Chord*>());
|
||||
_graceNotesAfter.assign(tracks, std::vector<Chord*>());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -493,8 +492,7 @@ void Segment::insertStaff(staff_idx_t staff)
|
|||
track_idx_t track = staff * VOICES;
|
||||
for (voice_idx_t voice = 0; voice < VOICES; ++voice) {
|
||||
_elist.insert(_elist.begin() + track, 0);
|
||||
_graceNotesBefore.insert(_graceNotesBefore.begin() + track, std::vector<Chord*>());
|
||||
_graceNotesAfter.insert(_graceNotesAfter.begin() + track, std::vector<Chord*>());
|
||||
_preAppendedItems.insert(_preAppendedItems.begin() + track, 0);
|
||||
}
|
||||
_dotPosX.insert(_dotPosX.begin() + staff, 0.0);
|
||||
_shapes.insert(_shapes.begin() + staff, Shape());
|
||||
|
@ -516,8 +514,7 @@ void Segment::removeStaff(staff_idx_t staff)
|
|||
{
|
||||
track_idx_t track = staff * VOICES;
|
||||
_elist.erase(_elist.begin() + track, _elist.begin() + track + VOICES);
|
||||
_graceNotesBefore.erase(_graceNotesBefore.begin() + track, _graceNotesBefore.begin() + track + VOICES);
|
||||
_graceNotesAfter.erase(_graceNotesAfter.begin() + track, _graceNotesAfter.begin() + track + VOICES);
|
||||
_preAppendedItems.erase(_preAppendedItems.begin() + track, _preAppendedItems.begin() + track + VOICES);
|
||||
_dotPosX.erase(_dotPosX.begin() + staff);
|
||||
_shapes.erase(_shapes.begin() + staff);
|
||||
|
||||
|
@ -2239,6 +2236,7 @@ void Segment::createShape(staff_idx_t staffIdx)
|
|||
s.add(r.translated(bl->pos()), bl);
|
||||
}
|
||||
s.addHorizontalSpacing(bl, 0, 0);
|
||||
addPreAppendedToShape(staffIdx, s);
|
||||
//s.addHorizontalSpacing(Shape::SPACING_LYRICS, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -2297,6 +2295,23 @@ void Segment::createShape(staff_idx_t staffIdx)
|
|||
s.add(e->shape().translated(e->pos()));
|
||||
}
|
||||
}
|
||||
|
||||
addPreAppendedToShape(staffIdx, s);
|
||||
}
|
||||
|
||||
void Segment::addPreAppendedToShape(int staffIdx, Shape& s)
|
||||
{
|
||||
for (unsigned track = staffIdx * VOICES; track < staffIdx * VOICES + VOICES; ++track) {
|
||||
if (!_preAppendedItems[track]) {
|
||||
continue;
|
||||
}
|
||||
EngravingItem* item = _preAppendedItems[track];
|
||||
item->layout();
|
||||
Shape itemShape = item->shape();
|
||||
double offset = -itemShape.minHorizontalDistance(s, score());
|
||||
s.add(itemShape.translated(mu::PointF(offset, 0.0)));
|
||||
item->setPos(offset, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -2631,19 +2646,4 @@ Fraction Segment::shortestChordRest() const
|
|||
}
|
||||
return shortest;
|
||||
}
|
||||
|
||||
/* positionGraceNotesAfter()
|
||||
* Moves grace-notes-after to the position of the segment. Needs to be called
|
||||
* after horizontal spacing is computed, otherwise the position of the segment
|
||||
* is not known. */
|
||||
void Segment::positionGraceNotesAfter()
|
||||
{
|
||||
int tracks = score()->staves().size() * VOICES;
|
||||
for (int track = 0; track < tracks; track++) {
|
||||
for (auto gn : _graceNotesAfter[track]) {
|
||||
double offset = rxpos() - gn->parentItem()->parentItem()->rxpos();
|
||||
gn->setPos(gn->pos().x() + offset, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Ms
|
||||
|
|
|
@ -73,10 +73,9 @@ class Segment final : public EngravingItem
|
|||
|
||||
std::vector<EngravingItem*> _annotations;
|
||||
std::vector<EngravingItem*> _elist; // EngravingItem storage, size = staves * VOICES.
|
||||
std::vector<EngravingItem*> _preAppendedItems; // Container for items appended to the left of this segment (example: grace notes), size = staves * VOICES.
|
||||
std::vector<Shape> _shapes; // size = staves
|
||||
std::vector<qreal> _dotPosX; // size = staves
|
||||
std::vector<std::vector<Chord*> > _graceNotesBefore; // We prepare an (initially empty) vector of grace notes for each voice
|
||||
std::vector<std::vector<Chord*> > _graceNotesAfter; // This will be filled with the grace-notes-after of a *previous* segment.
|
||||
qreal m_spacing{ 0 };
|
||||
|
||||
friend class mu::engraving::Factory;
|
||||
|
@ -290,14 +289,13 @@ public:
|
|||
bool isTimeSigAnnounceType() const { return _segmentType == SegmentType::TimeSigAnnounce; }
|
||||
bool isMMRestSegment() const;
|
||||
|
||||
void attachGraceNotesBefore(std::vector<Chord*> graceNotes, int track) { _graceNotesBefore[track] = graceNotes; }
|
||||
void attachGraceNotesAfter(std::vector<Chord*> graceNotes, int track) { _graceNotesAfter[track] = graceNotes; }
|
||||
std::vector<Chord*>& graceNotesBefore(int track) { return _graceNotesBefore[track]; }
|
||||
std::vector<Chord*>& graceNotesAfter(int track) { return _graceNotesAfter[track]; }
|
||||
void positionGraceNotesAfter();
|
||||
|
||||
Fraction shortestChordRest() const;
|
||||
|
||||
EngravingItem* preAppendedItem(int track) { return _preAppendedItems[track]; }
|
||||
void preAppend(EngravingItem* item, int track) { _preAppendedItems[track] = item; }
|
||||
void clearPreAppended(int track) { _preAppendedItems[track] = nullptr; }
|
||||
void addPreAppendedToShape(int staffIdx, Shape& s);
|
||||
|
||||
static constexpr SegmentType durationSegmentsMask = SegmentType::ChordRest; // segment types which may have non-zero tick length
|
||||
};
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ enum class ElementType {
|
|||
OSSIA,
|
||||
BAGPIPE_EMBELLISHMENT,
|
||||
STICKING,
|
||||
GRACE_NOTES_GROUP,
|
||||
|
||||
ROOT_ITEM,
|
||||
DUMMY,
|
||||
|
|
Loading…
Reference in a new issue