diff --git a/src/engraving/api/v1/apitypes.h b/src/engraving/api/v1/apitypes.h
index cc00fbf87e2d6..3282a4e6e4909 100644
--- a/src/engraving/api/v1/apitypes.h
+++ b/src/engraving/api/v1/apitypes.h
@@ -20,8 +20,7 @@
* along with this program. If not, see .
*/
-#ifndef MU_ENGRAVING_APIV1_APITYPES_H
-#define MU_ENGRAVING_APIV1_APITYPES_H
+#pragma once
#include
@@ -227,6 +226,8 @@ enum class ElementType {
TIE_SEGMENT = int(mu::engraving::ElementType::TIE_SEGMENT),
LAISSEZ_VIB_SEGMENT = int(mu::engraving::ElementType::LAISSEZ_VIB_SEGMENT),
LAISSEZ_VIB = int(mu::engraving::ElementType::LAISSEZ_VIB),
+ PARTIAL_TIE_SEGMENT = int(mu::engraving::ElementType::PARTIAL_TIE_SEGMENT),
+ PARTIAL_TIE = int(mu::engraving::ElementType::PARTIAL_TIE),
BAR_LINE = int(mu::engraving::ElementType::BAR_LINE),
STAFF_LINES = int(mu::engraving::ElementType::STAFF_LINES),
SYSTEM_DIVIDER = int(mu::engraving::ElementType::SYSTEM_DIVIDER),
@@ -3599,5 +3600,3 @@ Q_DECLARE_METATYPE(mu::engraving::apiv1::enums::Tid);
Q_DECLARE_METATYPE(mu::engraving::apiv1::enums::Syllabic);
Q_DECLARE_METATYPE(mu::engraving::apiv1::enums::Anchor);
Q_DECLARE_METATYPE(mu::engraving::apiv1::enums::SymId);
-
-#endif // MU_ENGRAVING_APIV1_APITYPES_H
diff --git a/src/engraving/compat/midi/compatmidirender.cpp b/src/engraving/compat/midi/compatmidirender.cpp
index e2515756a589e..35e54a6e61889 100644
--- a/src/engraving/compat/midi/compatmidirender.cpp
+++ b/src/engraving/compat/midi/compatmidirender.cpp
@@ -1080,7 +1080,7 @@ std::set CompatMidiRender::getNotesIndexesToRender(Chord* chord)
}
auto noteShouldBeRendered = [](Note* n) {
- while (n->tieBack() && n != n->tieBack()->startNote()) {
+ while (n->tieBackNonPartial() && n != n->tieBack()->startNote()) {
n = n->tieBack()->startNote();
if (findFirstTrill(n->chord())) {
// The previous tied note probably has events for this note too.
diff --git a/src/engraving/dom/barline.cpp b/src/engraving/dom/barline.cpp
index f390d4258a2ae..290911a35bb4b 100644
--- a/src/engraving/dom/barline.cpp
+++ b/src/engraving/dom/barline.cpp
@@ -103,6 +103,8 @@ static void undoChangeBarLineType(BarLine* bl, BarLineType barType, bool allStav
// createMMRest will then set for the mmrest directly
Measure* m2 = m->isMMRest() ? m->mmRestLast() : m;
+ BarLineType prevBarType = bl->barLineType();
+
switch (barType) {
case BarLineType::END:
case BarLineType::NORMAL:
diff --git a/src/engraving/dom/beam.cpp b/src/engraving/dom/beam.cpp
index fdf7583854cf9..14dab2822481f 100644
--- a/src/engraving/dom/beam.cpp
+++ b/src/engraving/dom/beam.cpp
@@ -481,15 +481,6 @@ void Beam::startEdit(EditData& ed)
initBeamEditData(ed);
}
-//---------------------------------------------------------
-// endEdit
-//---------------------------------------------------------
-
-void Beam::endEdit(EditData& ed)
-{
- EngravingItem::endEdit(ed);
-}
-
//---------------------------------------------------------
// triggerLayout
//---------------------------------------------------------
diff --git a/src/engraving/dom/beam.h b/src/engraving/dom/beam.h
index d9e9d30dd81ec..5e21b6f2d2350 100644
--- a/src/engraving/dom/beam.h
+++ b/src/engraving/dom/beam.h
@@ -20,8 +20,7 @@
* along with this program. If not, see .
*/
-#ifndef MU_ENGRAVING_BEAM_H
-#define MU_ENGRAVING_BEAM_H
+#pragma once
#include "beambase.h"
#include "engravingitem.h"
@@ -64,7 +63,6 @@ class Beam final : public BeamBase
bool isEditable() const override { return true; }
void startEdit(EditData&) override;
- void endEdit(EditData&) override;
void editDrag(EditData&) override;
Fraction tick() const override;
@@ -226,4 +224,3 @@ class Beam final : public BeamBase
std::vector m_tremAnchors;
};
} // namespace mu::engraving
-#endif
diff --git a/src/engraving/dom/chord.cpp b/src/engraving/dom/chord.cpp
index fcc5fff26a8a6..1fb3bca56b9df 100644
--- a/src/engraving/dom/chord.cpp
+++ b/src/engraving/dom/chord.cpp
@@ -1688,7 +1688,7 @@ void Chord::cmdUpdateNotes(AccidentalState* as, staff_idx_t staffIdx)
if (vStaffIdx() == staffIdx) {
std::vector lnotes(notes()); // we need a copy!
for (Note* note : lnotes) {
- if (note->tieBack() && note->tpc() == note->tieBack()->startNote()->tpc()) {
+ if (note->tieBackNonPartial() && note->tpc() == note->tieBack()->startNote()->tpc()) {
// same pitch
if (note->accidental() && note->accidental()->role() == AccidentalRole::AUTO) {
// not courtesy
@@ -2635,7 +2635,7 @@ static bool noteIsBefore(const Note* n1, const Note* n2)
}
if (n1->tieBack()) {
- if (n2->tieBack()) {
+ if (n2->tieBack() && !n2->incomingPartialTie()) {
const Note* sn1 = n1->tieBack()->startNote();
const Note* sn2 = n2->tieBack()->startNote();
if (sn1->chord() == sn2->chord()) {
@@ -2870,6 +2870,7 @@ EngravingItem* Chord::nextElement()
case ElementType::GLISSANDO_SEGMENT:
case ElementType::NOTELINE_SEGMENT:
case ElementType::LAISSEZ_VIB_SEGMENT:
+ case ElementType::PARTIAL_TIE_SEGMENT:
case ElementType::TIE_SEGMENT: {
SpannerSegment* s = toSpannerSegment(e);
Spanner* sp = s->spanner();
diff --git a/src/engraving/dom/cmd.cpp b/src/engraving/dom/cmd.cpp
index eb2b30b16a695..76d8d1c26f855 100644
--- a/src/engraving/dom/cmd.cpp
+++ b/src/engraving/dom/cmd.cpp
@@ -330,16 +330,17 @@ void Score::startCmd(const TranslatableString& actionName)
LOGD("===startCmd()");
}
+ if (undoStack()->hasActiveCommand()) {
+ LOGD("Score::startCmd(): cmd already active");
+ return;
+ }
+
MScore::setError(MsError::MS_NO_ERROR);
cmdState().reset();
// Start collecting low-level undo operations for a
// user-visible undo action.
- if (undoStack()->hasActiveCommand()) {
- LOGD("Score::startCmd(): cmd already active");
- return;
- }
undoStack()->beginMacro(this, actionName);
}
@@ -1691,8 +1692,11 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest)
undoRemoveElement(c->tremoloTwoChord());
}
for (Note* n : c->notes()) {
- if (n->tieFor()) {
- undoRemoveElement(n->tieFor());
+ if (Tie* tie = n->tieFor()) {
+ if (tie->tieJumpPoints()) {
+ tie->undoRemoveTiesFromJumpPoints();
+ }
+ undoRemoveElement(tie);
}
for (Spanner* sp : n->spannerFor()) {
if (sp->isGlissando() || sp->isGuitarBend()) {
@@ -3784,7 +3788,7 @@ void Score::cmdImplode()
// see if we are tying in to this chord
Chord* tied = 0;
for (Note* n : dstChord->notes()) {
- if (n->tieBack()) {
+ if (n->tieBackNonPartial()) {
tied = n->tieBack()->startNote()->chord();
break;
}
diff --git a/src/engraving/dom/dom.cmake b/src/engraving/dom/dom.cmake
index 06bc544d7083b..2b0e6475c06b7 100644
--- a/src/engraving/dom/dom.cmake
+++ b/src/engraving/dom/dom.cmake
@@ -223,6 +223,8 @@ set(DOM_SRC
${CMAKE_CURRENT_LIST_DIR}/ottava.h
${CMAKE_CURRENT_LIST_DIR}/page.cpp
${CMAKE_CURRENT_LIST_DIR}/page.h
+ ${CMAKE_CURRENT_LIST_DIR}/partialtie.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/partialtie.h
${CMAKE_CURRENT_LIST_DIR}/palmmute.cpp
${CMAKE_CURRENT_LIST_DIR}/palmmute.h
${CMAKE_CURRENT_LIST_DIR}/part.cpp
diff --git a/src/engraving/dom/edit.cpp b/src/engraving/dom/edit.cpp
index b57e1b00aca48..5d73c4f61f3aa 100644
--- a/src/engraving/dom/edit.cpp
+++ b/src/engraving/dom/edit.cpp
@@ -23,6 +23,7 @@
#include