Skip to content

Commit b2dec45

Browse files
Merge pull request #19746 from mike-spa/guitarBends
A trip to Bendsville
2 parents 30a7714 + b2a83da commit b2dec45

File tree

83 files changed

+2741
-218
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2741
-218
lines changed

fonts/mscore/MusescoreIcon.ttf

3.29 KB
Binary file not shown.

src/engraving/dom/actionicon.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ enum class ActionIconType {
5757

5858
PARENTHESES,
5959
BRACKETS,
60+
61+
STANDARD_BEND,
62+
PRE_BEND,
63+
GRACE_NOTE_BEND,
64+
SLIGHT_BEND,
6065
};
6166

6267
//! Dummy element, used for drag&drop

src/engraving/dom/bend.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ class Factory;
3636
// @@ Bend
3737
//---------------------------------------------------------
3838

39+
/**********************************************************
40+
* OBSOLETE CLASS
41+
* Used to represent bends before version 4.2. Now
42+
* replaced by the GuitarBend class.
43+
*********************************************************/
44+
3945
enum class BendType {
4046
BEND = 0,
4147
BEND_RELEASE,

src/engraving/dom/chord.cpp

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "chordline.h"
3636
#include "drumset.h"
3737
#include "factory.h"
38+
#include "guitarbend.h"
3839
#include "hook.h"
3940
#include "key.h"
4041
#include "ledgerline.h"
@@ -2302,7 +2303,7 @@ void Chord::setSlash(bool flag, bool stemless)
23022303
// end into this chord or no.
23032304
//---------------------------------------------------------
23042305

2305-
void Chord::updateEndsGlissando()
2306+
void Chord::updateEndsGlissandoOrGuitarBend()
23062307
{
23072308
m_endsGlissando = false; // assume no glissando ends here
23082309
// scan all chord notes for glissandi ending on this chord
@@ -2357,7 +2358,11 @@ double Chord::intrinsicMag() const
23572358
m *= style().styleD(Sid::smallNoteMag);
23582359
}
23592360
if (m_noteType != NoteType::NORMAL) {
2360-
m *= style().styleD(Sid::graceNoteMag);
2361+
bool tabGraceSizeException = staffType()->isTabStaff() && isPreBendOrGraceBendStart()
2362+
&& !style().styleB(Sid::useCueSizeFretForGraceBends);
2363+
if (!tabGraceSizeException) {
2364+
m *= style().styleD(Sid::graceNoteMag);
2365+
}
23612366
}
23622367
return m;
23632368
}
@@ -2551,6 +2556,73 @@ void Chord::toGraceAfter()
25512556
}
25522557
}
25532558

2559+
bool Chord::isPreBendOrGraceBendStart() const
2560+
{
2561+
if (!isGrace()) {
2562+
return false;
2563+
}
2564+
2565+
for (const Note* note : m_notes) {
2566+
GuitarBend* gb = note->bendFor();
2567+
if (gb && (gb->type() == GuitarBendType::PRE_BEND || gb->type() == GuitarBendType::GRACE_NOTE_BEND)) {
2568+
return true;
2569+
}
2570+
}
2571+
2572+
return false;
2573+
}
2574+
2575+
bool Chord::preOrGraceBendSpacingExceptionInTab() const
2576+
{
2577+
if (!staffType()->isTabStaff() || !isGrace()) {
2578+
return false;
2579+
}
2580+
2581+
std::vector<GuitarBend*> bends;
2582+
for (Note* note : m_notes) {
2583+
GuitarBend* bendFor = note->bendFor();
2584+
if (bendFor) {
2585+
GuitarBendType bendType = bendFor->type();
2586+
if (bendType == GuitarBendType::PRE_BEND || bendType == GuitarBendType::GRACE_NOTE_BEND) {
2587+
bends.push_back(bendFor);
2588+
break;
2589+
}
2590+
}
2591+
}
2592+
2593+
if (bends.empty() || bends.size() < m_notes.size()) {
2594+
return false;
2595+
}
2596+
2597+
Chord* endChord = bends.front()->endNote()->chord();
2598+
if (!endChord) {
2599+
return false;
2600+
}
2601+
2602+
GuitarBendType type = bends.front()->type();
2603+
for (GuitarBend* gb : bends) {
2604+
if (gb->type() != type || (gb->endNote() && gb->endNote()->chord() != endChord)) {
2605+
return false;
2606+
}
2607+
}
2608+
2609+
if (type == GuitarBendType::PRE_BEND) {
2610+
return true;
2611+
}
2612+
2613+
for (Note* note : endChord->notes()) {
2614+
GuitarBend* bendBack = note->bendBack();
2615+
if (bendBack) {
2616+
Note* startNote = bendBack->startNote();
2617+
if (!startNote || startNote->chord() != this) {
2618+
return false;
2619+
}
2620+
}
2621+
}
2622+
2623+
return bends.size() < endChord->notes().size();
2624+
}
2625+
25542626
//---------------------------------------------------------
25552627
// tremoloChordType
25562628
//---------------------------------------------------------
@@ -2603,6 +2675,7 @@ EngravingItem* Chord::nextElement()
26032675
break;
26042676
}
26052677

