@@ -139,6 +139,18 @@ void NotationActionController::init()
139139 registerCommand (ADD_TIE_COMMAND , &Controller::addTie);
140140 registerCommand (ADD_SLUR_COMMAND , &Controller::addSlur);
141141 registerCommand (ADD_LV_COMMAND , &Controller::addLaissezVib);
142+ registerCommand (ADD_MARCATO_COMMAND , [this ]() { toggleArticulation (SymbolId::articMarcatoAbove); });
143+ registerCommand (ADD_SFORZATO_COMMAND , [this ]() { toggleArticulation (SymbolId::articAccentAbove); });
144+ registerCommand (ADD_TENUTO_COMMAND , [this ]() { toggleArticulation (SymbolId::articTenutoAbove); });
145+ registerCommand (ADD_STACCATO_COMMAND , [this ]() { toggleArticulation (SymbolId::articStaccatoAbove); });
146+
147+ registerCommand (USE_VOICE_1_COMMAND , [this ]() { changeVoice (0 ); });
148+ registerCommand (USE_VOICE_2_COMMAND , [this ]() { changeVoice (1 ); });
149+ registerCommand (USE_VOICE_3_COMMAND , [this ]() { changeVoice (2 ); });
150+ registerCommand (USE_VOICE_4_COMMAND , [this ]() { changeVoice (3 ); });
151+
152+ registerCommand (FLIP_COMMAND , &Interaction::flipSelection);
153+ registerCommand (FLIP_HORIZONTALLY_COMMAND , &Interaction::flipSelectionHorizontally);
142154
143155 registerAction (" note-action" , &Controller::handleNoteAction);
144156
@@ -187,11 +199,6 @@ void NotationActionController::init()
187199
188200 registerAction (" rest" , &Interaction::putRestToSelection);
189201
190- registerAction (" add-marcato" , [this ]() { toggleArticulation (SymbolId::articMarcatoAbove); });
191- registerAction (" add-sforzato" , [this ]() { toggleArticulation (SymbolId::articAccentAbove); });
192- registerAction (" add-tenuto" , [this ]() { toggleArticulation (SymbolId::articTenutoAbove); });
193- registerAction (" add-staccato" , [this ]() { toggleArticulation (SymbolId::articStaccatoAbove); });
194-
195202 registerAction (" duplet" , [this ]() { putTuplet (2 ); }, &Controller::noteOrRestSelected);
196203 registerAction (" triplet" , [this ]() { putTuplet (3 ); }, &Controller::noteOrRestSelected);
197204 registerAction (" quadruplet" , [this ]() { putTuplet (4 ); }, &Controller::noteOrRestSelected);
@@ -235,9 +242,6 @@ void NotationActionController::init()
235242 registerAction (" notation-paste-special" , [this ]() { pasteSelection (PastingType::Special); });
236243 registerAction (" notation-swap" , &Interaction::swapSelection, &Controller::hasSelection);
237244
238- registerAction (" flip" , &Interaction::flipSelection, &Controller::hasSelection);
239- registerAction (" flip-horizontally" , &Interaction::flipSelectionHorizontally, &Controller::hasSelection);
240-
241245 registerAction (" chord-tie" , &Controller::chordTie);
242246
243247 registerAction (" hammer-on-pull-off" , &Controller::addHammerOnPullOff);
@@ -506,10 +510,6 @@ void NotationActionController::init()
506510 }
507511 }
508512
509- for (voice_idx_t i = 0 ; i < mu::engraving::VOICES ; ++i) {
510- registerAction (" voice-" + std::to_string (i + 1 ), [this , i]() { changeVoice (static_cast <int >(i)); });
511- }
512-
513513 registerAction (" voice-assignment-all-in-instrument" , &Interaction::changeSelectedElementsVoiceAssignment,
514514 VoiceAssignment::ALL_VOICE_IN_INSTRUMENT );
515515 registerAction (" voice-assignment-all-in-staff" , &Interaction::changeSelectedElementsVoiceAssignment,
@@ -1015,6 +1015,40 @@ int NotationActionController::currentDotCount() const
10151015 return interaction->noteInput ()->state ().duration ().dots ();
10161016}
10171017
1018+ bool NotationActionController::currentIsRest () const
1019+ {
1020+ INotationInteractionPtr interaction = currentNotationInteraction ();
1021+ if (!interaction) {
1022+ return false ;
1023+ }
1024+
1025+ INotationNoteInputPtr noteInput = interaction->noteInput ();
1026+ if (!noteInput) {
1027+ return false ;
1028+ }
1029+
1030+ if (noteInput->isNoteInputMode ()) {
1031+ return noteInput->state ().rest ();
1032+ }
1033+
1034+ INotationSelectionPtr selection = interaction->selection ();
1035+ if (!selection) {
1036+ return false ;
1037+ }
1038+
1039+ if (selection->isNone () || selection->isRange ()) {
1040+ return false ;
1041+ }
1042+
1043+ for (const EngravingItem* element: selection->elements ()) {
1044+ if (!element->isRest ()) {
1045+ return false ;
1046+ }
1047+ }
1048+
1049+ return true ;
1050+ }
1051+
10181052AccidentalType NotationActionController::currentAccidentalType () const
10191053{
10201054 INotationInteractionPtr interaction = currentNotationInteraction ();
@@ -1025,6 +1059,119 @@ AccidentalType NotationActionController::currentAccidentalType() const
10251059 return interaction->noteInput ()->state ().accidentalType ();
10261060}
10271061
1062+ std::set<SymbolId> NotationActionController::currentArticulations () const
1063+ {
1064+ INotationInteractionPtr interaction = currentNotationInteraction ();
1065+ if (!interaction) {
1066+ return {};
1067+ }
1068+
1069+ INotationNoteInputPtr noteInput = interaction->noteInput ();
1070+ if (!noteInput) {
1071+ return {};
1072+ }
1073+
1074+ if (noteInput->isNoteInputMode ()) {
1075+ return mu::engraving::splitArticulations (noteInput->state ().articulationIds ());
1076+ }
1077+
1078+ INotationSelectionPtr selection = interaction->selection ();
1079+ if (!selection) {
1080+ return {};
1081+ }
1082+
1083+ if (selection->isNone ()) {
1084+ return {};
1085+ }
1086+
1087+ auto chordArticulations = [](const Chord* chord) {
1088+ std::set<SymbolId> result;
1089+ for (Articulation* articulation: chord->articulations ()) {
1090+ result.insert (articulation->symId ());
1091+ }
1092+
1093+ result = mu::engraving::flipArticulations (result, mu::engraving::PlacementV::ABOVE );
1094+ return mu::engraving::splitArticulations (result);
1095+ };
1096+
1097+ std::set<SymbolId> result;
1098+ bool isFirstNote = true ;
1099+ for (const EngravingItem* element: selection->elements ()) {
1100+ if (!element->isNote ()) {
1101+ continue ;
1102+ }
1103+
1104+ const Note* note = toNote (element);
1105+ if (isFirstNote) {
1106+ result = chordArticulations (note->chord ());
1107+ isFirstNote = false ;
1108+ } else {
1109+ std::set<SymbolId> currentNoteArticulations = chordArticulations (note->chord ());
1110+ for (auto it = result.begin (); it != result.end ();) {
1111+ if (std::find (currentNoteArticulations.begin (), currentNoteArticulations.end (),
1112+ *it) == currentNoteArticulations.end ()) {
1113+ it = result.erase (it);
1114+ } else {
1115+ ++it;
1116+ }
1117+ }
1118+ }
1119+ }
1120+
1121+ return result;
1122+ }
1123+
1124+ voice_idx_t NotationActionController::currentVoice () const
1125+ {
1126+ constexpr voice_idx_t INVALID_VOICE = muse::nidx;
1127+
1128+ INotationInteractionPtr interaction = currentNotationInteraction ();
1129+ if (!interaction) {
1130+ return INVALID_VOICE ;
1131+ }
1132+
1133+ INotationNoteInputPtr noteInput = interaction->noteInput ();
1134+ if (!noteInput) {
1135+ return INVALID_VOICE ;
1136+ }
1137+
1138+ if (noteInput->isNoteInputMode ()) {
1139+ return noteInput->state ().voice ();
1140+ }
1141+
1142+ INotationSelectionPtr selection = interaction->selection ();
1143+ if (!selection) {
1144+ return INVALID_VOICE ;
1145+ }
1146+
1147+ if (selection->isNone ()) {
1148+ return INVALID_VOICE ;
1149+ }
1150+
1151+ const std::vector<EngravingItem*>& selectedElements = selection->elements ();
1152+ if (selectedElements.empty ()) {
1153+ return INVALID_VOICE ;
1154+ }
1155+
1156+ voice_idx_t voice = INVALID_VOICE ;
1157+ for (const EngravingItem* element : selectedElements) {
1158+ if (element->hasVoiceAssignmentProperties ()) {
1159+ VoiceAssignment voiceAssignment = element->getProperty (Pid::VOICE_ASSIGNMENT ).value <VoiceAssignment>();
1160+ if (voiceAssignment == VoiceAssignment::ALL_VOICE_IN_INSTRUMENT || voiceAssignment == VoiceAssignment::ALL_VOICE_IN_STAFF ) {
1161+ return INVALID_VOICE ;
1162+ }
1163+ }
1164+ voice_idx_t elementVoice = element->voice ();
1165+ if (elementVoice != voice && voice != INVALID_VOICE ) {
1166+ return INVALID_VOICE ;
1167+ }
1168+
1169+ voice = elementVoice;
1170+ }
1171+
1172+ return voice;
1173+ }
1174+
10281175muse::async::Notification NotationActionController::selectionChanged () const
10291176{
10301177 return m_selectionChanged;
0 commit comments