diff --git a/OpenUtau/Strings/Strings.axaml b/OpenUtau/Strings/Strings.axaml index 4aa620c1e..1e5614e7e 100644 --- a/OpenUtau/Strings/Strings.axaml +++ b/OpenUtau/Strings/Strings.axaml @@ -99,8 +99,9 @@ OpenUtau aims to be an open source editing environment for UTAU community, with Installing Installing phonemizer Installing - Merging Parts - Parts on different tracks cannot be merged. + Merging Parts + Parts on different tracks cannot be merged. + Merged part will contain overlapping notes. Are you sure to continue? Splitting Part There are one or more note(s) overlapping with the playhead. Do you want to continue by splitting at the nearest position after current playhead with no notes in the way? diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index 5ea4cdb0c..1ffc9ca50 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -81,7 +81,7 @@ public MainWindow() { PartGotoFileCommand = ReactiveCommand.Create(part => GotoFile(part)); PartReplaceAudioCommand = ReactiveCommand.Create(part => ReplaceAudio(part)); PartTranscribeCommand = ReactiveCommand.Create(part => Transcribe(part)); - PartMergeCommand = ReactiveCommand.Create(part => MergePart(part)); + PartMergeCommand = ReactiveCommand.Create(async part => await MergePart(part)); PartSplitCommand = ReactiveCommand.Create(async part => await SplitPart(part)); AddHandler(DragDrop.DropEvent, OnDrop); @@ -1568,17 +1568,17 @@ public void OnWelcomeRecovery(object sender, RoutedEventArgs args) { viewModel.Page = 1; } - void MergePart(UPart part) { + async Task MergePart(UPart part) { List selectedParts = viewModel.TracksViewModel.SelectedParts; - if (!selectedParts.All(p => p.trackNo.Equals(part.trackNo))) { + if (selectedParts.Count <= 1) { return; } + if (selectedParts.Any(p => p.trackNo != part.trackNo)) { _ = MessageBox.Show( this, - ThemeManager.GetString("dialogs.merge.multitracks"), - ThemeManager.GetString("dialogs.merge.caption"), + ThemeManager.GetString("dialogs.mergeparts.multitracks"), + ThemeManager.GetString("dialogs.mergeparts.caption"), MessageBox.MessageBoxButtons.Ok); return; } - if (selectedParts.Count() <= 1) { return; } List voiceParts = []; foreach (UPart p in selectedParts) { if (p is UVoicePart vp) { @@ -1625,6 +1625,14 @@ void MergePart(UPart part) { SkipPhonemizer = false }; mergedPart.Validate(options, DocManager.Inst.Project, DocManager.Inst.Project.tracks[part.trackNo]); + if (mergedPart.notes.Any(n => n.OverlapError)) { + var res = await MessageBox.Show( + this, + ThemeManager.GetString("dialogs.mergeparts.overlap"), + ThemeManager.GetString("dialogs.mergeparts.caption"), + MessageBox.MessageBoxButtons.YesNo); + if (res == MessageBox.MessageBoxResult.No) { return; } + } DocManager.Inst.StartUndoGroup("command.part.edit"); for (int i = selectedParts.Count - 1; i >= 0; i--) { // The index will shift by removing a part on each loop