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 <functional>
26 :
27 : #include "../types/types.h"
28 :
29 : #include "durationelement.h"
30 : #include "fermata.h"
31 :
32 : namespace mu::engraving {
33 : enum class CrossMeasure : signed char {
34 : UNKNOWN = -1,
35 : NONE = 0,
36 : FIRST,
37 : SECOND
38 : };
39 :
40 : class Articulation;
41 : class BeamBase;
42 : class BeamSegment;
43 : class Lyrics;
44 : class Measure;
45 : class Score;
46 : class Segment;
47 : class Slur;
48 : class TabDurationSymbol;
49 : class Transaction;
50 : enum class SegmentType;
51 :
52 : //-------------------------------------------------------------------
53 : // ChordRest
54 : // Virtual base class. Chords and rests can be part of a beam
55 : //-------------------------------------------------------------------
56 :
57 : class ChordRest : public DurationElement
58 : {
59 0 : OBJECT_ALLOCATOR(engraving, ChordRest)
60 3902 : DECLARE_CLASSOF(ElementType::INVALID) // dummy
61 :
62 : public:
63 : ChordRest(const ElementType& type, DummyParentOr<Segment> parent);
64 : ChordRest(const ChordRest&, bool link = false);
65 : ChordRest& operator=(const ChordRest&) = delete;
66 : ~ChordRest();
67 :
68 : virtual void scanElements(std::function<void(EngravingItem*)> func) override;
69 :
70 : bool acceptDrop(EditData&) const override;
71 : virtual EngravingItem* drop(Transaction& tx, EditData&) override;
72 : virtual void undoUnlink() override;
73 :
74 95445 : virtual Segment* segment() const { return (Segment*)ownershipParent(); }
75 :
76 14733 : void setBeamMode(BeamMode m) { m_beamMode = m; }
77 532729 : BeamMode beamMode() const { return m_beamMode; }
78 :
79 : void setBeam(Beam* b);
80 : void setBeamlet(BeamSegment* b);
81 255604 : BeamSegment* beamlet() const { return m_beamlet; }
82 :
83 : virtual Beam* beam() const final;
84 533873 : int beams() const { return m_durationType.hooks(); }
85 : virtual double upPos() const = 0;
86 : virtual double downPos() const = 0;
87 :
88 : virtual double rightEdge() const = 0;
89 :
90 7037185 : bool isSmall() const { return m_isSmall; }
91 7161 : void setSmall(bool val) { m_isSmall = val; }
92 :
93 574154 : int staffMove() const { return m_staffMove; }
94 9389 : void setStaffMove(int val) { m_staffMove = val; }
95 87691 : int storedStaffMove() const { return m_storedStaffMove; }
96 2688414 : staff_idx_t vStaffIdx() const override { return staffIdx() + m_staffMove; }
97 : void checkStaffMoveValidity();
98 :
99 2213181 : const TDuration durationType() const
100 : {
101 2213181 : return m_crossMeasure == CrossMeasure::FIRST ? m_crossMeasureTDur : m_durationType;
102 : }
103 :
104 211946 : const TDuration actualDurationType() const { return m_durationType; }
105 : void setDurationType(DurationType t);
106 : void setDurationType(const Fraction& ticks);
107 : void setDurationType(TDuration v);
108 262 : void setDots(int n) { m_durationType.setDots(n); }
109 562888 : int dots() const
110 : {
111 562888 : return m_crossMeasure == CrossMeasure::FIRST
112 1125727 : ? m_crossMeasureTDur.dots()
113 1125727 : : (m_crossMeasure == CrossMeasure::SECOND ? 0 : m_durationType.dots());
114 : }
115 :
116 : int actualDots() const { return m_durationType.dots(); }
117 699 : Fraction durationTypeTicks() const
118 : {
119 699 : return m_crossMeasure == CrossMeasure::FIRST ? m_crossMeasureTDur.ticks() : m_durationType.ticks();
120 : }
121 :
122 : String durationUserName() const;
123 :
124 : void setTrack(track_idx_t val) override;
125 :
126 606451 : const std::vector<Lyrics*>& lyrics() const { return m_lyrics; }
127 460327 : std::vector<Lyrics*>& lyrics() { return m_lyrics; }
128 : Lyrics* lyrics(int verse) const;
129 : Lyrics* lyrics(int verse, PlacementV) const;
130 : int lastVerse(PlacementV) const;
131 : bool isMelismaEnd() const;
132 : void setMelismaEnd(bool v);
133 :
134 : virtual void add(EngravingItem*) override;
135 : virtual void remove(EngravingItem*) override;
136 : void removeDeleteBeam(bool beamed);
137 : void replaceBeam(Beam* newBeam);
138 :
139 1946054 : const ElementList& el() const { return m_el; }
140 :
141 : //! TODO Look like a hack, see using
142 4 : void addFermata(Fermata* f) { addEl(f); }
143 4 : void removeFermata(Fermata* f) { removeEl(f); }
144 : //! --------------------------------
145 :
146 : Slur* slur(const ChordRest* secondChordRest = nullptr) const;
147 :
148 70497 : CrossMeasure crossMeasure() const { return m_crossMeasure; }
149 1709 : void setCrossMeasure(CrossMeasure val) { m_crossMeasure = val; }
150 :
151 : // the following two functions should not be used, unless absolutely necessary;
152 : // the cross-measure duration is best managed through setDuration() and crossMeasureSetup()
153 1687 : TDuration crossMeasureDurationType() const { return m_crossMeasureTDur; }
154 1689 : void setCrossMeasureDurationType(TDuration v) { m_crossMeasureTDur = v; }
155 :
156 : void undoChangeProperty(Pid id, const PropertyValue& newValue, PropertyFlags ps = PropertyFlags::NOSTYLE) override;
157 : void localSpatiumChanged(double oldValue, double newValue) override;
158 : PropertyValue getProperty(Pid propertyId) const override;
159 : bool setProperty(Pid propertyId, const PropertyValue&) override;
160 : PropertyValue propertyDefault(Pid) const override;
161 : bool isGrace() const;
162 : bool isGraceBefore() const;
163 : bool isGraceAfter() const;
164 : Breath* hasBreathMark() const;
165 :
166 : Segment* nextSegmentAfterCR(SegmentType types) const;
167 :
168 : void setScore(Score* s) override;
169 : EngravingItem* nextArticulationOrLyric(EngravingItem* e);
170 : EngravingItem* prevArticulationOrLyric(EngravingItem* e);
171 : virtual EngravingItem* nextElement() override;
172 : virtual EngravingItem* prevElement() override;
173 : EngravingItem* lastElementBeforeSegment();
174 : virtual EngravingItem* nextSegmentElement() override;
175 : virtual EngravingItem* prevSegmentElement() override;
176 : virtual String accessibleExtraInfo() const override;
177 : virtual void computeUp();
178 :
179 654893 : bool isFullMeasureRest() const { return m_durationType == DurationType::V_MEASURE; }
180 : virtual void removeMarkings(bool keepTremolo = false);
181 :
182 : bool isBefore(const EngravingItem*) const override;
183 :
184 : virtual double intrinsicMag() const = 0;
185 :
186 355663 : TabDurationSymbol* tabDur() const { return m_tabDur; }
187 50658 : void setTabDur(TabDurationSymbol* s) { m_tabDur = s; }
188 :
189 : bool isBelowCrossBeam(const BeamBase* beamBase) const;
190 :
191 : bool hasFollowingJumpItem() const;
192 : bool hasPrecedingJumpItem() const;
193 :
194 : struct LayoutData : public DurationElement::LayoutData {
195 : ld_field<bool> up = { "[ChordRest] up", true }; // actual stem direction
196 : };
197 3970055 : DECLARE_LAYOUTDATA_METHODS(ChordRest)
198 :
199 : //! DEPRECATED ------
200 550 : void setUp(bool val) { mutldata()->up = val; }
201 2843474 : bool up() const { return ldata()->up; }
202 : //! -----------------
203 :
204 : protected:
205 :
206 162 : void addEl(EngravingItem* e) { m_el.push_back(e); }
207 16 : bool removeEl(EngravingItem* e) { return m_el.remove(e); }
208 133 : void clearEls() { m_el.clear(); }
209 :
210 : std::vector<Lyrics*> m_lyrics;
211 : TabDurationSymbol* m_tabDur = nullptr; // stores a duration symbol in tablature staves
212 :
213 : Beam* m_beam = nullptr;
214 : BeamSegment* m_beamlet = nullptr;
215 : BeamMode m_beamMode = BeamMode::INVALID;
216 : bool m_isSmall = false;
217 : bool m_melismaEnd = false;
218 :
219 : // CrossMeasure: combine 2 tied notes if across a bar line and can be combined in a single duration
220 : CrossMeasure m_crossMeasure = CrossMeasure::UNKNOWN; ///< 0: no cross-measure modification; 1: 1st note of a mod.; -1: 2nd note
221 : TDuration m_crossMeasureTDur; ///< the total Duration type of the combined notes
222 :
223 : private:
224 :
225 : void processSiblings(std::function<void(EngravingItem*)> func);
226 :
227 : ElementList m_el;
228 : TDuration m_durationType;
229 : int m_staffMove = 0; // -1, 0, +1, used for crossbeaming
230 : int m_storedStaffMove = 0; // used to remember and re-apply staff move if needed
231 : };
232 : }
|