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 <set>
26 :
27 : #include "durationelement.h"
28 : #include "property.h"
29 : #include "../types/types.h"
30 :
31 : namespace mu::engraving {
32 : class Text;
33 : class Spanner;
34 :
35 : //------------------------------------------------------------------------
36 : // @@ Tuplet
37 : //! Example of 1/8 triplet:
38 : //! _baseLen = 1/8 (tuplet is measured in eighth notes)
39 : //! _ratio = 3/2 (3 eighth tuplet notes played in the space of 2 regular eighth notes)
40 : //!
41 : //! Entire tuplet has a duration of _baseLen * _ratio.denominator().
42 : //! A single tuplet note has duration of _baseLen * _ratio.denominator() / _ratio.numerator().
43 : //------------------------------------------------------------------------
44 :
45 : class Tuplet final : public DurationElement
46 : {
47 1708 : OBJECT_ALLOCATOR(engraving, Tuplet)
48 100 : DECLARE_CLASSOF(ElementType::TUPLET)
49 :
50 : public:
51 : Tuplet(DummyParentOr<Measure> parent);
52 : Tuplet(const Tuplet&);
53 : ~Tuplet();
54 :
55 : void setOwnershipParent(DummyParentOr<Measure> parent);
56 :
57 48 : Tuplet* clone() const override { return new Tuplet(*this); }
58 : void setTrack(track_idx_t val) override;
59 :
60 : void add(EngravingItem*) override;
61 : void remove(EngravingItem*) override;
62 :
63 34674 : Text* number() const { return m_number; }
64 1058 : void setNumber(Text* t) { m_number = t; }
65 : void resetNumberProperty();
66 : static void resetNumberProperty(Text* number);
67 :
68 : bool isEditable() const override;
69 : void startDragGrip(EditData&) override;
70 : void dragGrip(EditData&) override;
71 :
72 : void setSelected(bool f) override;
73 :
74 741 : Measure* measure() const override { return toMeasure(ownershipParent()); }
75 :
76 3991 : TupletNumberType numberType() const { return m_numberType; }
77 148 : TupletBracketType bracketType() const { return m_bracketType; }
78 1525 : void setNumberType(TupletNumberType val) { m_numberType = val; }
79 1267 : void setBracketType(TupletBracketType val) { m_bracketType = val; }
80 7019 : bool hasBracket() const { return m_hasBracket; }
81 2029 : void setHasBracket(bool b) { m_hasBracket = b; }
82 0 : Spatium bracketWidth() const { return m_bracketWidth; }
83 1054 : void setBracketWidth(Spatium s) { m_bracketWidth = s; }
84 :
85 203730 : const Fraction& ratio() const { return m_ratio; }
86 1014 : void setRatio(const Fraction& r) { m_ratio = r; }
87 :
88 3 : void setUserPoint1(PointF p) { m_userP1 = p; }
89 3 : void setUserPoint2(PointF p) { m_userP2 = p; }
90 :
91 47776 : const std::vector<DurationElement*>& elements() const { return m_currentElements; }
92 18 : void clear() { m_currentElements.clear(); }
93 4164 : bool contains(const DurationElement* el) const
94 : {
95 4164 : return std::find(m_currentElements.begin(), m_currentElements.end(), el) != m_currentElements.end();
96 : }
97 :
98 : void scanElements(std::function<void(EngravingItem*)> func) override;
99 :
100 : void reset() override;
101 :
102 2512 : TDuration baseLen() const { return m_baseLen; }
103 1103 : void setBaseLen(const TDuration& d) { m_baseLen = d; }
104 :
105 : void dump() const override;
106 :
107 1303 : void setDirection(DirectionV d) { m_direction = d; }
108 2726 : DirectionV direction() const { return m_direction; }
109 18462 : bool isUp() const { return m_isUp; }
110 2029 : void setIsUp(bool val) { m_isUp = val; }
111 1798 : bool isSmall() const { return m_isSmall; }
112 3414 : void setIsSmall(bool val) { m_isSmall = val; }
113 4173 : Fraction tick() const override { return m_tick; }
114 : Fraction rtick() const override;
115 1114 : void setTick(const Fraction& v) { m_tick = v; }
116 : Fraction elementsDuration();
117 : void sortElements();
118 : bool cross() const;
119 : staff_idx_t vStaffIdx() const override;
120 :
121 0 : const PointF& p1() const { return m_p1; }
122 51824 : PointF& p1() { return m_p1; }
123 2029 : void setP1(const PointF& p) { m_p1 = p; }
124 0 : const PointF& p2() const { return m_p2; }
125 38315 : PointF& p2() { return m_p2; }
126 2029 : void setP2(const PointF& p) { m_p2 = p; }
127 :
128 2029 : const PointF& userP1() const { return m_userP1; }
129 2029 : const PointF& userP2() const { return m_userP2; }
130 :
131 : void setVisible(bool f) override;
132 : void setColor(const Color& col) override;
133 :
134 : EngravingObject* propertyDelegate(Pid id) const override;
135 : PropertyValue getProperty(Pid propertyId) const override;
136 : bool setProperty(Pid propertyId, const PropertyValue& v) override;
137 : PropertyValue propertyDefault(Pid id) const override;
138 :
139 0 : bool needStartEditingAfterSelecting() const override { return true; }
140 : int gripsCount() const override;
141 0 : Grip initialEditModeGrip() const override { return Grip::MIDDLE; }
142 0 : Grip defaultGrip() const override { return Grip::MIDDLE; }
143 : std::vector<PointF> gripsPositions(const EditData&) const override;
144 :
145 : void sanitizeTuplet();
146 : void addMissingElements();
147 :
148 : bool calcHasBracket(const DurationElement* cr1, const DurationElement* cr2) const;
149 :
150 : static int computeTupletDenominator(int numerator, Fraction totalDuration);
151 :
152 : PointF bracketL[4];
153 : PointF bracketR[3];
154 :
155 : EngravingItem* nextElement() override;
156 : EngravingItem* prevElement() override;
157 :
158 : private:
159 :
160 : friend class DurationElement;
161 :
162 : void addDurationElement(DurationElement* de);
163 : void removeDurationElement(DurationElement* de);
164 :
165 : Fraction addMissingElement(const Fraction& startTick, const Fraction& endTick);
166 :
167 : // All DurationElements where `tuplet()` returns this tuplet
168 : std::set<DurationElement*> m_allElements;
169 :
170 : // Those DurationElements that are currently really part of this tuplet
171 : std::vector<DurationElement*> m_currentElements;
172 :
173 : bool m_beingDestructed = false;
174 :
175 : DirectionV m_direction = DirectionV::AUTO;
176 : TupletNumberType m_numberType = TupletNumberType::SHOW_NUMBER;
177 : TupletBracketType m_bracketType = TupletBracketType::AUTO_BRACKET;
178 : Spatium m_bracketWidth;
179 :
180 : bool m_hasBracket = false;
181 : Fraction m_ratio;
182 : TDuration m_baseLen; // 1/8 for a triplet of 1/8
183 :
184 : bool m_isUp = true;
185 : bool m_isSmall = true;
186 :
187 : Fraction m_tick;
188 :
189 : PointF m_p1, m_p2;
190 : PointF m_userP1, m_userP2; // user offset
191 :
192 : Text* m_number = nullptr;
193 : };
194 : }
|