Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <vector>
26 :
27 : #include "engravingitem.h"
28 :
29 : #include "draw/types/font.h"
30 :
31 : namespace muse::io {
32 : struct path_t;
33 : }
34 :
35 : namespace mu::engraving {
36 : class Chord;
37 : class Factory;
38 : class Harmony;
39 : class StringData;
40 : class Transaction;
41 :
42 : // Keep this in order - not used directly for comparisons, but the dots will appear in
43 : // this order in fret multidot mode. See fretproperties.cpp.
44 : enum class FretDotType : signed char {
45 : NORMAL = 0,
46 : CROSS,
47 : SQUARE,
48 : TRIANGLE = 3
49 : };
50 :
51 : enum class FretMarkerType : signed char {
52 : NONE,
53 : CIRCLE,
54 : CROSS
55 : };
56 :
57 : class FretItem
58 : {
59 : public:
60 : struct Barre {
61 : int startString = -1;
62 : int endString = -1;
63 :
64 36 : Barre() = default;
65 284 : Barre(int s, int e)
66 284 : : startString(s), endString(e) {}
67 :
68 523 : bool exists() const { return startString > -1; }
69 : };
70 :
71 : struct Dot {
72 : int fret = 0;
73 : FretDotType dtype = FretDotType::NORMAL;
74 : int fingering = 0; // NOTE:JT - possible future feature?
75 :
76 : Dot() = default;
77 1612 : Dot(int f, FretDotType t = FretDotType::NORMAL, bool isPartOfSlurBarre = false)
78 1612 : : fret(f), dtype(t), isPartOfSlurBarre(isPartOfSlurBarre) {}
79 :
80 2364 : bool exists() const { return fret > 0; }
81 : bool isPartOfSlurBarre = false;
82 : };
83 :
84 : struct Marker {
85 : FretMarkerType mtype = FretMarkerType::NONE;
86 :
87 505 : Marker() = default;
88 1115 : Marker(FretMarkerType t)
89 1115 : : mtype(t) {}
90 :
91 655 : bool exists() const { return mtype != FretMarkerType::NONE; }
92 : };
93 :
94 : struct MarkerTypeNameItem {
95 : FretMarkerType mtype = FretMarkerType::NONE;
96 : const char* name = nullptr;
97 : };
98 :
99 : struct DotTypeNameItem {
100 : FretDotType dtype = FretDotType::NORMAL;
101 : const char* name = nullptr;
102 : };
103 :
104 : static const std::vector<FretItem::MarkerTypeNameItem> markerTypeNameMap;
105 : static const std::vector<FretItem::DotTypeNameItem> dotTypeNameMap;
106 :
107 : static Char markerToChar(FretMarkerType t);
108 : static String markerTypeToName(FretMarkerType t);
109 : static FretMarkerType nameToMarkerType(String n);
110 : static String dotTypeToName(FretDotType t);
111 : static FretDotType nameToDotType(String n);
112 : };
113 :
114 : // The three main storage containers used by fret diagrams
115 : typedef std::map<int, FretItem::Barre> BarreMap;
116 : typedef std::map<int, FretItem::Marker> MarkerMap;
117 : typedef std::map<int, std::vector<FretItem::Dot> > DotMap;
118 :
119 : struct DiagramInfo {
120 : String harmonyName;
121 : String diagramXml;
122 : String diagramPattern;
123 : };
124 :
125 : //---------------------------------------------------------
126 : // @@ FretDiagram
127 : /// Fretboard diagram
128 : //
129 : // @P userMag double
130 : // @P strings int number of strings
131 : // @P frets int number of frets
132 : // @P fretOffset int
133 : //
134 : // Note that, while strings are zero-indexed, frets are one-indexed
135 : //---------------------------------------------------------
136 :
137 : class FretDiagram final : public EngravingItem
138 : {
139 302 : OBJECT_ALLOCATOR(engraving, FretDiagram)
140 1823 : DECLARE_CLASSOF(ElementType::FRET_DIAGRAM)
141 :
142 : public:
143 :
144 : ~FretDiagram();
145 :
146 : EngravingItem* linkedClone() override;
147 22 : FretDiagram* clone() const override { return new FretDiagram(*this); }
148 :
149 : Segment* segment() const;
150 :
151 : String patternFromDiagram() const;
152 : std::vector<String> harmoniesFromPattern(const String& pattern) const;
153 : std::vector<DiagramInfo> patternsFromHarmony(const String& harmonyName);
154 :
155 : void updateDiagram(const String& harmonyName);
156 :
157 : std::vector<LineF> dragAnchorLines() const override;
158 : double mainWidth() const;
159 :
160 2951 : int strings() const { return m_strings; }
161 1059 : int frets() const { return m_frets; }
162 : void setStrings(int n);
163 179 : void setFrets(int n) { m_frets = n; }
164 :
165 : void setDot(int string, int fret, bool add = false, FretDotType dtype = FretDotType::NORMAL);
166 : void addDotForDotStyleBarre(int string, int fret);
167 : void removeDotForDotStyleBarre(int string, int fret);
168 : void setBarre(int startString, int endString, int fret);
169 : void setBarre(int string, int fret, bool add = false);
170 : void setMarker(int string, FretMarkerType marker);
171 : /*void setFingering(int string, int finger);*/
172 :
173 : void clear();
174 : bool isClear() const;
175 :
176 : void undoSetFretDot(int _string, int _fret, bool _add = false, FretDotType _dtype = FretDotType::NORMAL);
177 : void undoSetFretMarker(int _string, FretMarkerType _mtype);
178 : void undoSetFretBarre(int _string, int _fret, bool _add = false);
179 : void undoFretClear();
180 2396 : int fretOffset() const { return m_fretOffset; }
181 14 : void setFretOffset(int val) { m_fretOffset = val; }
182 : int maxFrets() const { return m_maxFrets; }
183 : void setMaxFrets(int val) { m_maxFrets = val; }
184 657 : bool showNut() const { return m_showNut; }
185 156 : void setShowNut(bool val) { m_showNut = val; }
186 3710 : double userMag() const { return m_userMag; }
187 214 : void setUserMag(double m) { m_userMag = m; }
188 : int numPos() const;
189 :
190 2092 : Orientation orientation() const { return m_orientation; }
191 :
192 : String harmonyPlainText() const;
193 : String harmonyDisplayText() const;
194 3136 : Harmony* harmony() const { return m_harmony; }
195 : void setHarmony(String harmonyText);
196 :
197 : std::vector<FretItem::Dot> dot(int s, int f = 0) const;
198 : FretItem::Marker marker(int s) const;
199 : FretItem::Barre barre(int fret) const;
200 :
201 916 : const BarreMap& barres() const { return m_barres; }
202 57 : const DotMap& dots() const { return m_dots; }
203 1 : const MarkerMap& markers() const { return m_markers; }
204 :
205 : muse::draw::Font fretNumFont() const;
206 : muse::draw::Font fingeringFont() const;
207 :
208 : void init(StringData*, Chord*);
209 : void add(EngravingItem*) override;
210 : void remove(EngravingItem*) override;
211 :
212 : RectF drag(EditData&) override;
213 : bool acceptDrop(EditData&) const override;
214 : EngravingItem* drop(Transaction& tx, EditData&) override;
215 :
216 : void scanElements(std::function<void(EngravingItem*)> func) override;
217 :
218 : void undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps) override;
219 : using EngravingObject::undoChangeProperty;
220 : PropertyValue getProperty(Pid propertyId) const override;
221 : bool setProperty(Pid propertyId, const PropertyValue&) override;
222 : PropertyValue propertyDefault(Pid) const override;
223 :
224 : void setTrack(track_idx_t val) override;
225 :
226 : String accessibleInfo() const override;
227 : String screenReaderInfo() const override;
228 :
229 701 : bool showFingering() const { return m_showFingering; }
230 156 : void setShowFingering(bool v) { m_showFingering = v; }
231 0 : const std::vector<int>& fingering() const { return m_fingering; }
232 : void setFingering(std::vector<int> v);
233 :
234 : static FretDiagram* makeFromHarmonyOrFretDiagram(const EngravingItem* harmonyOrFretDiagram);
235 :
236 : bool isInFretBox() const;
237 : bool isCustom(const String& harmonyNameForCompare) const;
238 :
239 0 : bool allowTimeAnchor() const override { return ownershipParent() && parent()->isSegment(); }
240 :
241 : friend class FretUndoData;
242 :
243 : struct FingeringItem {
244 : String fingerNumber;
245 : PointF pos;
246 0 : FingeringItem(String s, PointF p)
247 0 : : fingerNumber(s), pos(p) {}
248 : };
249 :
250 : struct LayoutData : public EngravingItem::LayoutData {
251 : double stringLineWidth = 0.0;
252 : double nutLineWidth = 0.0;
253 : double nutY = 0.0;
254 : double stringDist = 0.0;
255 : double fretDist = 0.0;
256 : double markerSize = 0.0;
257 : double markerY = 0.0;
258 : double stringExtendTop = 0.0;
259 : double stringExtendBottom = 0.0;
260 : double dotDiameter = 0.0;
261 : double fretNumPadding = 0.0;
262 : double gridHeight = 0.0;
263 : std::vector<FingeringItem> fingeringItems;
264 : std::vector<PainterPath> slurPaths;
265 : String fretText = String();
266 : };
267 3879 : DECLARE_LAYOUTDATA_METHODS(FretDiagram)
268 :
269 : private:
270 : friend class Factory;
271 :
272 : FretDiagram(DummyParentOr<Segment> parent);
273 : FretDiagram(const FretDiagram&);
274 :
275 : void readHarmonyToDiagramFile(const muse::io::path_t& filePath) const;
276 :
277 : void initDefaultValues();
278 :
279 : void removeDot(int s, int f = 0);
280 : void removeBarre(int f);
281 : void removeBarres(int string, int fret = 0);
282 : void removeMarker(int s);
283 : void removeDotsMarkers(int ss, int es, int fret);
284 :
285 : static void applyDiagramPattern(FretDiagram* diagram, const String& pattern);
286 :
287 : int m_strings = 0;
288 : int m_frets = 0;
289 : int m_fretOffset = 0;
290 : int m_maxFrets = 0;
291 : bool m_showNut = false;
292 : Orientation m_orientation = Orientation::VERTICAL;
293 :
294 : // Barres are stored in the format: K: fret, V: barre struct
295 : BarreMap m_barres;
296 :
297 : // Dots stored as K: string, V: dot struct
298 : DotMap m_dots;
299 :
300 : // Markers stored as K: string, V: marker struct
301 : MarkerMap m_markers;
302 :
303 : Harmony* m_harmony = nullptr;
304 :
305 : double m_userMag = 1.0; // allowed 0.1 - 10.0
306 :
307 : bool m_showFingering = false;
308 : std::vector<int> m_fingering = std::vector<int>(m_strings, 0);
309 : };
310 : } // namespace mu::engraving
311 :
312 : #ifndef NO_QT_SUPPORT
313 0 : Q_DECLARE_METATYPE(mu::engraving::FretDiagram*)
314 : #endif
|