Skip to content

Commit 1dc02db

Browse files
authored
Merge pull request #31113 from miiizen/23712-transposeFretDiagrams
Transpose fret diagrams
2 parents 88e53ab + 4ae3dbd commit 1dc02db

32 files changed

+5176
-3184
lines changed

src/engraving/data/harmony_to_diagram.xml

Lines changed: 93 additions & 2940 deletions
Large diffs are not rendered by default.

src/engraving/dom/fret.cpp

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,6 @@ struct HarmonyMapKey
9696
}
9797
};
9898

99-
struct DiagramInfo {
100-
String harmonyName;
101-
String diagramXml;
102-
String diagramPattern;
103-
};
104-
10599
static std::map<HarmonyMapKey /*key*/, std::vector<DiagramInfo> > s_harmonyToDiagramMap;
106100
static std::unordered_map<String /*pattern*/, std::vector<String /*harmonyName*/> > s_diagramPatternToHarmoniesMap;
107101

@@ -244,16 +238,7 @@ Segment* FretDiagram::segment() const
244238

245239
void FretDiagram::updateDiagram(const String& harmonyName)
246240
{
247-
if (s_harmonyToDiagramMap.empty()) {
248-
readHarmonyToDiagramFile(HARMONY_TO_DIAGRAM_FILE_PATH);
249-
}
250-
251-
String _harmonyName = harmonyName;
252-
253-
NoteSpellingType spellingType = style().styleV(Sid::chordSymbolSpelling).value<NoteSpellingType>();
254-
HarmonyMapKey key = createHarmonyMapKey(_harmonyName, spellingType, score()->chordList());
255-
256-
std::vector<DiagramInfo> availableDiagrams = muse::value(s_harmonyToDiagramMap, key);
241+
std::vector<DiagramInfo> availableDiagrams = patternsFromHarmony(harmonyName);
257242
if (availableDiagrams.empty()) {
258243
return;
259244
}
@@ -272,6 +257,7 @@ void FretDiagram::updateDiagram(const String& harmonyName)
272257
read460::TRead::read(this, reader, ctx);
273258

274259
triggerLayout();
260+
return;
275261
}
276262

277263
//---------------------------------------------------------
@@ -761,21 +747,21 @@ void FretDiagram::applyDiagramPattern(FretDiagram* diagram, const String& patter
761747
}
762748
}
763749

