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 : #pragma once
23 :
24 : #include "engravingitem.h"
25 : #include "line.h"
26 : #include "property.h"
27 : #include "textbase.h"
28 :
29 : namespace mu::engraving {
30 : enum class GuitarBendType : unsigned char {
31 : BEND,
32 : PRE_BEND,
33 : GRACE_NOTE_BEND,
34 : SLIGHT_BEND,
35 :
36 : DIVE,
37 : PRE_DIVE,
38 : DIP,
39 : SCOOP,
40 : };
41 :
42 : enum class GuitarBendShowHoldLine : unsigned char {
43 : AUTO,
44 : SHOW,
45 : HIDE,
46 : };
47 :
48 : enum class ActionIconType : signed char;
49 :
50 : class GuitarBend final : public SLine
51 : {
52 740 : OBJECT_ALLOCATOR(engraving, GuitarBend)
53 : DECLARE_CLASSOF(ElementType::GUITAR_BEND)
54 :
55 1399 : M_PROPERTY2(DirectionV, direction, setDirection, DirectionV::AUTO)
56 9591 : M_PROPERTY2(int, bendAmountInQuarterTones, setBendAmountInQuarterTones, 4)
57 391 : M_PROPERTY2(GuitarBendShowHoldLine, showHoldLine, setShowHoldLine, GuitarBendShowHoldLine::AUTO)
58 1112 : M_PROPERTY2(float, startTimeFactor, setStartTimeFactor, 0.f)
59 1121 : M_PROPERTY2(float, endTimeFactor, setEndTimeFactor, 1.f)
60 :
61 : public:
62 : GuitarBend(EngravingObject* parent);
63 : GuitarBend(const GuitarBend&);
64 : ~GuitarBend() override;
65 :
66 4 : GuitarBend* clone() const override { return new GuitarBend(*this); }
67 :
68 : LineSegment* createLineSegment() override;
69 :
70 1600 : Anchor anchor() const override { return Anchor::NOTE; }
71 :
72 0 : bool allowTimeAnchor() const override { return false; }
73 :
74 : Note* startNote() const;
75 : Note* startNoteOfChain() const;
76 :
77 : Note* endNote() const;
78 : void changeBendAmount(int bendAmount, int startBendAmount);
79 : void setEndNotePitch(int pitch, int quarterToneOffset);
80 :
81 : bool isReleaseBend() const;
82 : bool isFullRelease() const;
83 : bool angledPreBend() const;
84 : bool isDive() const;
85 : bool isFullReleaseDive() const;
86 :
87 : static void fixNotesFrettingForGraceBend(Note* grace, Note* main);
88 : static void fixNotesFrettingForStandardBend(Note* startNote, Note* endNote);
89 : static Note* createEndNote(Note* startNote, GuitarBendType bendType = GuitarBendType::BEND);
90 :
91 : PropertyValue getProperty(Pid id) const override;
92 : bool setProperty(Pid propertyId, const PropertyValue& v) override;
93 : PropertyValue propertyDefault(Pid id) const override;
94 :
95 : static constexpr int SLACK_BEND_AMOUNT = -33;
96 : void computeBendAmount();
97 : int totBendAmountIncludingPrecedingBends() const;
98 : void computeBendText();
99 : void computeIsInvalidOrNeedsWarning();
100 : bool isInvalid() const { return m_isInvalid; }
101 : bool isBorderlineUnplayable() const { return m_isBorderlineUnplayable; }
102 : GuitarBend* overlappingBendOrDive() const;
103 :
104 : GuitarBend* findPrecedingBend() const;
105 : GuitarBend* findFollowingPreBendOrDive() const;
106 : WhammyBar* findOverlappingWhammyBar(Fraction startTick, Fraction endTick) const;
107 :
108 : void updateHoldLine();
109 3 : void setHoldLine(GuitarBendHold* hold) { m_holdLine = hold; }
110 1640 : GuitarBendHold* holdLine() const { return m_holdLine; }
111 :
112 : double lineWidth() const;
113 :
114 : Color curColor(const rendering::PaintOptions& opt) const override;
115 :
116 0 : DirectionV diveTabPos() const { return m_diveTabPos; }
117 0 : void setDiveTabPos(DirectionV v) { m_diveTabPos = v; }
118 :
119 : static void adaptBendsFromTabToStandardStaff(const Staff* staff);
120 :
121 : static GuitarBendType bendTypeFromActionIcon(ActionIconType actionIconType);
122 107818 : GuitarBendType bendType() const { return m_bendType; }
123 : void setBendType(GuitarBendType t);
124 :
125 154 : VibratoType dipVibratoType() const { return m_dipVibratoType; }
126 0 : void setDipVibratoType(VibratoType v) { m_dipVibratoType = v; }
127 :
128 3846 : bool isSlack() const { return m_isSlack; }
129 0 : void setIsSlack(bool v) { m_isSlack = v; }
130 :
131 324 : std::optional<float> targetTimeFactor() const { return m_targetTimeFactor; }
132 : void setTargetTimeFactor(float v);
133 :
134 : struct LayoutData : public SLine::LayoutData
135 : {
136 : public:
137 6631 : bool up() const { return m_up; }
138 1095 : void setUp(bool v) { m_up = v; }
139 :
140 2190 : bool isInside() const { return m_isInside; }
141 1095 : void setIsInside(bool v) { m_isInside = v; }
142 :
143 106 : const String& bendDigit() const { return m_bendDigit; }
144 1537 : void setBendDigit(const String& s) { m_bendDigit = s; }
145 :
146 0 : const std::set<int>& diveLevels() const { return m_diveLevels; }
147 0 : void resetDiveLevels() { m_diveLevels.clear(); }
148 0 : void setDiveLevels(const std::set<int>& v) { m_diveLevels = v; }
149 :
150 0 : bool aboveStaff() const { return m_aboveStaff; }
151 0 : void setAboveStaff(bool v) { m_aboveStaff = v; }
152 :
153 : private:
154 : bool m_up = true;
155 : bool m_isInside = false;
156 : String m_bendDigit;
157 : std::set<int> m_diveLevels;
158 : bool m_aboveStaff = false;
159 : };
160 13053 : DECLARE_LAYOUTDATA_METHODS(GuitarBend)
161 :
162 : protected:
163 505 : bool isInSpannerMap() const override { return false; }
164 :
165 : private:
166 : GuitarBendType m_bendType = GuitarBendType::BEND;
167 : GuitarBendHold* m_holdLine = nullptr;
168 : bool m_isInvalid = false;
169 : bool m_isBorderlineUnplayable = false;
170 : DirectionV m_diveTabPos = DirectionV::AUTO;
171 : VibratoType m_dipVibratoType = VibratoType::NONE;
172 : bool m_isSlack = false;
173 : std::optional<float> m_targetTimeFactor;
174 : };
175 :
176 : class GuitarBendText; // forward decl
177 : class GuitarBendSegment final : public LineSegment
178 : {
179 738 : OBJECT_ALLOCATOR(engraving, GuitarBendSegment)
180 : DECLARE_CLASSOF(ElementType::GUITAR_BEND_SEGMENT)
181 :
182 : public:
183 : GuitarBendSegment(GuitarBend* sp);
184 : GuitarBendSegment(const GuitarBendSegment&);
185 : ~GuitarBendSegment() override;
186 :
187 9557 : GuitarBend* guitarBend() const { return toGuitarBend(spanner()); }
188 :
189 4 : GuitarBendSegment* clone() const override { return new GuitarBendSegment(*this); }
190 :
191 : int gripsCount() const override;
192 : std::vector<PointF> gripsPositions(const EditData& = EditData()) const override;
193 :
194 : PropertyValue getProperty(Pid id) const override;
195 : bool setProperty(Pid propertyId, const PropertyValue& v) override;
196 : PropertyValue propertyDefault(Pid id) const override;
197 : EngravingObject* propertyDelegate(Pid id) const override;
198 :
199 3735 : PointF vertexPointOff() const { return m_vertexPointOff; }
200 0 : void setVertexPointOff(PointF p) { m_vertexPointOff = p; }
201 :
202 : void reset() override;
203 :
204 : double lineWidth() const;
205 :
206 : void scanElements(std::function<void(EngravingItem*)> func) override;
207 :
208 3082 : GuitarBendText* bendText() const { return m_text; }
209 0 : void setBendText(GuitarBendText* t) { m_text = t; }
210 :
211 : bool isUserModified() const override;
212 :
213 0 : std::vector<LineF> gripAnchorLines(Grip) const override { return {}; }
214 :
215 0 : Color curColor(const rendering::PaintOptions& opt) const override
216 : {
217 0 : return guitarBend()->curColor(opt);
218 : }
219 :
220 : struct LayoutData : public LineSegment::LayoutData
221 : {
222 : public:
223 95 : const PointF& vertexPoint() const { return m_vertexPoint; }
224 1242 : void setVertexPoint(PointF p) { m_vertexPoint = p; }
225 :
226 0 : const PainterPath& path() const { return m_path; }
227 1247 : void setPath(const PainterPath& path) { m_path = path; }
228 :
229 24 : const PolygonF& arrow() const { return m_arrow; }
230 1 : PolygonF& arrow() { return m_arrow; }
231 94 : void setArrow(const PolygonF& a) { m_arrow = a; }
232 :
233 : private:
234 : PointF m_vertexPoint = PointF(); // Coordinates relative to pos()
235 : PainterPath m_path = PainterPath();
236 : PolygonF m_arrow = PolygonF();
237 : };
238 4313 : DECLARE_LAYOUTDATA_METHODS(GuitarBendSegment)
239 :
240 : private:
241 : void startDragGrip(EditData& ed) override;
242 : void dragGrip(EditData& ed) override;
243 :
244 : PointF m_vertexPointOff = PointF();
245 : GuitarBendText* m_text = nullptr;
246 : };
247 :
248 : class GuitarBendHold final : public SLine
249 : {
250 6 : OBJECT_ALLOCATOR(engraving, GuitarBendHold)
251 : DECLARE_CLASSOF(ElementType::GUITAR_BEND_HOLD)
252 :
253 : public:
254 : GuitarBendHold(GuitarBend* parent);
255 : GuitarBendHold(const GuitarBendHold&);
256 :
257 0 : GuitarBendHold* clone() const override { return new GuitarBendHold(*this); }
258 :
259 12 : Anchor anchor() const override { return Anchor::NOTE; }
260 :
261 : LineSegment* createLineSegment() override;
262 :
263 : PropertyValue propertyDefault(Pid id) const override;
264 :
265 0 : bool allowTimeAnchor() const override { return false; }
266 :
267 : Note* startNote() const;
268 : Note* endNote() const;
269 :
270 6 : GuitarBend* guitarBend() const { return toGuitarBend(ownershipParent()); }
271 :
272 : double lineWidth() const;
273 :
274 : protected:
275 4 : bool isInSpannerMap() const override { return false; }
276 : };
277 :
278 : class GuitarBendHoldSegment final : public LineSegment
279 : {
280 4 : OBJECT_ALLOCATOR(engraving, GuitarBendHoldSegment)
281 : DECLARE_CLASSOF(ElementType::GUITAR_BEND_HOLD_SEGMENT)
282 :
283 : public:
284 : GuitarBendHoldSegment(GuitarBendHold* sp);
285 :
286 18 : GuitarBendHold* guitarBendHold() const { return toGuitarBendHold(spanner()); }
287 :
288 0 : GuitarBendHoldSegment* clone() const override { return new GuitarBendHoldSegment(*this); }
289 :
290 : GuitarBendSegment* startBendSeg() const { return m_startBendSeg; }
291 : GuitarBendSegment* endBendSeg() const { return m_endBendSeg; }
292 6 : void setStartBendSeg(GuitarBendSegment* s) { m_startBendSeg = s; }
293 6 : void setEndBendSeg(GuitarBendSegment* s) { m_endBendSeg = s; }
294 :
295 6 : double dashLength() const { return m_dashLength; }
296 :
297 6 : double lineWidth() const { return guitarBendHold()->lineWidth(); }
298 :
299 0 : std::vector<LineF> gripAnchorLines(Grip) const override { return {}; }
300 :
301 : struct LayoutData : LineSegment::LayoutData {
302 : public:
303 0 : const SymIdList& symIds() const { return m_symIds; }
304 0 : void setSymIds(const SymIdList& v) { m_symIds = v; }
305 :
306 : private:
307 : SymIdList m_symIds;
308 : };
309 8 : DECLARE_LAYOUTDATA_METHODS(GuitarBendHoldSegment)
310 :
311 : private:
312 : void dragGrip(EditData& ed) override;
313 :
314 : double m_dashLength = 3.0;
315 :
316 : GuitarBendSegment* m_startBendSeg = nullptr;
317 : GuitarBendSegment* m_endBendSeg = nullptr;
318 : };
319 :
320 : class GuitarBendText final : public TextBase
321 : {
322 738 : OBJECT_ALLOCATOR(engraving, GuitarBendText)
323 : DECLARE_CLASSOF(ElementType::GUITAR_BEND_TEXT)
324 :
325 : public:
326 : GuitarBendText(GuitarBendSegment* parent);
327 0 : GuitarBendText* clone() const override { return new GuitarBendText(*this); }
328 :
329 0 : bool isEditable() const override { return false; }
330 :
331 100 : bool positionRelativeToNoteheadRest() const override { return false; }
332 : };
333 : }
|