Skip to content

Commit bb5bada

Browse files
committed
Implement dropping on arbitrary ticks, with visualisation
1 parent a5b8c28 commit bb5bada

File tree

4 files changed

+93
-16
lines changed

4 files changed

+93
-16
lines changed

src/engraving/dom/anchors.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,23 @@
2727
#include "score.h"
2828

2929
namespace mu::engraving {
30+
class Factory;
31+
3032
class EditTimeTickAnchors
3133
{
3234
public:
3335
static void updateAnchors(const EngravingItem* item, track_idx_t track);
36+
static void updateAnchors(Measure* measure, staff_idx_t staffIdx);
3437
static TimeTickAnchor* createTimeTickAnchor(Measure* measure, Fraction relTick, staff_idx_t staffIdx);
3538
static void updateLayout(Measure* measure);
36-
37-
private:
38-
static void updateAnchors(Measure* measure, staff_idx_t staffIdx);
3939
};
4040

4141
class TimeTickAnchor : public EngravingItem
4242
{
43-
public:
4443
TimeTickAnchor(Segment* parent);
44+
friend class Factory;
4545

46+
public:
4647
Segment* segment() const { return toSegment(parentItem()); }
4748

4849
TimeTickAnchor* clone() const override { return new TimeTickAnchor(*this); }

src/engraving/dom/cmd.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,11 +1431,13 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
14311431

14321432
bool Score::makeGap1(const Fraction& baseTick, staff_idx_t staffIdx, const Fraction& len, int voiceOffset[VOICES])
14331433
{
1434-
Segment* seg = tick2segment(baseTick, true, SegmentType::ChordRest);
1435-
if (!seg) {
1436-
LOGD("no segment to paste at tick %d", baseTick.ticks());
1434+
Measure* m = tick2measure(baseTick);
1435+
if (!m) {
1436+
LOGD() << "No measure to paste at tick " << baseTick.toString();
14371437
return false;
14381438
}
1439+
1440+
Segment* seg = m->undoGetSegment(SegmentType::ChordRest, baseTick);
14391441
track_idx_t strack = staffIdx * VOICES;
14401442
for (track_idx_t track = strack; track < strack + VOICES; track++) {
14411443
if (voiceOffset[track - strack] == -1) {

src/engraving/rw/read410/read410.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ bool Read410::readScore410(Score* score, XmlReader& e, ReadContext& ctx)
305305

306306
bool Read410::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fraction scale)
307307
{
308-
assert(dst->isChordRestType());
308+
assert(dst->isType(Segment::CHORD_REST_OR_TIME_TICK_TYPE));
309309

310310
Score* score = dst->score();
311311
ReadContext ctx(score);

src/notation/internal/notationinteraction.cpp

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,85 @@ bool NotationInteraction::isDropSingleAccepted(const PointF& pos, Qt::KeyboardMo
15071507
return false;
15081508
}
15091509

1510+
static void dropRangePosition(Score* score, const PointF& pos, Fraction tickLength, staff_idx_t* staffIdx, Segment** segment)
1511+
{
1512+
IF_ASSERT_FAILED(score && staffIdx && segment) {
1513+
return;
1514+
}
1515+
1516+
static constexpr double spacingFactor = 0.5;
1517+
static constexpr bool useTimeAnchors = true;
1518+
1519+
// First, get an approximate location
1520+
score->dragPosition(pos, staffIdx, segment, spacingFactor, useTimeAnchors);
1521+
if (*staffIdx == muse::nidx || !*segment) {
1522+
return;
1523+
}
1524+
1525+
// Determine the measures range
1526+
Fraction startTick = (*segment)->tick();
1527+
Fraction endTick = startTick + tickLength;
1528+
1529+
Measure* startMeasure = (*segment)->measure();
1530+
if (!startMeasure) {
1531+
return;
1532+
}
1533+
1534+
Measure* endMeasure = score->tick2measure(endTick);
1535+
if (!endMeasure) {
1536+
endMeasure = score->lastMeasure();
1537+
1538+
if (!endMeasure) {
1539+
return;
1540+
}
1541+
}
1542+
1543+
IF_ASSERT_FAILED(startMeasure == endMeasure || startMeasure->isBefore(endMeasure)) {
1544+
return;
1545+
}
1546+
1547+
// Add time tick anchors throughout these measures
1548+
for (MeasureBase* mb = startMeasure; mb && mb->tick() <= endMeasure->tick(); mb = mb->next()) {
1549+
if (!mb->isMeasure()) {
1550+
continue;
1551+
}
1552+
EditTimeTickAnchors::updateAnchors(toMeasure(mb), *staffIdx);
1553+
}
1554+
1555+
// Get precise location using the newly created time tick anchors
1556+
score->dragPosition(pos, staffIdx, segment, spacingFactor, useTimeAnchors);
1557+
if (*staffIdx == muse::nidx || !*segment) {
1558+
return;
1559+
}
1560+
1561+
startTick = (*segment)->tick();
1562+
endTick = startTick + tickLength;
1563+
1564+
score->setShowAnchors(ShowAnchors(0, *staffIdx, startTick, endTick,
1565+
startMeasure->tick(), endMeasure->endTick()));
1566+
1567+
// Invalidate BSP tree of affected pages
1568+
System* lastSeenSystem = nullptr;
1569+
Page* lastSeenPage = nullptr;
1570+
for (MeasureBase* mb = startMeasure; mb && mb->tick() <= endMeasure->tick(); mb = mb->next()) {
1571+
System* s = mb->system();
1572+
if (!s || s == lastSeenSystem) {
1573+
continue;
1574+
}
1575+
1576+
lastSeenSystem = s;
1577+
1578+
Page* p = s->page();
1579+
if (!p || p == lastSeenPage) {
1580+
continue;
1581+
}
1582+
1583+
lastSeenPage = p;
1584+
1585+
p->invalidateBspTree();
1586+
}
1587+
}
1588+
15101589
bool NotationInteraction::isDropRangeAccepted(const PointF& pos)
15111590
{
15121591
IF_ASSERT_FAILED(m_dropData.rangeDropData.has_value()) {
@@ -1517,11 +1596,8 @@ bool NotationInteraction::isDropRangeAccepted(const PointF& pos)
15171596

15181597
staff_idx_t staffIdx = muse::nidx;
15191598
Segment* segment = nullptr;
1520-
static constexpr double spacingFactor = 0.5;
1521-
static constexpr bool useTimeAnchors = true;
1522-
1523-
score()->dragPosition(pos, &staffIdx, &segment, spacingFactor, useTimeAnchors);
15241599

1600+
dropRangePosition(score(), pos, rdd.tickLength, &staffIdx, &segment);
15251601
if (staffIdx == muse::nidx || !segment) {
15261602
return false;
15271603
}
@@ -1822,11 +1898,8 @@ bool NotationInteraction::dropRange(const QByteArray& data, const PointF& pos, b
18221898

18231899
staff_idx_t staffIdx = muse::nidx;
18241900
Segment* segment = nullptr;
1825-
static constexpr double spacingFactor = 0.5;
1826-
static constexpr bool useTimeAnchors = true;
1827-
1828-
score()->dragPosition(pos, &staffIdx, &segment, spacingFactor, useTimeAnchors);
18291901

1902+
dropRangePosition(score(), pos, rdd.tickLength, &staffIdx, &segment);
18301903
if (staffIdx == muse::nidx || !segment) {
18311904
return false;
18321905
}
@@ -2587,6 +2660,7 @@ bool NotationInteraction::notesHaveActiculation(const std::vector<Note*>& notes,
25872660
//! NOTE Copied from ScoreView::dragLeaveEvent
25882661
void NotationInteraction::endDrop()
25892662
{
2663+
score()->hideAnchors();
25902664
score()->setUpdateAll();
25912665
setDropTarget(nullptr);
25922666
resetDropData();

0 commit comments

Comments
 (0)