LCOV - code coverage report
Current view: top level - src/engraving/dom - guitarbend.h Coverage Total Hit
Test: filtered_coverage.info Lines: 66.2 % 71 47
Test Date: 2026-11-05 04:07:02

            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              : }
        

Generated by: LCOV version 2.0-1