764-
String FretDiagram::patternFromDiagram(const FretDiagram* diagram)
750+
String FretDiagram::patternFromDiagram() const
765751
{
766-
const int strings = diagram->strings();
767-
const int offset = diagram->fretOffset();
752+
const int diagramStrings = strings();
753+
const int offset = fretOffset();
768754

769755
StringList patternParts;
770-
const DotMap& dotsMap = diagram->dots();
756+
const DotMap& dotsMap = dots();
771757

772-
for (int i = 0; i < strings; ++i) {
773-
const FretItem::Marker marker = diagram->marker(i);
758+
for (int i = 0; i < diagramStrings; ++i) {
759+
const FretItem::Marker fretMarker = marker(i);
774760

775-
if (marker.mtype == FretMarkerType::CROSS) {
761+
if (fretMarker.mtype == FretMarkerType::CROSS) {
776762
patternParts.push_back(u"X");
777763
continue;
778-
} else if (marker.mtype == FretMarkerType::CIRCLE) {
764+
} else if (fretMarker.mtype == FretMarkerType::CIRCLE) {
779765
patternParts.push_back(u"O");
780766
continue;
781767
}
@@ -825,16 +811,16 @@ String FretDiagram::patternFromDiagram(const FretDiagram* diagram)
825811

826812
String pattern = patternParts.join(u"");
827813

828-
const BarreMap& barres = diagram->barres();
814+
const BarreMap& _barres = barres();
829815
StringList barreParts;
830-
for (const auto& [fret, b] : barres) {
816+
for (const auto& [fret, b] : _barres) {
831817
if (!b.exists()) {
832818
continue;
833819
}
834820

835821
int adjustedFret = fret + offset;
836822
int start = b.startString;
837-
int end = (b.endString != -1) ? b.endString : strings - 1;
823+
int end = (b.endString != -1) ? b.endString : diagramStrings - 1;
838824

839825
barreParts.push_back(u'B' + String::number(adjustedFret)
840826
+ u'[' + String::number(start)
@@ -848,11 +834,28 @@ String FretDiagram::patternFromDiagram(const FretDiagram* diagram)
848834
return pattern;
849835
}
850836

851-
std::vector<String> FretDiagram::patternHarmonies(const String& pattern)
837+
std::vector<String> FretDiagram::harmoniesFromPattern(const String& pattern) const
852838
{
839+
if (s_diagramPatternToHarmoniesMap.empty()) {
840+
readHarmonyToDiagramFile(HARMONY_TO_DIAGRAM_FILE_PATH);
841+
}
853842
return muse::value(s_diagramPatternToHarmoniesMap, pattern);
854843
}
855844

845+
std::vector<DiagramInfo> FretDiagram::patternsFromHarmony(const String& harmonyName)
846+
{
847+
if (s_harmonyToDiagramMap.empty()) {
848+
readHarmonyToDiagramFile(HARMONY_TO_DIAGRAM_FILE_PATH);
849+
}
850+
851+
String _harmonyName = harmonyName;
852+
853+
NoteSpellingType spellingType = style().styleV(Sid::chordSymbolSpelling).value<NoteSpellingType>();
854+
HarmonyMapKey key = createHarmonyMapKey(_harmonyName, spellingType, score()->chordList());
855+
856+
return muse::value(s_harmonyToDiagramMap, key);
857+
}
858+
856859
//---------------------------------------------------------
857860
// clear
858861
//---------------------------------------------------------
@@ -1002,7 +1005,7 @@ void FretDiagram::add(EngravingItem* e)
10021005
readHarmonyToDiagramFile(HARMONY_TO_DIAGRAM_FILE_PATH);
10031006
}
10041007

1005-
String pattern = patternFromDiagram(this);
1008+
String pattern = patternFromDiagram();
10061009
if (!pattern.empty()) {
10071010
std::vector<String> matchedHarmonies = muse::value(s_diagramPatternToHarmoniesMap, pattern);
10081011
if (!matchedHarmonies.empty()) {
@@ -1415,7 +1418,7 @@ bool FretDiagram::isCustom(const String& harmonyNameForCompare) const
14151418
return true;
14161419
}
14171420

1418-
String currentPattern = patternFromDiagram(this);
1421+
String currentPattern = patternFromDiagram();
14191422

14201423
for (const DiagramInfo& diagram : availableDiagrams) {
14211424
if (diagram.diagramPattern == currentPattern) {

src/engraving/dom/fret.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ typedef std::map<int, FretItem::Barre> BarreMap;
111111
typedef std::map<int, FretItem::Marker> MarkerMap;
112112
typedef std::map<int, std::vector<FretItem::Dot> > DotMap;
113113

114+
struct DiagramInfo {
115+
String harmonyName;
116+
String diagramXml;
117+
String diagramPattern;
118+
};
119+
114120
//---------------------------------------------------------
115121
// @@ FretDiagram
116122
/// Fretboard diagram
@@ -137,8 +143,9 @@ class FretDiagram final : public EngravingItem
137143

138144
Segment* segment() const;
139145

140-
static String patternFromDiagram(const FretDiagram* diagram);
141-
static std::vector<String> patternHarmonies(const String& pattern);
146+
String patternFromDiagram() const;
147+
std::vector<String> harmoniesFromPattern(const String& pattern) const;
148+
std::vector<DiagramInfo> patternsFromHarmony(const String& harmonyName);
142149

143150
void updateDiagram(const String& harmonyName);
144151

src/engraving/dom/mscore.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ bool MScore::svgPrinting = false;
6363
extern void initDrumset();
6464

6565
MsError MScore::_error { MsError::MS_NO_ERROR };
66+
bool MScore::_errorIsWarning = false;
6667

6768
void MScore::registerUiTypes()
6869
{
@@ -118,6 +119,7 @@ std::string MScore::errorToString(MsError err)
118119
case MsError::CANNOT_REMOVE_KEY_SIG: return "CANNOT_REMOVE_KEY_SIG";
119120
case MsError::CANNOT_JOIN_MEASURE_STAFFTYPE_CHANGE: return "CANNOT_JOIN_MEASURE_STAFFTYPE_CHANGE";
120121
case MsError::CANNOT_REPEAT_SELECTION: return "CANNOT_REPEAT_SELECTION";
122+
case MsError::TRANSPOSE_NO_FRET_DIAGRAM: return "TRANSPOSE_NO_FRET_DIAGRAM";
121123
}
122124

123125
return {};

src/engraving/dom/mscore.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ enum class MsError : unsigned char {
165165
CANNOT_REMOVE_KEY_SIG,
166166
CANNOT_JOIN_MEASURE_STAFFTYPE_CHANGE,
167167
CANNOT_REPEAT_SELECTION,
168+
TRANSPOSE_NO_FRET_DIAGRAM,
168169
};
169170

170171
/// \cond PLUGIN_API \private \endcond
@@ -187,6 +188,7 @@ class MScore
187188
public:
188189

189190
static MsError _error;
191+
static bool _errorIsWarning;
190192

191193
static void registerUiTypes();
192194

@@ -230,7 +232,7 @@ class MScore
230232
static double horizontalPageGapEven;
231233
static double horizontalPageGapOdd;
232234

233-
static void setError(MsError e) { _error = e; }
235+
static void setError(MsError e, bool warning = false) { _error = e; _errorIsWarning = warning; }
234236

235237
static std::string errorToString(MsError err);
236238
};

src/engraving/dom/pitchspelling.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,4 +1168,36 @@ Key clampKey(Key key, PreferSharpFlat prefer)
11681168

11691169
return key;
11701170
}
1171+
1172+
int bestEnharmonicFit(const std::vector<int> tpcs, Key key)
1173+
{
1174+
int keyIndex = int(key) - int(Key::MIN);
1175+
if (keyIndex < 0 || keyIndex >= int(Key::NUM_OF)) {
1176+
return tpcs.front();
1177+
}
1178+
1179+
// Highest penalty in enharmonicSpelling available (100) + 1
1180+
int bestPenalty = 101;
1181+
int closestTpc = Tpc::TPC_INVALID;
1182+
1183+
for (int tpc : tpcs) {
1184+
if (tpc == Tpc::TPC_INVALID) {
1185+
continue;
1186+
}
1187+
1188+
int lof = tpc - Tpc::TPC_MIN;
1189+
if (lof < 0 || lof >= 34) {
1190+
continue;
1191+
}
1192+
1193+
int penalty = enharmonicSpelling[keyIndex][lof];
1194+
1195+
if (penalty < bestPenalty) {
1196+
bestPenalty = penalty;
1197+
closestTpc = tpc;
1198+
}
1199+
}
1200+
1201+
return closestTpc;
1202+
}
11711203
}

src/engraving/dom/pitchspelling.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ extern int convertNote(const String& s, NoteSpellingType noteSpelling, NoteCaseT
104104
extern int clampEnharmonic(int tpc, bool useDoubleSharpsFlats = true);
105105
extern int clampPitch(int pitch, bool octaved = false);
106106
extern Key clampKey(Key key, PreferSharpFlat prefer = PreferSharpFlat::NONE);
107+
extern int bestEnharmonicFit(const std::vector<int> tpcs, Key key);
107108

108109
//---------------------------------------------------------
109110
// tpc2alter

src/engraving/editing/cmd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ void Score::endCmd(bool rollback, bool layoutAllParts)
414414
return;
415415
}
416416

417-
if (readOnly() || MScore::_error != MsError::MS_NO_ERROR) {
417+
if (readOnly() || (MScore::_error != MsError::MS_NO_ERROR && !MScore::_errorIsWarning)) {
418418
rollback = true;
419419
}
420420

0 commit comments

Comments
 (0)