-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5763 from dmitrio95/anchors_rebasing
Rebase segment-anchored lines on dragging
- Loading branch information
Showing
30 changed files
with
1,001 additions
and
204 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
//============================================================================= | ||
// MuseScore | ||
// Music Composition & Notation | ||
// | ||
// Copyright (C) 2020 MuseScore BVBA | ||
// | ||
// This program is free software; you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License version 2 | ||
// as published by the Free Software Foundation and appearing in | ||
// the file LICENCE.GPL | ||
//============================================================================= | ||
|
||
#include "dynamichairpingroup.h" | ||
#include "dynamic.h" | ||
#include "hairpin.h" | ||
#include "score.h" | ||
#include "segment.h" | ||
|
||
namespace Ms { | ||
|
||
static std::pair<Hairpin*, Hairpin*> findAdjacentHairpins(Dynamic* d) | ||
{ | ||
Score* score = d->score(); | ||
const Segment* dSeg = d->segment(); | ||
Hairpin* leftHairpin = nullptr; | ||
Hairpin* rightHairpin = nullptr; | ||
|
||
const Fraction tick = dSeg->tick(); | ||
const int intTick = tick.ticks(); | ||
|
||
const auto& nearSpanners = score->spannerMap().findOverlapping(intTick - 1, intTick + 1); | ||
for (auto i : nearSpanners) { | ||
Spanner* s = i.value; | ||
if (s->track() == d->track() && s->isHairpin()) { | ||
Hairpin* h = toHairpin(s); | ||
if (h->tick() == tick) | ||
rightHairpin = h; | ||
else if (h->tick2() == tick) | ||
leftHairpin = h; | ||
} | ||
} | ||
|
||
return { leftHairpin, rightHairpin }; | ||
} | ||
|
||
std::unique_ptr<ElementGroup> HairpinWithDynamicsDragGroup::detectFor(HairpinSegment* hs, std::function<bool(const Element*)> isDragged) | ||
{ | ||
if (!hs->isSingleType()) | ||
return nullptr; | ||
|
||
Hairpin* hairpin = hs->hairpin(); | ||
|
||
Segment* startSegment = hairpin->startSegment(); | ||
Segment* endSegment = hairpin->endSegment(); | ||
const int track = hs->track(); | ||
|
||
Dynamic* startDynamic = toDynamic(startSegment->findAnnotation(ElementType::DYNAMIC, track, track)); | ||
Dynamic* endDynamic = toDynamic(endSegment->findAnnotation(ElementType::DYNAMIC, track, track)); | ||
|
||
// Include only dragged dynamics to this group | ||
if (!isDragged(startDynamic)) | ||
startDynamic = nullptr; | ||
if (!isDragged(endDynamic)) | ||
endDynamic = nullptr; | ||
|
||
if (startDynamic || endDynamic) | ||
return std::unique_ptr<ElementGroup>(new HairpinWithDynamicsDragGroup(startDynamic, hs, endDynamic)); | ||
return nullptr; | ||
} | ||
|
||
std::unique_ptr<ElementGroup> HairpinWithDynamicsDragGroup::detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged) | ||
{ | ||
Hairpin* leftHairpin = nullptr; | ||
Hairpin* rightHairpin = nullptr; | ||
|
||
std::tie(leftHairpin, rightHairpin) = findAdjacentHairpins(d); | ||
|
||
// Dynamic will be governed bt HairpinWithDynamicsDragGroup if any of adjacent | ||
// hairpins is dragged, disable separate drag logic for dynamic in this case. | ||
if (isDragged(leftHairpin)) | ||
return std::unique_ptr<ElementGroup>(new DisabledElementGroup()); | ||
if (isDragged(rightHairpin)) | ||
return std::unique_ptr<ElementGroup>(new DisabledElementGroup()); | ||
|
||
return nullptr; | ||
} | ||
|
||
void HairpinWithDynamicsDragGroup::startDrag(EditData& ed) | ||
{ | ||
if (startDynamic) | ||
startDynamic->startDrag(ed); | ||
static_cast<Element*>(hairpinSegment)->startDrag(ed); | ||
if (endDynamic) | ||
endDynamic->startDrag(ed); | ||
} | ||
|
||
QRectF HairpinWithDynamicsDragGroup::drag(EditData& ed) | ||
{ | ||
QRectF r; | ||
|
||
if (startDynamic) | ||
r |= static_cast<Element*>(startDynamic)->drag(ed); | ||
r |= hairpinSegment->drag(ed); | ||
if (endDynamic) | ||
r |= static_cast<Element*>(endDynamic)->drag(ed); | ||
|
||
Hairpin* h = hairpinSegment->hairpin(); | ||
|
||
const Fraction startTick = startDynamic ? startDynamic->segment()->tick() : h->tick(); | ||
const Fraction endTick = endDynamic ? endDynamic->segment()->tick() : h->tick2(); | ||
|
||
if (endTick > startTick) { | ||
if (h->tick() != startTick) | ||
h->undoChangeProperty(Pid::SPANNER_TICK, startTick); | ||
if (h->tick2() != endTick) | ||
h->undoChangeProperty(Pid::SPANNER_TICKS, endTick - startTick); | ||
} | ||
|
||
return r; | ||
} | ||
|
||
void HairpinWithDynamicsDragGroup::endDrag(EditData& ed) | ||
{ | ||
if (startDynamic) { | ||
startDynamic->endDrag(ed); | ||
startDynamic->triggerLayout(); | ||
} | ||
|
||
hairpinSegment->endDrag(ed); | ||
hairpinSegment->triggerLayout(); | ||
|
||
if (endDynamic) { | ||
endDynamic->endDrag(ed); | ||
endDynamic->triggerLayout(); | ||
} | ||
} | ||
|
||
std::unique_ptr<ElementGroup> DynamicNearHairpinsDragGroup::detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged) | ||
{ | ||
Hairpin* leftHairpin = nullptr; | ||
Hairpin* rightHairpin = nullptr; | ||
|
||
std::tie(leftHairpin, rightHairpin) = findAdjacentHairpins(d); | ||
|
||
// Drag hairpins according to this rule only if they are not being dragged themselves | ||
if (isDragged(leftHairpin)) | ||
leftHairpin = nullptr; | ||
if (isDragged(rightHairpin)) | ||
rightHairpin = nullptr; | ||
|
||
if (leftHairpin || rightHairpin) | ||
return std::unique_ptr<ElementGroup>(new DynamicNearHairpinsDragGroup(leftHairpin, d, rightHairpin)); | ||
return nullptr; | ||
} | ||
|
||
void DynamicNearHairpinsDragGroup::startDrag(EditData& ed) | ||
{ | ||
dynamic->startDrag(ed); | ||
} | ||
|
||
QRectF DynamicNearHairpinsDragGroup::drag(EditData& ed) | ||
{ | ||
QRectF r(static_cast<Element*>(dynamic)->drag(ed)); | ||
|
||
const Fraction tick = dynamic->segment()->tick(); | ||
|
||
if (leftHairpin && leftHairpin->tick2() != tick && tick > leftHairpin->tick()) | ||
leftHairpin->undoChangeProperty(Pid::SPANNER_TICKS, tick - leftHairpin->tick()); | ||
|
||
if (rightHairpin && rightHairpin->tick() != tick) { | ||
const Fraction tick2 = rightHairpin->tick2(); | ||
if (tick < tick2) { | ||
rightHairpin->undoChangeProperty(Pid::SPANNER_TICK, tick); | ||
rightHairpin->undoChangeProperty(Pid::SPANNER_TICKS, tick2 - tick); | ||
} | ||
} | ||
|
||
if (leftHairpin || rightHairpin) | ||
dynamic->triggerLayout(); | ||
|
||
return r; | ||
} | ||
|
||
void DynamicNearHairpinsDragGroup::endDrag(EditData& ed) | ||
{ | ||
dynamic->endDrag(ed); | ||
dynamic->triggerLayout(); | ||
} | ||
|
||
} // namespace Ms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
//============================================================================= | ||
// MuseScore | ||
// Music Composition & Notation | ||
// | ||
// Copyright (C) 2020 MuseScore BVBA | ||
// | ||
// This program is free software; you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License version 2 | ||
// as published by the Free Software Foundation and appearing in | ||
// the file LICENCE.GPL | ||
//============================================================================= | ||
|
||
#ifndef __DYNAMICHAIPRINGROUP_H__ | ||
#define __DYNAMICHAIRPINGROUP_H__ | ||
|
||
#include "elementgroup.h" | ||
|
||
namespace Ms { | ||
|
||
class Dynamic; | ||
class Hairpin; | ||
class HairpinSegment; | ||
|
||
//------------------------------------------------------------------- | ||
// HairpinWithDynamicsDragGroup | ||
/// Sequence of Dynamics and Hairpins | ||
//------------------------------------------------------------------- | ||
|
||
class HairpinWithDynamicsDragGroup : public ElementGroup { | ||
Dynamic* startDynamic; | ||
HairpinSegment* hairpinSegment; | ||
Dynamic* endDynamic; | ||
|
||
public: | ||
HairpinWithDynamicsDragGroup(Dynamic* start, HairpinSegment* hs, Dynamic* end) | ||
: startDynamic(start), hairpinSegment(hs), endDynamic(end) {} | ||
|
||
void startDrag(EditData&) override; | ||
QRectF drag(EditData&) override; | ||
void endDrag(EditData&) override; | ||
|
||
static std::unique_ptr<ElementGroup> detectFor(HairpinSegment* hs, std::function<bool(const Element*)> isDragged); | ||
static std::unique_ptr<ElementGroup> detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged); | ||
}; | ||
|
||
//------------------------------------------------------------------- | ||
// DynamicNearHairpinsDragGroup | ||
//------------------------------------------------------------------- | ||
|
||
class DynamicNearHairpinsDragGroup : public ElementGroup { | ||
Hairpin* leftHairpin; | ||
Dynamic* dynamic; | ||
Hairpin* rightHairpin; | ||
|
||
public: | ||
DynamicNearHairpinsDragGroup(Hairpin* left, Dynamic* d, Hairpin* right) | ||
: leftHairpin(left), dynamic(d), rightHairpin(right) {} | ||
|
||
void startDrag(EditData&) override; | ||
QRectF drag(EditData&) override; | ||
void endDrag(EditData&) override; | ||
|
||
static std::unique_ptr<ElementGroup> detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged); | ||
}; | ||
|
||
} // namespace Ms | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.