2678+
case ElementType::GUITAR_BEND_SEGMENT:
26062679
case ElementType::GLISSANDO_SEGMENT:
26072680
case ElementType::TIE_SEGMENT: {
26082681
SpannerSegment* s = toSpannerSegment(e);

src/engraving/dom/chord.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ class Chord final : public ChordRest
167167
void setTremolo(Tremolo* t, bool applyLogic = true);
168168

169169
ChordLine* chordLine() const;
170-
bool endsGlissando() const { return m_endsGlissando; }
171-
void setEndsGlissando(bool val) { m_endsGlissando = val; }
172-
void updateEndsGlissando();
170+
bool endsGlissandoOrGuitarBend() const { return m_endsGlissando; }
171+
void setEndsGlissandoOrGuitarBend(bool val) { m_endsGlissando = val; }
172+
void updateEndsGlissandoOrGuitarBend();
173173
StemSlash* stemSlash() const { return m_stemSlash; }
174174
bool slash();
175175
void setSlash(bool flag, bool stemless);
@@ -210,6 +210,9 @@ class Chord final : public ChordRest
210210
bool isGrace() const { return m_noteType != NoteType::NORMAL; }
211211
void toGraceAfter();
212212

213+
bool isPreBendOrGraceBendStart() const;
214+
bool preOrGraceBendSpacingExceptionInTab() const;
215+
213216
void setTrack(track_idx_t val) override;
214217

215218
double dotPosX() const { return m_dotPosX; }

src/engraving/dom/cmd.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#include "drumset.h"
4444
#include "dynamic.h"
4545
#include "factory.h"
46+
#include "glissando.h"
47+
#include "guitarbend.h"
4648
#include "hairpin.h"
4749
#include "harmony.h"
4850
#include "key.h"
@@ -834,6 +836,126 @@ Note* Score::setGraceNote(Chord* ch, int pitch, NoteType type, int len)
834836
return note;
835837
}
836838

