Skip to content

Commit

Permalink
Merge pull request #24147 from ketgg/gsoc_dynamics_popup_part_2
Browse files Browse the repository at this point in the history
GSoC '24 - Dynamics Popup - Part 2
  • Loading branch information
cbjeukendrup authored Feb 6, 2025
2 parents 2f1accb + 4d9efc0 commit 76fef15
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 12 deletions.
1 change: 0 additions & 1 deletion src/engraving/dom/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,6 @@ void Score::cmdAddSpanner(Spanner* spanner, const PointF& pos, bool systemStaves

bool ctrlModifier = isSystemTextLine(spanner) && !systemStavesOnly;
undoAddElement(spanner, true /*addToLinkedStaves*/, ctrlModifier);
select(spanner, SelectType::SINGLE, 0);
}

//---------------------------------------------------------
Expand Down
147 changes: 146 additions & 1 deletion src/engraving/dom/dynamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

#include "log.h"

using namespace mu;
using namespace muse::draw;
using namespace mu::engraving;

namespace mu::engraving {
Expand Down Expand Up @@ -532,6 +532,39 @@ TranslatableString Dynamic::subtypeUserName() const
}
}

void Dynamic::editDrag(EditData& ed)
{
const bool hasLeftGrip = this->hasLeftGrip();
const bool hasRightGrip = this->hasRightGrip();

// Right grip (when two grips/when single grip)
if ((int(ed.curGrip) == 1 && hasLeftGrip && hasRightGrip) || (int(ed.curGrip) == 0 && !hasLeftGrip && hasRightGrip)) {
m_rightDragOffset += ed.evtDelta.x();
if (m_rightDragOffset < 0) {
m_rightDragOffset = 0;
}
return;
}

// Left grip (when two grips or single grip)
if (int(ed.curGrip) == 0 && hasLeftGrip) {
m_leftDragOffset += ed.evtDelta.x();
if (m_leftDragOffset > 0) {
m_leftDragOffset = 0;
}
return;
}

TextBase::editDrag(ed);
}

void Dynamic::endEditDrag(EditData& ed)
{
m_leftDragOffset = m_rightDragOffset = 0.0;

TextBase::endEditDrag(ed);
}

//---------------------------------------------------------
// reset
//---------------------------------------------------------
Expand Down Expand Up @@ -717,3 +750,115 @@ String Dynamic::screenReaderInfo() const
return String(u"%1: %2").arg(EngravingItem::accessibleInfo(), s);
}
}

//---------------------------------------------------------
// drawEditMode
//---------------------------------------------------------

void Dynamic::drawEditMode(Painter* p, EditData& ed, double currentViewScaling)
{
if (ed.editTextualProperties) {
TextBase::drawEditMode(p, ed, currentViewScaling);
} else {
EngravingItem::drawEditMode(p, ed, currentViewScaling);
}
}

//---------------------------------------------------------
// hasLeftHairpin
//---------------------------------------------------------

bool Dynamic::hasLeftGrip() const
{
if (segment()->tick().isZero()) {
return false; // Don't show the left grip for the leftmost dynamic with tick zero
}
return m_leftHairpin == nullptr;
}

//---------------------------------------------------------
// hasRightHairpin
//---------------------------------------------------------

bool Dynamic::hasRightGrip() const
{
return m_rightHairpin == nullptr;
}

//---------------------------------------------------------
// findAdjacentHairpins
//---------------------------------------------------------

void Dynamic::findAdjacentHairpins()
{
m_leftHairpin = nullptr;
m_rightHairpin = nullptr;

const Fraction tick = segment()->tick();
const int intTick = tick.ticks();

const auto& spanners = score()->spannerMap().findOverlapping(intTick - 1, intTick + 1);
for (auto i : spanners) {
Spanner* sp = i.value;
if (sp->track() == track() && sp->isHairpin()) {
Hairpin* hp = toHairpin(sp);
if (hp->tick() == tick) {
m_rightHairpin = hp;
} else if (hp->tick2() == tick) {
m_leftHairpin = hp;
}
}
}
}

//---------------------------------------------------------
// gripsCount
//---------------------------------------------------------

int Dynamic::gripsCount() const
{
if (empty()) {
return 0;
}

const bool hasLeftGrip = this->hasLeftGrip();
const bool hasRightGrip = this->hasRightGrip();

if (hasLeftGrip && hasRightGrip) {
return 2;
} else if (hasLeftGrip || hasRightGrip) {
return 1;
} else {
return 0;
}
}

//---------------------------------------------------------
// gripsPositions
//---------------------------------------------------------

std::vector<PointF> Dynamic::gripsPositions(const EditData&) const
{
const LayoutData* ldata = this->ldata();
const PointF pp(pagePos());
double md = score()->style().styleS(Sid::hairpinMinDistance).val() * spatium(); // Minimum distance between dynamic and grip

// Calculated by subtracting the y-value of the dynamic's pagePos from the y-value of hairpin's Grip::START position in HairpinSegment::gripsPositions
const double GRIP_VERTICAL_OFFSET = -11.408;

PointF leftOffset(-ldata->bbox().width() / 2 - md + m_leftDragOffset, GRIP_VERTICAL_OFFSET);
PointF rightOffset(ldata->bbox().width() / 2 + md + m_rightDragOffset, GRIP_VERTICAL_OFFSET);

const bool hasLeftGrip = this->hasLeftGrip();
const bool hasRightGrip = this->hasRightGrip();

if (hasLeftGrip && hasRightGrip) {
return { pp + leftOffset, pp + rightOffset };
} else if (hasLeftGrip) {
return { pp + leftOffset };
} else if (hasRightGrip) {
return { pp + rightOffset };
} else {
return {};
}
}
30 changes: 30 additions & 0 deletions src/engraving/dom/dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

