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 "textbase.h"
26 :
27 : namespace muse::draw {
28 : class Painter;
29 : }
30 :
31 : namespace mu::engraving {
32 : class Transaction;
33 : class Measure;
34 : class Segment;
35 :
36 : struct Dyn {
37 : DynamicType type = DynamicType::OTHER;
38 : int velocity = -1; // associated midi velocity (0-127, -1 = none)
39 : int changeInVelocity = 0;
40 : bool accent = 0; // if true add velocity to current chord velocity
41 : const char* text = nullptr; // utf8 text of dynamic
42 : };
43 :
44 : //-----------------------------------------------------------------------------
45 : // @@ Dynamic
46 : /// dynamics marker; determines midi velocity
47 : //
48 : // @P range enum (Dynamic.STAFF, .PART, .SYSTEM)
49 : //-----------------------------------------------------------------------------
50 :
51 : class Dynamic final : public TextBase
52 : {
53 1701 : OBJECT_ALLOCATOR(engraving, Dynamic)
54 1866 : DECLARE_CLASSOF(ElementType::DYNAMIC)
55 :
56 : public:
57 : struct ChangeSpeedItem {
58 : DynamicSpeed speed = DynamicSpeed::NORMAL;
59 : const char* name = nullptr;
60 : };
61 :
62 : Dynamic(DummyParentOr<Segment> parent);
63 : Dynamic(const Dynamic&);
64 22 : Dynamic* clone() const override { return new Dynamic(*this); }
65 2948 : Segment* segment() const { return (Segment*)ownershipParent(); }
66 : Measure* measure() const { return (Measure*)ownershipParent()->ownershipParent(); }
67 :
68 902 : void setDynamicType(DynamicType val) { m_dynamicType = val; }
69 : void setDynamicType(const String&);
70 :
71 6580 : DynamicType dynamicType() const { return m_dynamicType; }
72 0 : int subtype() const override { return static_cast<int>(m_dynamicType); }
73 : TranslatableString subtypeUserName() const override;
74 :
75 : void reset() override;
76 :
77 295 : void setVelocity(int v) { m_velocity = v; }
78 : int velocity() const;
79 :
80 : int changeInVelocity() const;
81 : void setChangeInVelocity(int val);
82 : Fraction velocityChangeLength(BeatsPerSecond tempo) const;
83 : bool isVelocityChangeAvailable() const;
84 :
85 32 : DynamicSpeed velChangeSpeed() const { return m_velChangeSpeed; }
86 0 : void setVelChangeSpeed(DynamicSpeed val) { m_velChangeSpeed = val; }
87 :
88 : PropertyValue getProperty(Pid propertyId) const override;
89 : bool setProperty(Pid propertyId, const PropertyValue&) override;
90 : PropertyValue propertyDefault(Pid id) const override;
91 : Sid getPropertyStyle(Pid) const override;
92 :
93 : std::unique_ptr<ElementGroup> getDragGroup(std::function<bool(const EngravingItem*)> isDragged) override;
94 :
95 : String accessibleInfo() const override;
96 : String screenReaderInfo() const override;
97 :
98 : static String dynamicText(DynamicType t);
99 647 : bool hasCustomText() const { return dynamicText(m_dynamicType) != xmlText(); }
100 :
101 : Expression* snappedExpression() const;
102 : HairpinSegment* findSnapBeforeHairpinAcrossSystemBreak() const;
103 :
104 852 : bool playDynamic() const { return m_playDynamic; }
105 0 : void setPlayDynamic(bool v) { m_playDynamic = v; }
106 :
107 : bool acceptDrop(EditData& ed) const override;
108 : EngravingItem* drop(Transaction& tx, EditData& ed) override;
109 :
110 : static int dynamicVelocity(DynamicType t);
111 1 : static const std::vector<Dyn>& dynamicList() { return DYN_LIST; }
112 :
113 1453 : bool hasVoiceAssignmentProperties() const override { return true; }
114 :
115 : void startEdit(EditData&) override;
116 : void endEdit(EditData&) override;
117 : int gripsCount() const override;
118 : std::vector<PointF> gripsPositions(const EditData& = EditData()) const override;
119 : void dragGrip(EditData& editData) override;
120 : void endDragGrip(EditData&) override;
121 :
122 : bool isEditAllowed(EditData&) const override;
123 :
124 1285 : bool positionRelativeToNoteheadRest() const override { return true; }
125 6498 : bool sizeIsSpatiumDependent() const override { return true; }
126 :
127 0 : Hairpin* leftHairpin() const { return m_leftHairpin; }
128 0 : Hairpin* rightHairpin() const { return m_rightHairpin; }
129 :
130 : bool hasLeftGrip() const;
131 : bool hasRightGrip() const;
132 :
133 : void resetLeftDragOffset() { m_leftDragOffset = 0.0; }
134 0 : void resetRightDragOffset() { m_rightDragOffset = 0.0; }
135 :
136 : double leftDragOffset() const { return m_leftDragOffset; }
137 : double rightDragOffset() const { return m_rightDragOffset; }
138 :
139 : void findAdjacentHairpins();
140 :
141 : Shape symShapeWithCutouts(SymId id) const override;
142 :
143 : static Dyn dynInfo(DynamicType type);
144 :
145 : private:
146 :
147 2083 : M_PROPERTY(bool, avoidBarLines, setAvoidBarLines)
148 4793 : M_PROPERTY(bool, centerOnNotehead, setCenterOnNotehead)
149 :
150 : std::pair<DynamicType, String> parseDynamicText(const String&) const;
151 : DynamicType m_dynamicType = DynamicType::OTHER;
152 : bool m_playDynamic = true;
153 :
154 : mutable PointF m_dragOffset;
155 : int m_velocity = -1; // associated midi velocity 0-127
156 :
157 : int m_changeInVelocity = 128;
158 : DynamicSpeed m_velChangeSpeed = DynamicSpeed::NORMAL;
159 :
160 : static const std::vector<Dyn> DYN_LIST;
161 :
162 : double m_leftDragOffset = 0.0;
163 : double m_rightDragOffset = 0.0;
164 :
165 : Hairpin* m_leftHairpin = nullptr;
166 : Hairpin* m_rightHairpin = nullptr;
167 : };
168 : }
|