Skip to content

Commit

Permalink
Calculate up for user modified tremolos
Browse files Browse the repository at this point in the history
  • Loading branch information
miiizen committed Sep 27, 2024
1 parent 03b2a59 commit 27fe07c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 40 deletions.
18 changes: 14 additions & 4 deletions src/engraving/rendering/score/chordlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "chordlayout.h"
#include "accidentalslayout.h"
#include "horizontalspacing.h"
#include "beamtremololayout.h"

#include "containers.h"

Expand Down Expand Up @@ -1297,6 +1298,18 @@ bool ChordLayout::isChordPosBelowBeam(Chord* item, Beam* beam)
return noteY > desiredY;
}

bool ChordLayout::isChordPosBelowTrem(const Chord* item, TremoloTwoChord* trem)
{
if (!item || !trem || !trem->ldata()->isValid()) {
return true;
}
Note* baseNote = item->up() ? item->downNote() : item->upNote();
double noteY = baseNote->pagePos().y();
double tremY = trem->chordBeamAnchor(item, ChordBeamAnchorType::Middle).y();

return noteY > tremY;
}

static bool computeUp_TremoloTwoNotesCase(const Chord* item, TremoloTwoChord* tremolo, const LayoutContext& ctx)
{
const Chord* c1 = tremolo->chord1();
Expand Down Expand Up @@ -1324,10 +1337,7 @@ static bool computeUp_TremoloTwoNotesCase(const Chord* item, TremoloTwoChord* tr
}

if (tremolo->userModified()) {
Note* baseNote = item->up() ? item->downNote() : item->upNote();
double tremY = tremolo->chordBeamAnchor(item, ChordBeamAnchorType::Middle).y();
double noteY = baseNote->pagePos().y();
return noteY > tremY;
return ChordLayout::isChordPosBelowTrem(item, tremolo);
} else if (cross) {
// unmodified cross-staff trem, should be one note per staff
if (item->staffMove() != 0) {
Expand Down
1 change: 1 addition & 0 deletions src/engraving/rendering/score/chordlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ChordLayout
static void computeUp(ChordRest* item, const LayoutContext& ctx);
static int computeAutoStemDirection(const std::vector<int>& noteDistances);
static bool isChordPosBelowBeam(Chord* item, Beam* beam);
static bool isChordPosBelowTrem(const Chord* item, TremoloTwoChord* trem);

static void layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_t staffIdx);
static double layoutChords2(std::vector<Note*>& notes, bool up, LayoutContext& ctx);
Expand Down
92 changes: 56 additions & 36 deletions src/engraving/rendering/score/tremololayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,54 @@ void TremoloLayout::layoutOneNoteTremolo(TremoloSingleChord* item, const LayoutC
item->setPos(x, y);
}

void TremoloLayout::calcIsUp(TremoloTwoChord* item)
{
if (item->userModified()) {
bool startChordUp = ChordLayout::isChordPosBelowTrem(item->chord1(), item);
bool endChordUp = ChordLayout::isChordPosBelowTrem(item->chord2(), item);

item->setUp(startChordUp || endChordUp);
item->chord1()->setUp(startChordUp);
item->chord2()->setUp(endChordUp);
return;
}

int up = 0;
bool isUp = item->up();
bool hasVoices = item->chord1()->measure()->hasVoices(item->chord1()->staffIdx(), item->chord1()->tick(),
item->chord2()->tick() - item->chord1()->tick());
if (item->chord1()->stemDirection() == DirectionV::AUTO
&& item->chord2()->stemDirection() == DirectionV::AUTO
&& item->chord1()->staffMove() == item->chord2()->staffMove()
&& !hasVoices) {
std::vector<int> noteDistances;
for (int distance : item->chord1()->noteDistances()) {
noteDistances.push_back(distance);
}
for (int distance : item->chord2()->noteDistances()) {
noteDistances.push_back(distance);
}
std::sort(noteDistances.begin(), noteDistances.end());
up = ChordLayout::computeAutoStemDirection(noteDistances);

isUp = up > 0;
} else if (item->chord1()->stemDirection() != DirectionV::AUTO) {
isUp = item->chord1()->stemDirection() == DirectionV::UP;
} else if (item->chord2()->stemDirection() != DirectionV::AUTO) {
isUp = item->chord2()->stemDirection() == DirectionV::UP;
} else if (item->chord1()->staffMove() > 0 || item->chord2()->staffMove() > 0) {
isUp = false;
} else if (item->chord1()->staffMove() < 0 || item->chord2()->staffMove() < 0) {
isUp = true;
} else if (hasVoices) {
isUp = item->chord1()->track() % 2 == 0;
}

item->setUp(isUp);
item->chord1()->setUp(item->chord1()->staffMove() == 0 ? isUp : !isUp); // if on a different staff, flip stem dir
item->chord2()->setUp(item->chord2()->staffMove() == 0 ? isUp : !isUp);
}

//---------------------------------------------------------
// layoutTwoNotesTremolo
//---------------------------------------------------------
Expand All @@ -170,48 +218,20 @@ void TremoloLayout::layoutTwoNotesTremolo(TremoloTwoChord* item, const LayoutCon
TremoloTwoChord::LayoutData* ldata = item->mutldata();

// make sure both stems are in the same direction
int up = 0;
bool isUp = item->up();
if (item->chord1()->beam() && item->chord1()->beam() == item->chord2()->beam()) {
Beam* beam = item->chord1()->beam();
item->setUp(beam->up());
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
bool hasVoices = item->chord1()->measure()->hasVoices(item->chord1()->staffIdx(), item->chord1()->tick(),
item->chord2()->tick() - item->chord1()->tick());
if (item->chord1()->stemDirection() == DirectionV::AUTO
&& item->chord2()->stemDirection() == DirectionV::AUTO
&& item->chord1()->staffMove() == item->chord2()->staffMove()
&& !hasVoices) {
std::vector<int> noteDistances;
for (int distance : item->chord1()->noteDistances()) {
noteDistances.push_back(distance);
}
for (int distance : item->chord2()->noteDistances()) {
noteDistances.push_back(distance);
}
std::sort(noteDistances.begin(), noteDistances.end());
up = ChordLayout::computeAutoStemDirection(noteDistances);
isUp = up > 0;
} else if (item->chord1()->stemDirection() != DirectionV::AUTO) {
isUp = item->chord1()->stemDirection() == DirectionV::UP;
} else if (item->chord2()->stemDirection() != DirectionV::AUTO) {
isUp = item->chord2()->stemDirection() == DirectionV::UP;
} else if (item->chord1()->staffMove() > 0 || item->chord2()->staffMove() > 0) {
isUp = false;
} else if (item->chord1()->staffMove() < 0 || item->chord2()->staffMove() < 0) {
isUp = true;
} else if (hasVoices) {
isUp = item->chord1()->track() % 2 == 0;
}
item->setUp(isUp);
item->chord1()->setUp(item->chord1()->staffMove() == 0 ? isUp : !isUp); // if on a different staff, flip stem dir
item->chord2()->setUp(item->chord2()->staffMove() == 0 ? isUp : !isUp);
} else {
TremoloLayout::calcIsUp(item);

ChordLayout::layoutStem(item->chord1(), ctx);
ChordLayout::layoutStem(item->chord2(), ctx);
if (!item->userModified()) {
// user modified trems will be dealt with later
ChordLayout::layoutStem(item->chord1(), ctx);
ChordLayout::layoutStem(item->chord2(), ctx);
}
LOGI() << "trem up: " << item->up() << " c1: " << item->chord1()->up() << " c2: " << item->chord2()->up();
}

BeamTremoloLayout::setupLData(item, item->mutldata(), ctx);
Expand Down
1 change: 1 addition & 0 deletions src/engraving/rendering/score/tremololayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class TremoloLayout
private:
static void layoutOneNoteTremolo(TremoloSingleChord* item, const LayoutContext& ctx, double x, double y, double h, double spatium);
static void layoutTwoNotesTremolo(TremoloTwoChord* item, const LayoutContext& ctx, double x, double y, double h, double spatium);
static void calcIsUp(TremoloTwoChord* item);
};
}

Expand Down
Binary file added vtest/scores/tremolo-adjusted.mscz
Binary file not shown.

0 comments on commit 27fe07c

Please sign in to comment.