Skip to content

Commit

Permalink
Merge pull request #26367 from RomanPudashkin/input_by_duration_fixes
Browse files Browse the repository at this point in the history
Input by duration: various fixes
  • Loading branch information
RomanPudashkin authored Feb 12, 2025
2 parents da05a8e + ad6b33f commit 6558ac6
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ BaseSection {
id: root

property alias playNotesWhenEditing: playNotesToggle.checked
property alias playPreviewNotesInInputByDuration: playPreviewNotesInInputByDurationBox.checked
property alias playChordWhenEditing: playChordBox.checked
property alias playChordSymbolWhenEditing: playChordSymbolBox.checked
property alias playPreviewNotesInInputByDuration: playPreviewNotesInInputByDurationBox.checked
property alias notePlayDurationMilliseconds: notePlayDurationControl.currentValue

signal playNotesWhenEditingChangeRequested(bool play)
signal playPreviewNotesInInputByDurationChangeRequested(bool play)
signal playChordWhenEditingChangeRequested(bool play)
signal playChordSymbolWhenEditingChangeRequested(bool play)
signal playPreviewNotesInInputByDurationChangeRequested(bool play)
signal notePlayDurationChangeRequested(int duration)

title: qsTrc("appshell/preferences", "Note preview")
Expand Down Expand Up @@ -71,23 +71,6 @@ BaseSection {
}
}

CheckBox {
id: playPreviewNotesInInputByDurationBox
width: parent.width

text: qsTrc("appshell/preferences", "Include preview notes in playback (input by duration only)")

enabled: root.playNotesWhenEditing

navigation.name: "PlayPreviewNotesInInputByDurationBox"
navigation.panel: root.navigation
navigation.row: 1

onClicked: {
root.playPreviewNotesInInputByDurationChangeRequested(!checked)
}
}