#include "textbase.h"

namespace muse::draw {
class Painter;
}

namespace mu::engraving {
class Measure;
class Segment;
Expand Down Expand Up @@ -114,6 +118,26 @@ class Dynamic final : public TextBase

bool hasVoiceAssignmentProperties() const override { return true; }

int gripsCount() const override;
std::vector<PointF> gripsPositions(const EditData& = EditData()) const override;
void editDrag(EditData& editData) override;
void endEditDrag(EditData&) override;
void drawEditMode(muse::draw::Painter* painter, EditData& editData, double currentViewScaling) override;

Hairpin* leftHairpin() const { return m_leftHairpin; }
Hairpin* rightHairpin() const { return m_rightHairpin; }

bool hasLeftGrip() const;
bool hasRightGrip() const;

void resetLeftDragOffset() { m_leftDragOffset = 0.0; }
void resetRightDragOffset() { m_rightDragOffset = 0.0; }

double leftDragOffset() const { return m_leftDragOffset; }
double rightDragOffset() const { return m_rightDragOffset; }

void findAdjacentHairpins();

private:

M_PROPERTY(bool, avoidBarLines, setAvoidBarLines)
Expand All @@ -132,6 +156,12 @@ class Dynamic final : public TextBase
DynamicSpeed m_velChangeSpeed = DynamicSpeed::NORMAL;

static const std::vector<Dyn> DYN_LIST;

double m_leftDragOffset = 0.0;
double m_rightDragOffset = 0.0;

Hairpin* m_leftHairpin = nullptr;
Hairpin* m_rightHairpin = nullptr;
};
} // namespace mu::engraving

Expand Down
40 changes: 40 additions & 0 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "infrastructure/messagebox.h"

#include "accidental.h"
#include "anchors.h"
#include "articulation.h"
#include "barline.h"
#include "beam.h"
Expand Down Expand Up @@ -3964,6 +3965,45 @@ void Score::addHairpinToDynamic(Hairpin* hairpin, Dynamic* dynamic)
undoAddElement(hairpin);
}

Hairpin* Score::addHairpinToDynamicOnGripDrag(Dynamic* dynamic, bool isLeftGrip, const PointF& pos)
{
const track_idx_t track = dynamic->track();
staff_idx_t staffIndex = dynamic->staffIdx();
Segment* seg = nullptr;
constexpr double spacingFactor = 0.5;

// Ensure time tick segments are created
EditTimeTickAnchors::updateAnchors(dynamic, track);

// Find segment of type ChordRest or TimeTick near cursor postion
dragPosition(pos, &staffIndex, &seg, spacingFactor, /*allowTimeAnchor*/ true);

const bool hasValidTick = seg && (isLeftGrip
? seg->tick() < dynamic->tick()
: seg->tick() > dynamic->tick());
if (!hasValidTick) {
return nullptr;
}

Hairpin* hairpin = Factory::createHairpin(dummy()->segment());
hairpin->setHairpinType(isLeftGrip ? HairpinType::DECRESC_HAIRPIN : HairpinType::CRESC_HAIRPIN);

hairpin->setTrack(track);
hairpin->setTrack2(track);

if (isLeftGrip) {
hairpin->setTick(seg->tick());
hairpin->setTick2(dynamic->tick());
} else {
hairpin->setTick(dynamic->tick());
hairpin->setTick2(seg->tick());
}

undoAddElement(hairpin);

return hairpin;
}

//---------------------------------------------------------
// cmdCreateTuplet
// replace cr with tuplet
Expand Down
1 change: 1 addition & 0 deletions src/engraving/dom/editdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ DECLARE_OPERATORS_FOR_FLAGS(MouseButtons)
enum class Grip {
NO_GRIP = -1,
START = 0, END = 1, // arpeggio etc.
LEFT = START, RIGHT = END, // aliases for dynamic
MIDDLE = 2, APERTURE = 3, // Line
/*START, END , */
BEZIER1 = 2, SHOULDER = 3, BEZIER2 = 4, DRAG = 5, // Slur
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class Bracket;
class Chord;
class ChordRest;
class Clef;
class Dynamic;
class Element;
class EventsHolder;
class Excerpt;
Expand Down Expand Up @@ -932,6 +933,7 @@ class Score : public EngravingObject, public muse::Injectable
Hairpin* addHairpin(HairpinType type, ChordRest* cr1, ChordRest* cr2 = nullptr);
void addHairpin(Hairpin* hairpin, ChordRest* cr1, ChordRest* cr2 = nullptr);
void addHairpinToDynamic(Hairpin* hairpin, Dynamic* dynamic);
Hairpin* addHairpinToDynamicOnGripDrag(Dynamic* dynamic, bool isLeftGrip, const PointF& pos);

ChordRest* findCR(Fraction tick, track_idx_t track) const;
ChordRest* findChordRestEndingBeforeTickInStaff(const Fraction& tick, staff_idx_t staffIdx) const;
Expand Down
1 change: 1 addition & 0 deletions src/notation/inotationinteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class INotationInteraction
virtual void addLaissezVibToSelection() = 0;
virtual void addSlurToSelection() = 0;
virtual void addOttavaToSelection(OttavaType type) = 0;
virtual void addHairpinOnGripDrag(engraving::Dynamic* dynamic, bool isLeftGrip) = 0;
virtual void addHairpinsToSelection(HairpinType type) = 0;
virtual void putRestToSelection() = 0;
virtual void putRest(Duration duration) = 0;
Expand Down
Loading

0 comments on commit 76fef15

Please sign in to comment.