839+
Note* Score::addEndNoteForBend(Note* startNote)
840+
{
841+
track_idx_t track = startNote->track();
842+
Chord* startChord = startNote->chord();
843+
Segment* startSegment = startChord->segment();
844+
845+
Segment* endSegment = startSegment->nextCR(track);
846+
if (!endSegment) {
847+
return nullptr;
848+
}
849+
850+
EngravingItem* item = endSegment->elementAt(track);
851+
if (!item || !item->isRest()) {
852+
return nullptr;
853+
}
854+
855+
Rest* rest = toRest(item);
856+
Fraction duration = std::min(startChord->ticks(), rest->ticks());
857+
NoteVal noteVal = startNote->noteVal();
858+
859+
endSegment = setNoteRest(endSegment, track, noteVal, duration);
860+
Chord* endChord = endSegment ? toChord(endSegment->elementAt(track)) : nullptr;
861+
Note* endNote = endChord ? endChord->upNote() : nullptr;
862+
if (endNote) {
863+
endNote->transposeDiatonic(1, true, false);
864+
}
865+
866+
return endNote;
867+
}
868+
869+
GuitarBend* Score::addGuitarBend(GuitarBendType type, Note* note, Note* endNote)
870+
{
871+
if (note->isPreBendStart()) {
872+
return nullptr;
873+
}
874+
875+
if (note->isGraceBendStart() && type != GuitarBendType::PRE_BEND) {
876+
return nullptr;
877+
}
878+
879+
Chord* chord = note->chord();
880+
881+
if (type == GuitarBendType::BEND) {
882+
for (Spanner* sp : note->spannerFor()) {
883+
if (sp->isGuitarBend() || sp->isGlissando()) {
884+
return nullptr;
885+
}
886+
}
887+
888+
if (!endNote) {
889+
endNote = Glissando::guessFinalNote(chord, note);
890+
}
891+
892+
if (!endNote) {
893+
endNote = addEndNoteForBend(note);
894+
}
895+
896+
if (!endNote) {
897+
return nullptr;
898+
}
899+
}
900+
901+
GuitarBend* bend = new GuitarBend(score()->dummy()->note());
902+
bend->setAnchor(Spanner::Anchor::NOTE);
903+
bend->setTick(chord->tick());
904+
bend->setTrack(chord->track());
905+
906+
if (type == GuitarBendType::BEND) {
907+
bend->setType(chord->isGrace() ? GuitarBendType::GRACE_NOTE_BEND : type);
908+
bend->setStartElement(note);
909+
bend->setTick2(endNote->tick());
910+
bend->setTrack2(endNote->track());
911+
bend->setEndElement(endNote);
912+
bend->setParent(note);
913+
GuitarBend::fixNotesFrettingForStandardBend(note, endNote);
914+
} else {
915+
bend->setType(type);
916+
bend->setTick2(chord->tick());
917+
bend->setTrack2(chord->track());
918+
919+
if (type == GuitarBendType::PRE_BEND || type == GuitarBendType::GRACE_NOTE_BEND) {
920+
// Create grace note
921+
Note* graceNote = setGraceNote(chord, note->pitch(), NoteType::APPOGGIATURA, Constants::DIVISION / 2);
922+
graceNote->transposeDiatonic(-1, true, false);
923+
GuitarBend::fixNotesFrettingForGraceBend(graceNote, note);
924+
925+
Chord* graceChord = graceNote->chord();
926+
for (EngravingObject* item : graceChord->linkList()) {
927+
Chord* linkedGrace = toChord(item);
928+
linkedGrace->undoChangeProperty(Pid::NO_STEM, true);
929+
linkedGrace->undoChangeProperty(Pid::BEAM_MODE, BeamMode::NONE);
930+
}
931+
932+
// Add bend
933+
bend->setParent(graceNote);
934+
bend->setStartElement(graceNote);
935+
bend->setEndElement(note);
936+
} else if (type == GuitarBendType::SLIGHT_BEND) {
937+
bend->setParent(note);
938+
bend->setStartElement(note);
939+
// Slight bends don't end on another note
940+
bend->setEndElement(note);
941+
}
942+
}
943+
944+
Chord* startChord = bend->startNote()->chord();
945+
if (startChord->isGrace()) {
946+
for (EngravingObject* item : startChord->linkList()) {
947+
Chord* linkedGrace = toChord(item);
948+
if (linkedGrace->staffType()->isTabStaff()) {
949+
linkedGrace->undoChangeProperty(Pid::NO_STEM, true);
950+
linkedGrace->undoChangeProperty(Pid::BEAM_MODE, BeamMode::NONE);
951+
}
952+
}
953+
}
954+
955+
score()->undoAddElement(bend);
956+
return bend;
957+
}
958+
837959
//---------------------------------------------------------
838960
// createCRSequence
839961
// Create a rest or chord of len f.