IncrementalPropertyControlWithTitle {
id: notePlayDurationControl

Expand All @@ -103,7 +86,7 @@ BaseSection {

navigation.name: "NotePlayDurationControl"
navigation.panel: root.navigation
navigation.row: 2
navigation.row: 1

onValueEdited: function(newValue) {
root.notePlayDurationChangeRequested(newValue)
Expand All @@ -120,7 +103,7 @@ BaseSection {

navigation.name: "PlayChordBox"
navigation.panel: root.navigation
navigation.row: 3
navigation.row: 2

onClicked: {
root.playChordWhenEditingChangeRequested(!checked)
Expand All @@ -137,10 +120,27 @@ BaseSection {

navigation.name: "PlayChordSymbolBox"
navigation.panel: root.navigation
navigation.row: 4
navigation.row: 3

onClicked: {
root.playChordSymbolWhenEditingChangeRequested(!checked)
}
}

CheckBox {
id: playPreviewNotesInInputByDurationBox
width: parent.width

text: qsTrc("appshell/preferences", "Play when setting pitch (input by duration mode only)")

enabled: root.playNotesWhenEditing

navigation.name: "PlayPreviewNotesInInputByDurationBox"
navigation.panel: root.navigation
navigation.row: 4

onClicked: {
root.playPreviewNotesInInputByDurationChangeRequested(!checked)
}
}
}
31 changes: 16 additions & 15 deletions src/engraving/dom/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1068,7 +1068,7 @@ Segment* Score::setNoteRest(Segment* segment, track_idx_t track, NoteVal nval, F
assert(segment->segmentType() == SegmentType::ChordRest);
InputState& is = externalInputState ? (*externalInputState) : m_is;

bool isRest = nval.pitch == -1;
bool isRest = nval.isRest();
Fraction tick = segment->tick();
EngravingItem* nr = nullptr;
Tie* tie = nullptr;
Expand Down Expand Up @@ -2155,8 +2155,8 @@ void Score::toggleAccidental(AccidentalType at)
m_is.setAccidentalType(at);
m_is.setRest(false);

if (usingNoteEntryMethod(NoteEntryMethod::BY_DURATION)) {
applyAccidentalToInputNotes();
if (!m_is.notes().empty()) {
applyAccidentalToInputNotes(at);
}
} else {
if (selection().isNone()) {
Expand All @@ -2169,23 +2169,24 @@ void Score::toggleAccidental(AccidentalType at)
}
}

void Score::applyAccidentalToInputNotes()
void Score::applyAccidentalToInputNotes(AccidentalType accidentalType)
{
const AccidentalVal acc = Accidental::subtype2value(m_is.accidentalType());
const bool concertPitch = style().styleB(Sid::concertPitch);
NoteValList notes = m_is.notes();
NoteValList notes;

for (NoteVal& nval : notes) {
const int oldPitch = nval.pitch;
const int step = mu::engraving::pitch2step(oldPitch);
const int newTpc = mu::engraving::step2tpc(step, acc);
Position pos;
pos.segment = m_is.segment();
pos.staffIdx = m_is.staffIdx();

nval.pitch += static_cast<int>(acc);
for (const NoteVal& oldVal : m_is.notes()) {
pos.line = noteValToLine(oldVal, m_is.staff(), m_is.tick());

if (concertPitch) {
nval.tpc1 = newTpc;
bool error = false;
const NoteVal newVal = noteValForPosition(pos, accidentalType, error);

if (error) {
notes.push_back(oldVal);
} else {
nval.tpc2 = newTpc;
notes.push_back(newVal);
}
}

Expand Down
90 changes: 45 additions & 45 deletions src/engraving/dom/noteentry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,56 +150,20 @@ NoteVal Score::noteValForPosition(Position pos, AccidentalType at, bool& error)
return nval;
}

Note* Score::addPitch(NoteVal& nval, bool addToPreviousChord, InputState* externalInputState)
{
AddToChord addType = addToPreviousChord ? AddToChord::AtPreviousPosition : AddToChord::None;
return addPitch(nval, addType, externalInputState);
}

Note* Score::addPitch(NoteVal& nval, AddToChord addFlag, InputState* externalInputState)
Note* Score::addPitch(NoteVal& nval, bool addFlag, InputState* externalInputState)
{
InputState& is = externalInputState ? (*externalInputState) : m_is;

if (addFlag != AddToChord::None) {
ChordRest* c = nullptr;
if (addFlag == AddToChord::AtPreviousPosition) {
c = toChordRest(is.lastSegment()->element(is.track()));
} else if (addFlag == AddToChord::AtCurrentPosition) {
c = is.cr();
}

if (c == 0 || !c->isChord()) {
if (addFlag) {
ChordRest* c = toChordRest(is.lastSegment()->element(is.track()));
if (!c || !c->isChord()) {
LOGD("Score::addPitch: cr %s", c ? c->typeName() : "zero");
return 0;
}

Chord* chord = toChord(c);
auto isTied = [](const Chord* ch) {
if (ch->notes().empty()) {
return false;
}
Note* n = ch->notes().at(0);
return n->tieFor() || n->tieBack();
};

Note* note = nullptr;
if (isTied(chord)) {
note = addNoteToTiedChord(chord, nval, /* forceAccidental */ false);
if (!note) {
note = addNote(chord, nval, /* forceAccidental */ false, /* articulationIds */ {}, externalInputState);
}
} else {
note = addNote(chord, nval, /* forceAccidental */ false, is.articulationIds(), externalInputState);
return nullptr;
}

if (is.lastSegment() == is.segment()) {
NoteEntryMethod entryMethod = is.noteEntryMethod();
if (entryMethod != NoteEntryMethod::REALTIME_AUTO && entryMethod != NoteEntryMethod::REALTIME_MANUAL) {
is.moveToNextInputPos();
}
}
return note;
return addPitchToChord(nval, toChord(c), externalInputState);
}

expandVoice(is.segment(), is.track());

// insert note
Expand Down Expand Up @@ -253,7 +217,7 @@ Note* Score::addPitch(NoteVal& nval, AddToChord addFlag, InputState* externalInp
note->setTrack(chord->track());
note->setNval(nval);
lastTiedNote = note;
if (addFlag == AddToChord::None) {
if (!addFlag) {
std::vector<Note*> notes = chord->notes();
// break all ties into current chord
// these will exist only if user explicitly moved cursor to a tied-into note
Expand Down Expand Up @@ -359,6 +323,42 @@ Note* Score::addPitch(NoteVal& nval, AddToChord addFlag, InputState* externalInp
return note;
}

Note* Score::addPitchToChord(NoteVal& nval, Chord* chord, InputState* externalInputState)
{
IF_ASSERT_FAILED(chord) {
return nullptr;
}

InputState& is = externalInputState ? (*externalInputState) : m_is;

auto isTied = [](const Chord* ch) {
if (ch->notes().empty()) {
return false;
}
Note* n = ch->notes().at(0);
return n->tieFor() || n->tieBack();
};

Note* note = nullptr;
if (isTied(chord)) {
note = addNoteToTiedChord(chord, nval, /* forceAccidental */ false);
if (!note) {
note = addNote(chord, nval, /* forceAccidental */ false, /* articulationIds */ {}, externalInputState);
}
} else {
note = addNote(chord, nval, /* forceAccidental */ false, is.articulationIds(), externalInputState);
}

if (is.lastSegment() == is.segment()) {
NoteEntryMethod entryMethod = is.noteEntryMethod();
if (entryMethod != NoteEntryMethod::REALTIME_AUTO && entryMethod != NoteEntryMethod::REALTIME_MANUAL) {
is.moveToNextInputPos();
}
}

return note;
}

//---------------------------------------------------------
// putNote
// mouse click in state NoteType::ENTRY
Expand Down Expand Up @@ -468,7 +468,7 @@ Ret Score::putNote(const Position& p, bool replace)
handleOverlappingChordRest(m_is);
}

auto checkTied = [&](){
auto checkTied = [&]() {
if (!cr || !cr->isChord()) {
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/engraving/dom/noteval.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ struct NoteVal {
{
return concertPitch ? tpc1 : tpc2;
}

bool isRest() const
{
return pitch == -1;
}
};

using NoteValList = std::vector<NoteVal>;
Expand Down
29 changes: 23 additions & 6 deletions src/engraving/dom/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3203,17 +3203,34 @@ void Score::padToggle(Pad p, bool toggleForSelectionOnly)
// Enter a rest
setNoteRest(m_is.segment(), m_is.track(), NoteVal(), m_is.duration().fraction());
m_is.moveToNextInputPos();
} else if (!m_is.notes().empty()) {
const ChordRest* cr = m_is.cr();
AddToChord addType = AddToChord::None;
} else {
if (usingNoteEntryMethod(NoteEntryMethod::RHYTHM)) {
const EngravingItem* selectedItem = score()->selection().element();
if (selectedItem && selectedItem->isNote()) {
m_is.setNotes({ toNote(selectedItem)->noteVal() });
}
}

ChordRest* cr = m_is.cr();
Chord* chord = nullptr;

if (cr && cr->isChord() && cr->durationType() == m_is.duration()) {
addType = AddToChord::AtCurrentPosition;
chord = toChord(cr);
}

for (const NoteVal& nval : m_is.notes()) {
NoteVal copy(nval);
addPitch(copy, addType);
addType = AddToChord::AtCurrentPosition;
const Note* note = nullptr;

if (chord) {
note = addPitchToChord(copy, chord);
} else {
note = addPitch(copy, false /*addFlag*/);
}

if (note) {
chord = note->chord();
}
}
}
} else {
Expand Down
20 changes: 7 additions & 13 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,22 +515,12 @@ class Score : public EngravingObject, public muse::Injectable
void doUndoRemoveElement(EngravingItem*);
bool containsElement(const EngravingItem*) const;

enum class AddToChord : unsigned char {
None,
AtPreviousPosition,
AtCurrentPosition,
};

Note* addPitch(NoteVal&, bool addToPreviousChord, InputState* externalInputState = nullptr);
Note* addPitch(NoteVal&, AddToChord addFlag = AddToChord::None, InputState* externalInputState = nullptr);

Note* addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord, bool allowTransposition);
NoteVal noteVal(int pitch, bool allowTransposition) const;
Note* addPitch(NoteVal&, bool addFlag, InputState* externalInputState = nullptr);
Note* addMidiPitch(int pitch, bool addFlag, bool allowTransposition);
Note* addNote(Chord*, const NoteVal& noteVal, bool forceAccidental = false, const std::set<SymId>& articulationIds = {},
InputState* externalInputState = nullptr);
Note* addNoteToTiedChord(Chord*, const NoteVal& noteVal, bool forceAccidental = false, const std::set<SymId>& articulationIds = {});

NoteVal noteVal(int pitch, bool allowTransposition) const;
NoteVal noteValForPosition(Position pos, AccidentalType at, bool& error);

Slur* addSlur(ChordRest* firstChordRest, ChordRest* secondChordRest, const Slur* slurTemplate);
Expand Down Expand Up @@ -1117,7 +1107,11 @@ class Score : public EngravingObject, public muse::Injectable

void updateStavesNumberForSystems();

void applyAccidentalToInputNotes();
void applyAccidentalToInputNotes(AccidentalType accidentalType);

Note* addPitchToChord(NoteVal&, Chord* chord, InputState* externalInputState = nullptr);
Note* addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord, bool allowTransposition);
Note* addNoteToTiedChord(Chord*, const NoteVal& noteVal, bool forceAccidental = false, const std::set<SymId>& articulationIds = {});

int m_linkId = 0;
MasterScore* m_masterScore = nullptr;
Expand Down
Loading

0 comments on commit 6558ac6

Please sign in to comment.