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 "spanner.h"
26 :
27 : #include "draw/types/painterpath.h"
28 :
29 : namespace mu::engraving {
30 : //---------------------------------------------------------
31 : // SlurPos
32 : //---------------------------------------------------------
33 :
34 : struct SlurTiePos {
35 : PointF p1; // start point of slur in system coordinates
36 : System* system1 = nullptr; // start system of slur
37 : PointF p2; // end point of slur in system coordinates
38 : System* system2 = nullptr; // end system of slur
39 : };
40 :
41 : struct SlurOffsets {
42 : PointF o[4];
43 : };
44 :
45 : //---------------------------------------------------------
46 : // UP
47 : //---------------------------------------------------------
48 :
49 : struct UP {
50 : PointF p; // layout position relative to pos()
51 : PointF off; // user offset in point units
52 :
53 33940 : PointF pos() const { return p + off; }
54 : bool operator!=(const UP& up) const { return p != up.p || off != up.off; }
55 : };
56 :
57 : //---------------------------------------------------------
58 : // CubicBezier
59 : // Helper class to optimize cubic Bezier curve points
60 : // calculation.
61 : //---------------------------------------------------------
62 :
63 : class CubicBezier
64 : {
65 : PointF p1;
66 : PointF p2;
67 : PointF p3;
68 : PointF p4;
69 :
70 : public:
71 8802 : CubicBezier(PointF _p1, PointF _p2, PointF _p3, PointF _p4)
72 8802 : : p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
73 :
74 275054 : PointF pointAtPercent(double t) const
75 : {
76 275054 : assert(t >= 0.0 && t <= 1.0);
77 275054 : const double r = 1.0 - t;
78 275054 : const PointF B123 = r * (r * p1 + t * p2) + t * (r * p2 + t * p3);
79 275054 : const PointF B234 = r * (r * p2 + t * p3) + t * (r * p3 + t * p4);
80 550108 : return r * B123 + t * B234;
81 : }
82 : };
83 :
84 : class SlurTie;
85 :
86 : //---------------------------------------------------------
87 : // SlurTieSegment
88 : //---------------------------------------------------------
89 :
90 : class SlurTieSegment : public SpannerSegment
91 : {
92 0 : OBJECT_ALLOCATOR(engraving, SlurTieSegment)
93 :
94 : public:
95 :
96 : virtual void spatiumChanged(double, double) override;
97 215142 : SlurTie* slurTie() const { return (SlurTie*)spanner(); }
98 :
99 : bool isEditAllowed(EditData&) const override;
100 : bool edit(EditData&) override;
101 :
102 : void startDragGrip(EditData& ed) override;
103 : void endDragGrip(EditData& ed) override;
104 :
105 : PropertyValue getProperty(Pid propertyId) const override;
106 : bool setProperty(Pid propertyId, const PropertyValue&) override;
107 : PropertyValue propertyDefault(Pid id) const override;
108 : virtual EngravingObject* propertyDelegate(Pid) const override;
109 : virtual void reset() override;
110 : void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
111 : void move(const PointF& s) override;
112 0 : bool isEditable() const override { return true; }
113 :
114 : int subtype() const override;
115 : TranslatableString subtypeUserName() const override;
116 :
117 0 : void setSlurOffset(Grip i, const PointF& val) { m_ups[int(i)].off = val; }
118 3984 : const UP& ups(Grip i) const { return m_ups[int(i)]; }
119 173876 : UP& ups(Grip i) { return m_ups[int(i)]; }
120 :
121 0 : bool needStartEditingAfterSelecting() const override { return true; }
122 0 : int gripsCount() const override { return int(Grip::GRIPS); }
123 0 : Grip initialEditModeGrip() const override { return Grip::END; }
124 0 : Grip defaultGrip() const override { return Grip::DRAG; }
125 : std::vector<PointF> gripsPositions(const EditData& = EditData()) const override;
126 :
127 : virtual bool isUserModified() const override;
128 :
129 : virtual double endWidth() const = 0;
130 : virtual double midWidth() const = 0;
131 : virtual double dottedWidth() const = 0;
132 :
133 : struct LayoutData : public SpannerSegment::LayoutData
134 : {
135 : ld_field<muse::draw::PainterPath> path = "path";
136 : ld_field<double> midThickness = "midThickness";
137 : };
138 23395 : DECLARE_LAYOUTDATA_METHODS(SlurTieSegment)
139 :
140 : protected:
141 : SlurTieSegment(const ElementType& type, SlurTie* sp);
142 : SlurTieSegment(const SlurTieSegment&);
143 :
144 : virtual void changeAnchor(EditData&, EngravingItem*) = 0;
145 : std::vector<LineF> gripAnchorLines(Grip grip) const override;
146 :
147 : struct UP m_ups[int(Grip::GRIPS)];
148 : };
149 :
150 : //-------------------------------------------------------------------
151 : // @@ SlurTie
152 : // @P lineType int (0 - solid, 1 - dotted, 2 - dashed, 3 - wide dashed)
153 : // @P slurDirection enum (Direction.AUTO, Direction.DOWN, Direction.UP)
154 : // @P maskSlurTie enum (AutoOnOff.AUTO, AutoOnOff.ON, AutoOnOff.OFF)
155 : //-------------------------------------------------------------------
156 :
157 : class SlurTie : public Spanner
158 : {
159 0 : OBJECT_ALLOCATOR(engraving, SlurTie)
160 :
161 : public:
162 : SlurTie(const ElementType& type, EngravingObject* parent);
163 : SlurTie(const SlurTie&);
164 : ~SlurTie();
165 :
166 136372 : bool up() const { return m_up; }
167 6977 : void setUp(bool val) { m_up = val; }
168 :
169 : virtual void reset() override;
170 :
171 7890 : DirectionV slurDirection() const { return m_slurDirection; }
172 117 : void setSlurDirection(DirectionV d) { m_slurDirection = d; }
173 : void undoSetSlurDirection(DirectionV d);
174 :
175 0 : virtual bool contains(const PointF&) const { return false; } // not selectable
176 :
177 212851 : SlurStyleType styleType() const { return m_styleType; }
178 203 : void setStyleType(SlurStyleType type) { m_styleType = type; }
179 :
180 0 : int subtype() const override { return static_cast<int>(m_styleType) + 1; }
181 : TranslatableString subtypeUserName() const override;
182 :
183 4298 : AutoOnOff maskSlurTie() const { return m_maskSlurTie; }
184 0 : void setMaskSlurTie(AutoOnOff val) { m_maskSlurTie = val; }
185 :
186 : virtual SlurTieSegment* newSlurTieSegment() = 0;
187 :
188 : PropertyValue getProperty(Pid propertyId) const override;
189 : bool setProperty(Pid propertyId, const PropertyValue&) override;
190 : PropertyValue propertyDefault(Pid id) const override;
191 :
192 : void fixupSegments(unsigned nsegs);
193 :
194 : virtual double scalingFactor() const = 0;
195 :
196 : protected:
197 :
198 : bool m_up = true; // actual direction
199 :
200 : DirectionV m_slurDirection = DirectionV::AUTO;
201 :
202 : private:
203 :
204 : SlurStyleType m_styleType = SlurStyleType::Undefined;
205 : AutoOnOff m_maskSlurTie = AutoOnOff::AUTO;
206 : };
207 : }
|