Skip to content

Commit

Permalink
when resetting expressions, only reset curve expressions where the no…
Browse files Browse the repository at this point in the history
…te is selected. remove duplicate editing macros.
  • Loading branch information
oxygen-dioxide committed Sep 20, 2024
1 parent d541154 commit 5c81f7e
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 40 deletions.
151 changes: 113 additions & 38 deletions OpenUtau.Core/Editing/ResetBatchEdits.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,83 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using OpenUtau.Core.Ustx;
using OpenUtau.Core.Util;

namespace OpenUtau.Core.Editing {
public class ResetAllParameters : BatchEdit {
public virtual string Name => name;
class TickRange{
public int start;
public int end;

private string name;
public TickRange(int start, int end){
this.start = start;
this.end = end;
}

public ResetAllParameters() {
name = "pianoroll.menu.notes.reset.allparameters";
public TickRange copy(){
return new TickRange(start, end);
}
}

public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, DocManager docManager) {
var notes = selectedNotes.Count > 0 ? selectedNotes : part.notes.ToList();
docManager.StartUndoGroup(true);
foreach (var note in notes) {
// pitch points
docManager.ExecuteCmd(new ResetPitchPointsCommand(part, note));
// expressions
if (note.phonemeExpressions.Count > 0) {
docManager.ExecuteCmd(new ResetExpressionsCommand(part, note));
}
// vibrato
if (note.vibrato.length > 0) {
docManager.ExecuteCmd(new VibratoLengthCommand(part, note, 0));
}
// timings
bool shouldClear = false;
foreach (var o in note.phonemeOverrides) {
if (o.offset != null || o.preutterDelta != null || o.overlapDelta != null) {
shouldClear = true;
break;
}
}
if (shouldClear) {
docManager.ExecuteCmd(new ClearPhonemeTimingCommand(part, note));
static class SelectionUtils{
/// <summary>
/// Simplify the time selection by merging overlapping ranges.
/// </summary>
/// <param name="ranges">Time selection to be simplified</param>
/// <returns></returns>
public static List<TickRange> SimplifyTimeSelection(List<TickRange> ranges){
var result = new List<TickRange>();
if(ranges.Count == 0){
return result;
}
ranges.Sort((a, b) => a.start - b.start);
var current = ranges[0].copy();
for(int i = 1; i < ranges.Count; i++){
var next = ranges[i];
if(next.start <= current.end){
current.end = Math.Max(current.end, next.end);
}else{
result.Add(current);
current = next;
}
// aliases
foreach (var o in note.phonemeOverrides) {
if (o.phoneme != null) {
docManager.ExecuteCmd(new ChangePhonemeAliasCommand(part, note, o.index, null));
}
}
result.Add(current);
return result;
}

public static Dictionary<UNote, List<UPhoneme>> NotePhonemes(UVoicePart part){
var result = new Dictionary<UNote, List<UPhoneme>>();
foreach(var phoneme in part.phonemes){
var note = phoneme.Parent;
if(result.ContainsKey(note)){
result[note].Add(phoneme);
}else{
result[note] = new List<UPhoneme>(){phoneme};
}
}
docManager.EndUndoGroup();
return result;
}

/// <summary>
/// Get the tick ranges of the selected notes, relative to the beginning of the part.
/// </summary>
/// <param name="part"></param>
/// <param name="selectedNotes"></param>
/// <returns></returns>
public static List<TickRange> SelectedTickRanges(UVoicePart part, List<UNote> selectedNotes) {
var notePhonemes = NotePhonemes(part);
var result = selectedNotes.Select(note => {
int start = note.position;
if(note.Prev.End < note.position
&& notePhonemes.TryGetValue(note, out var phonemes)
&& phonemes.Count > 0
){
start = Math.Min(start, phonemes[0].position);
}
int end = note.End;
return new TickRange(start - 1, end + 1);
}).ToList();
return SimplifyTimeSelection(result);
}
}

Expand Down Expand Up @@ -80,14 +112,34 @@ public ResetAllExpressions() {
public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, DocManager docManager) {
var notes = selectedNotes.Count > 0 ? selectedNotes : part.notes.ToList();
docManager.StartUndoGroup(true);
//reset numerical and options expressions
foreach (var note in notes) {
if (note.phonemeExpressions.Count > 0) {
docManager.ExecuteCmd(new ResetExpressionsCommand(part, note));
}
}
//reset curve expressions
var curveAbbrs = part.curves.Select(c => c.abbr).ToArray();
foreach (var abbr in curveAbbrs) {
docManager.ExecuteCmd(new ClearCurveCommand(part, abbr));
foreach (var abbr in curveAbbrs) {
if(notes.Count == part.notes.Count){
//All notes are selected
docManager.ExecuteCmd(new ClearCurveCommand(part, abbr));
}
else{
var selectedTickRanges = SelectionUtils.SelectedTickRanges(part, notes);
int defaultValue = (int)part.curves.First(c => c.abbr == abbr).descriptor.defaultValue;
foreach(var range in selectedTickRanges){
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.start, defaultValue,
range.start, defaultValue));
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.end, defaultValue,
range.end, defaultValue));
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.start, defaultValue,
range.end, defaultValue));
}
}
}
docManager.EndUndoGroup();
}
Expand Down Expand Up @@ -235,6 +287,29 @@ public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, Do
}
}
}
//curve expressions
var curveAbbrs = part.curves.Select(c => c.abbr).ToArray();
foreach (var abbr in curveAbbrs) {
if(notes.Count == part.notes.Count){
//All notes are selected
docManager.ExecuteCmd(new ClearCurveCommand(part, abbr));
}
else{
var selectedTickRanges = SelectionUtils.SelectedTickRanges(part, notes);
int defaultValue = (int)part.curves.First(c => c.abbr == abbr).descriptor.defaultValue;
foreach(var range in selectedTickRanges){
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.start, defaultValue,
range.start, defaultValue));
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.end, defaultValue,
range.end, defaultValue));
docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr,
range.start, defaultValue,
range.end, defaultValue));
}
}
}
docManager.EndUndoGroup();
}
}
Expand Down
3 changes: 1 addition & 2 deletions OpenUtau/Views/PianoRollWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,13 @@ await MessageBox.ShowProcessing(this, $"{name} - ? / ?",
CommandParameter = edit,
}));
ViewModel.ResetBatchEdits.AddRange(new List<BatchEdit>() {
new ResetAllParameters(),
new ResetAll(),
new ResetPitchBends(),
new ResetAllExpressions(),
new ClearVibratos(),
new ResetVibratos(),
new ClearTimings(),
new ResetAliases(),
new ResetAll(),
}.Select(edit => new MenuItemViewModel() {
Header = ThemeManager.GetString(edit.Name),
Command = noteBatchEditCommand,
Expand Down

0 comments on commit 5c81f7e

Please sign in to comment.