diff --git a/OpenUtau.Core/Commands/NoteCommands.cs b/OpenUtau.Core/Commands/NoteCommands.cs index 85bde011f..99859d664 100644 --- a/OpenUtau.Core/Commands/NoteCommands.cs +++ b/OpenUtau.Core/Commands/NoteCommands.cs @@ -26,18 +26,19 @@ public class AddNoteCommand : NoteCommand { readonly int OldPartDuration; public AddNoteCommand(UVoicePart part, UNote note) : base(part, note) { OldPartDuration = part.Duration; - DocManager.Inst.Project.timeAxis.TickPosToBarBeat(note.End - 1, out int bar, out int beat, out int remainingTicks); - int minDurTick = DocManager.Inst.Project.timeAxis.BarBeatToTickPos(bar + 2, 0) - part.position; + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End); if (part.Duration < minDurTick) { NewPartDuration = minDurTick; } } public AddNoteCommand(UVoicePart part, List notes) : base(part, notes) { OldPartDuration = part.Duration; - DocManager.Inst.Project.timeAxis.TickPosToBarBeat((Notes.LastOrDefault()?.End ?? 1) - 1, out int bar, out int beat, out int remainingTicks); - int minDurTick = DocManager.Inst.Project.timeAxis.BarBeatToTickPos(bar + 2, 0) - part.position; - if (part.Duration < minDurTick) { - NewPartDuration = minDurTick; + var note = notes.LastOrDefault(); + if (note != null) { + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End); + if (part.Duration < minDurTick) { + NewPartDuration = minDurTick; + } } } public override string ToString() { return "Add note"; } @@ -83,13 +84,28 @@ public override void Unexecute() { public class MoveNoteCommand : NoteCommand { readonly int DeltaPos, DeltaNoteNum; + readonly int NewPartDuration; + readonly int OldPartDuration; public MoveNoteCommand(UVoicePart part, UNote note, int deltaPos, int deltaNoteNum) : base(part, note) { DeltaPos = deltaPos; DeltaNoteNum = deltaNoteNum; + OldPartDuration = part.Duration; + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End + deltaPos); + if (part.Duration < minDurTick) { + NewPartDuration = minDurTick; + } } public MoveNoteCommand(UVoicePart part, List notes, int deltaPos, int deltaNoteNum) : base(part, notes) { DeltaPos = deltaPos; DeltaNoteNum = deltaNoteNum; + OldPartDuration = part.Duration; + var note = notes.LastOrDefault(); + if (note != null) { + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End + deltaPos); + if (part.Duration < minDurTick) { + NewPartDuration = minDurTick; + } + } } public override string ToString() { return $"Move {Notes.Count()} notes"; } public override void Execute() { @@ -100,6 +116,9 @@ public override void Execute() { note.tone += DeltaNoteNum; Part.notes.Add(note); } + if (NewPartDuration > 0) { + Part.Duration = NewPartDuration; + } } } public override void Unexecute() { @@ -110,6 +129,7 @@ public override void Unexecute() { note.tone -= DeltaNoteNum; Part.notes.Add(note); } + Part.Duration = OldPartDuration; } } } @@ -121,8 +141,7 @@ public class ResizeNoteCommand : NoteCommand { public ResizeNoteCommand(UVoicePart part, UNote note, int deltaDur) : base(part, note) { DeltaDur = deltaDur; OldPartDuration = part.Duration; - DocManager.Inst.Project.timeAxis.TickPosToBarBeat(note.End + deltaDur - 1, out int bar, out int beat, out int remainingTicks); - int minDurTick = DocManager.Inst.Project.timeAxis.BarBeatToTickPos(bar + 2, 0) - part.position; + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End + deltaDur); if (part.Duration < minDurTick) { NewPartDuration = minDurTick; } @@ -130,10 +149,12 @@ public ResizeNoteCommand(UVoicePart part, UNote note, int deltaDur) : base(part, public ResizeNoteCommand(UVoicePart part, List notes, int deltaDur) : base(part, notes) { DeltaDur = deltaDur; OldPartDuration = part.Duration; - DocManager.Inst.Project.timeAxis.TickPosToBarBeat((Notes.LastOrDefault()?.End ?? 1) + deltaDur - 1, out int bar, out int beat, out int remainingTicks); - int minDurTick = DocManager.Inst.Project.timeAxis.BarBeatToTickPos(bar + 2, 0) - part.position; - if (part.Duration < minDurTick) { - NewPartDuration = minDurTick; + var note = notes.LastOrDefault(); + if (note != null) { + int minDurTick = part.GetMinDurTickForNoteEdit(DocManager.Inst.Project, note.End + deltaDur); + if (part.Duration < minDurTick) { + NewPartDuration = minDurTick; + } } } public override string ToString() { return $"Change {Notes.Count()} notes duration"; } diff --git a/OpenUtau.Core/Ustx/UPart.cs b/OpenUtau.Core/Ustx/UPart.cs index 45a755cf8..80597c5bb 100644 --- a/OpenUtau.Core/Ustx/UPart.cs +++ b/OpenUtau.Core/Ustx/UPart.cs @@ -66,6 +66,10 @@ public override int GetMinDurTick(UProject project) { project.timeAxis.TickPosToBarBeat(endTicks, out int bar, out int beat, out int remainingTicks); return project.timeAxis.BarBeatToTickPos(bar, beat + 1) - position; } + public int GetMinDurTickForNoteEdit(UProject project, int noteEnd) { + project.timeAxis.TickPosToBarBeat(position + noteEnd - 1, out int bar, out int beat, out int remainingTicks); + return project.timeAxis.BarBeatToTickPos(bar + 2, 0) - position; + } public override int GetMaxPosiTick(UProject project) { int maxStartTick = position + (notes.FirstOrDefault()?.position ?? Duration); diff --git a/OpenUtau/ViewModels/TracksViewModel.cs b/OpenUtau/ViewModels/TracksViewModel.cs index 387b7dfbe..4c0065104 100644 --- a/OpenUtau/ViewModels/TracksViewModel.cs +++ b/OpenUtau/ViewModels/TracksViewModel.cs @@ -384,7 +384,7 @@ private void SetPlayPos(int tick, bool waitingRendering) { public void OnNext(UCommand cmd, bool isUndo) { if (cmd is NoteCommand noteCommand) { - if (noteCommand is ResizeNoteCommand || noteCommand is AddNoteCommand) { + if (noteCommand is ResizeNoteCommand || noteCommand is AddNoteCommand || noteCommand is MoveNoteCommand) { MessageBus.Current.SendMessage(new PartRefreshEvent(noteCommand.Part)); } MessageBus.Current.SendMessage(new PartRedrawEvent(noteCommand.Part));