diff --git a/OpenUtau.Core/Commands/ExpCommands.cs b/OpenUtau.Core/Commands/ExpCommands.cs index fd8b09635..100b5dff4 100644 --- a/OpenUtau.Core/Commands/ExpCommands.cs +++ b/OpenUtau.Core/Commands/ExpCommands.cs @@ -21,10 +21,20 @@ public ExpCommand(UVoicePart part) { } public class SetNoteExpressionCommand : ExpCommand { + static readonly HashSet needsPhonemizer = new HashSet { + Format.Ustx.ALT, Format.Ustx.CLR, Format.Ustx.SHFT, Format.Ustx.VEL + }; + public readonly UProject project; public readonly UTrack track; public readonly float?[] newValue; public readonly float?[] oldValue; + public override ValidateOptions ValidateOptions + => new ValidateOptions { + SkipTiming = true, + Part = Part, + SkipPhonemizer = !needsPhonemizer.Contains(Key), + }; public SetNoteExpressionCommand(UProject project, UTrack track, UVoicePart part, UNote note, string abbr, float?[] values) : base(part) { this.project = project; this.track = track; @@ -39,11 +49,21 @@ public SetNoteExpressionCommand(UProject project, UTrack track, UVoicePart part, } public class SetNotesSameExpressionCommand : ExpCommand { + static readonly HashSet needsPhonemizer = new HashSet { + Format.Ustx.ALT, Format.Ustx.CLR, Format.Ustx.SHFT, Format.Ustx.VEL + }; + public readonly UProject project; public readonly UTrack track; public readonly UNote[] notes; public readonly float? newValue; public readonly float?[][] oldValue; + public override ValidateOptions ValidateOptions + => new ValidateOptions { + SkipTiming = true, + Part = Part, + SkipPhonemizer = !needsPhonemizer.Contains(Key), + }; public SetNotesSameExpressionCommand(UProject project, UTrack track, UVoicePart part, IEnumerable notes, string abbr, float? value) : base(part) { this.project = project; this.track = track; diff --git a/OpenUtau.Core/Ustx/UNote.cs b/OpenUtau.Core/Ustx/UNote.cs index b900c52f7..7f7ff3245 100644 --- a/OpenUtau.Core/Ustx/UNote.cs +++ b/OpenUtau.Core/Ustx/UNote.cs @@ -220,6 +220,8 @@ public void SetExpression(UProject project, UTrack track, string abbr, float?[] return; } + phonemeExpressions.RemoveAll(exp => exp.descriptor?.abbr == abbr); + int indexes = phonemeIndexes.LastOrDefault() + 1; for (int i = 0; i < indexes; i++) { if (i == 0 || phonemeIndexes.Contains(i)) { @@ -229,21 +231,14 @@ public void SetExpression(UProject project, UTrack track, string abbr, float?[] } else { value = values.Last(); } - if (value == null) { - phonemeExpressions.RemoveAll(exp => exp.descriptor?.abbr == abbr && exp.index == i); continue; } - var phonemeExp = phonemeExpressions.FirstOrDefault(exp => exp.descriptor?.abbr == abbr && exp.index == i); - if (phonemeExp != null) { - phonemeExp.descriptor = trackExp.descriptor; - phonemeExp.value = (float)value; - } else { - phonemeExpressions.Add(new UExpression(trackExp.descriptor) { - index = i, - value = (float)value, - }); - } + + phonemeExpressions.Add(new UExpression(trackExp.descriptor) { + index = i, + value = (float)value, + }); } } } diff --git a/OpenUtau.Core/Ustx/UPhoneme.cs b/OpenUtau.Core/Ustx/UPhoneme.cs index 6c46e5016..0d98d4ab0 100644 --- a/OpenUtau.Core/Ustx/UPhoneme.cs +++ b/OpenUtau.Core/Ustx/UPhoneme.cs @@ -190,7 +190,7 @@ public void SetExpression(UProject project, UTrack track, string abbr, float? va } var note = Parent.Extends ?? Parent; if (value == null) { - note.phonemeExpressions.RemoveAll(exp => exp.descriptor?.abbr == abbr && exp.index == index); + note.phonemeExpressions.RemoveAll(exp => exp.descriptor?.abbr == abbr && exp.index == index || (exp.index != null && !note.phonemeIndexes.Contains((int)exp.index))); } else { var phonemeExp = note.phonemeExpressions.FirstOrDefault(exp => exp.descriptor?.abbr == abbr && exp.index == index); if (phonemeExp != null) { diff --git a/OpenUtau/Controls/NotePropertyExpression.axaml b/OpenUtau/Controls/NotePropertyExpression.axaml index 7161fada8..0d702dd6d 100644 --- a/OpenUtau/Controls/NotePropertyExpression.axaml +++ b/OpenUtau/Controls/NotePropertyExpression.axaml @@ -13,6 +13,7 @@ Name="slider"/> + IsDropDownOpen="{Binding DropDownOpen, Mode=OneWayToSource}" + Name="comboBox"/> diff --git a/OpenUtau/Controls/NotePropertyExpression.axaml.cs b/OpenUtau/Controls/NotePropertyExpression.axaml.cs index 35af94f6a..c8d3c379d 100644 --- a/OpenUtau/Controls/NotePropertyExpression.axaml.cs +++ b/OpenUtau/Controls/NotePropertyExpression.axaml.cs @@ -14,48 +14,39 @@ public NotePropertyExpression() { slider.AddHandler(PointerPressedEvent, SliderPointerPressed, RoutingStrategies.Tunnel); slider.AddHandler(PointerReleasedEvent, SliderPointerReleased, RoutingStrategies.Tunnel); slider.AddHandler(PointerMovedEvent, SliderPointerMoved, RoutingStrategies.Tunnel); + comboBox.AddHandler(PointerPressedEvent, OnComboBoxPointerPressed, RoutingStrategies.Tunnel); } + // textbox private string textBoxValue = string.Empty; void OnTextBoxGotFocus(object? sender, GotFocusEventArgs args) { Log.Debug("Note property textbox got focus"); - if (sender is TextBox text) { - textBoxValue = text.Text ?? string.Empty; + if (sender is TextBox textBox) { + textBoxValue = textBox.Text ?? string.Empty; } } void OnTextBoxLostFocus(object? sender, RoutedEventArgs args) { Log.Debug("Note property textbox lost focus"); if (sender is TextBox textBox && textBoxValue != textBox.Text) { - if (DataContext is NotePropertyExpViewModel ViewModel) { - DocManager.Inst.StartUndoGroup(); - NotePropertiesViewModel.PanelControlPressed = true; - ViewModel.SetNumericalExpressions(textBox.Text); - NotePropertiesViewModel.PanelControlPressed = false; - DocManager.Inst.EndUndoGroup(); - } + SetNumericalExpressions(textBox.Text); } } + // slider void SliderPointerPressed(object? sender, PointerPressedEventArgs args) { - Log.Debug("Slider pressed"); + Log.Debug("Note property slider pressed"); if (sender is Control control) { var point = args.GetCurrentPoint(control); if (point.Properties.IsLeftButtonPressed) { DocManager.Inst.StartUndoGroup(); NotePropertiesViewModel.PanelControlPressed = true; } else if (point.Properties.IsRightButtonPressed) { - if (DataContext is NotePropertyExpViewModel ViewModel) { - DocManager.Inst.StartUndoGroup(); - NotePropertiesViewModel.PanelControlPressed = true; - ViewModel.SetNumericalExpressions(null); - NotePropertiesViewModel.PanelControlPressed = false; - DocManager.Inst.EndUndoGroup(); - } + SetNumericalExpressions(null); } } } void SliderPointerReleased(object? sender, PointerReleasedEventArgs args) { - Log.Debug("Slider released"); + Log.Debug("Note property slider released"); if (NotePropertiesViewModel.PanelControlPressed) { if (sender is Slider slider && DataContext is NotePropertyExpViewModel ViewModel) { ViewModel.SetNumericalExpressions((float)slider.Value); @@ -69,5 +60,26 @@ void SliderPointerMoved(object? sender, PointerEventArgs args) { ViewModel.SetNumericalExpressions((float)slider.Value); } } + + void OnComboBoxPointerPressed(object? sender, PointerPressedEventArgs args) { + Log.Debug("Note property textbox pressed"); + if (sender is ComboBox comboBox) { + var point = args.GetCurrentPoint(comboBox); + if (point.Properties.IsRightButtonPressed) { + SetNumericalExpressions(null); + args.Handled = true; + } + } + } + + private void SetNumericalExpressions(string? expression) { + if (DataContext is NotePropertyExpViewModel viewModel) { + DocManager.Inst.StartUndoGroup(); + NotePropertiesViewModel.PanelControlPressed = true; + viewModel.SetNumericalExpressions(expression); + NotePropertiesViewModel.PanelControlPressed = false; + DocManager.Inst.EndUndoGroup(); + } + } } } diff --git a/OpenUtau/ViewModels/NotePropertiesViewModel.cs b/OpenUtau/ViewModels/NotePropertiesViewModel.cs index 6306394c5..c46ad3431 100644 --- a/OpenUtau/ViewModels/NotePropertiesViewModel.cs +++ b/OpenUtau/ViewModels/NotePropertiesViewModel.cs @@ -189,7 +189,7 @@ private void AttachExpressions() { foreach (NotePropertyExpViewModel exp in Expressions) { exp.IsNoteSelected = true; - var phonemeExpression = note.phonemeExpressions.FirstOrDefault(e => e.abbr == exp.abbr); + var phonemeExpression = note.phonemeExpressions.FirstOrDefault(e => e.abbr == exp.abbr && e.index == 0); if (phonemeExpression != null) { if (exp.IsNumerical) { exp.Value = phonemeExpression.value; @@ -470,12 +470,18 @@ public void SetVibratoEnable() { public void SetNumericalExpressionsChanges(string abbr, float? value) { if (AllowNoteEdit && Part != null && selectedNotes.Count > 0) { var track = DocManager.Inst.Project.tracks[Part.trackNo]; + if (track.TryGetExpression(DocManager.Inst.Project, abbr, out UExpression expression) && expression.value == value) { + value = null; + } DocManager.Inst.ExecuteCmd(new SetNotesSameExpressionCommand(DocManager.Inst.Project, track, Part, selectedNotes, abbr, value)); } } public void SetOptionalExpressionsChanges(string abbr, int? value) { if (!NoteLoading && Part != null && selectedNotes.Count > 0) { var track = DocManager.Inst.Project.tracks[Part.trackNo]; + if (track.TryGetExpression(DocManager.Inst.Project, abbr, out UExpression expression) && expression.value == value) { + value = null; + } DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new SetNotesSameExpressionCommand(DocManager.Inst.Project, track, Part, selectedNotes, abbr, value)); DocManager.Inst.EndUndoGroup();