src/engraving/dom/dom.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ set(DOM_SRC
121121
${CMAKE_CURRENT_LIST_DIR}/gradualtempochange.h
122122
${CMAKE_CURRENT_LIST_DIR}/groups.cpp
123123
${CMAKE_CURRENT_LIST_DIR}/groups.h
124+
${CMAKE_CURRENT_LIST_DIR}/guitarbend.cpp
125+
${CMAKE_CURRENT_LIST_DIR}/guitarbend.h
124126
${CMAKE_CURRENT_LIST_DIR}/hairpin.cpp
125127
${CMAKE_CURRENT_LIST_DIR}/hairpin.h
126128
${CMAKE_CURRENT_LIST_DIR}/harmonicmark.cpp

src/engraving/dom/edit.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,6 +2798,7 @@ void Score::deleteItem(EngravingItem* el)
27982798
case ElementType::RASGUEADO_SEGMENT:
27992799
case ElementType::HARMONIC_MARK_SEGMENT:
28002800
case ElementType::PICK_SCRAPE_SEGMENT:
2801+
case ElementType::GUITAR_BEND_SEGMENT:
28012802
{
28022803
el = toSpannerSegment(el)->spanner();
28032804
undoRemoveElement(el);
@@ -5866,6 +5867,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
58665867
|| et == ElementType::NOTE
58675868
|| et == ElementType::TEXT
58685869
|| et == ElementType::GLISSANDO
5870+
|| et == ElementType::GUITAR_BEND
58695871
|| et == ElementType::BEND
58705872
|| (et == ElementType::CHORD && toChord(element)->isGrace())
58715873
) {
@@ -5879,7 +5881,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
58795881
links = 0;
58805882
}
58815883
}
5882-
if (links == 0) {
5884+
if (links == 0 || !addToLinkedStaves) {
58835885
undo(new AddElement(element));
58845886
return;
58855887
}
@@ -5889,8 +5891,8 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
58895891
if (e == parent) {
58905892
ne = element;
58915893
} else {
5892-
if (element->isGlissando()) { // and other spanners with Anchor::NOTE
5893-
Note* newEnd = Spanner::endElementFromSpanner(toGlissando(element), e);
5894+
if (element->isGlissando() || element->isGuitarBend()) { // and other spanners with Anchor::NOTE
5895+
Note* newEnd = Spanner::endElementFromSpanner(toSpanner(element), e);
58945896
if (newEnd) {
58955897
ne = element->linkedClone();
58965898
toSpanner(ne)->setNoteSpan(toNote(e), newEnd);
@@ -6267,7 +6269,7 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
62676269
}
62686270
}
62696271
undo(new AddElement(nsp));
6270-
} else if (et == ElementType::GLISSANDO) {
6272+
} else if (et == ElementType::GLISSANDO || et == ElementType::GUITAR_BEND) {
62716273
undo(new AddElement(toSpanner(ne)));
62726274
} else if (element->isTremolo() && toTremolo(element)->twoNotes()) {
62736275
Tremolo* tremolo = toTremolo(element);

src/engraving/dom/engravingitem.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,11 @@ PropertyPropagation EngravingItem::propertyPropagation(const EngravingItem* dest
13001300
const Score* destinationScore = destinationItem->score();
13011301
const bool isTextProperty = propertyGroup(propertyId) == PropertyGroup::TEXT;
13021302

1303-
if ((isTextProperty && isPropertyLinkedToMaster(propertyId)) || sourceScore == destinationScore) {
1303+
if (propertyGroup(propertyId) != PropertyGroup::TEXT && sourceScore == destinationScore) {
1304+
return PropertyPropagation::NONE;
1305+
}
1306+
1307+
if ((isTextProperty && isPropertyLinkedToMaster(propertyId))) {
13041308
return PropertyPropagation::PROPAGATE;
13051309
}
13061310

src/engraving/dom/engravingobject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ bool EngravingObject::isTextBase() const
729729
|| type() == ElementType::MMREST_RANGE
730730
|| type() == ElementType::STICKING
731731
|| type() == ElementType::HARP_DIAGRAM
732-
;
732+
|| type() == ElementType::GUITAR_BEND_TEXT;
733733
}
734734

735735
//---------------------------------------------------------

0 commit comments

Comments
 (0)