Skip to content

Commit

Permalink
Merge pull request #1142 from maiko3tattun/240514_DrawPitchToolV3
Browse files Browse the repository at this point in the history
Add Overwrite Pitch Tool
  • Loading branch information
stakira authored Jun 9, 2024
2 parents c7cba6e + be90b13 commit 447ec87
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 5 deletions.
6 changes: 6 additions & 0 deletions OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ Warning: this option removes custom presets.</system:String>
Hold Alt to smoothen</system:String>
<system:String x:Key="pianoroll.tool.eraser">Eraser Tool (3)</system:String>
<system:String x:Key="pianoroll.tool.knife">Knife Tool (5)</system:String>
<system:String x:Key="pianoroll.tool.overwritepitch">Overwrite Pitch Tool (Ctrl + 4)
Left click to draw (overwrites vibrato or mod+)
Right click to reset
Hold Ctrl to select
Hold Alt to smoothen
</system:String>
<system:String x:Key="pianoroll.tool.penplus">Pen Plus Tool (Ctrl + 2)
Left click to draw
Right click to delete
Expand Down
6 changes: 6 additions & 0 deletions OpenUtau/Strings/Strings.ja-JP.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@
Alt長押しで線をなめらかにする</system:String>
<system:String x:Key="pianoroll.tool.eraser">消しゴムツール (3)</system:String>
<system:String x:Key="pianoroll.tool.knife">ナイフツール (5)</system:String>
<system:String x:Key="pianoroll.tool.overwritepitch">ピッチ上書きツール (Ctrl + 4)
左クリックで描画(ビブラートやMOD+を上書き)
右クリックでリセット
Ctrl長押しで選択
Alt長押しで線をなめらかにする
</system:String>
<system:String x:Key="pianoroll.tool.penplus">ペン+ツール (Ctrl + 2)
左クリックで描画
右クリックで削除
Expand Down
3 changes: 3 additions & 0 deletions OpenUtau/ViewModels/NotesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class NotesViewModel : ViewModelBase, ICmdSubscriber {
[Reactive] public bool PenPlusTool { get; set; }
[Reactive] public bool EraserTool { get; set; }
[Reactive] public bool DrawPitchTool { get; set; }
[Reactive] public bool OverwritePitchTool { get; set; }
[Reactive] public bool KnifeTool { get; set; }
public ReactiveCommand<string, Unit> SelectToolCommand { get; }
[Reactive] public bool ShowTips { get; set; }
Expand Down Expand Up @@ -203,13 +204,15 @@ public NotesViewModel() {
}
EraserTool = false;
DrawPitchTool = false;
OverwritePitchTool = false;
KnifeTool = false;
SelectToolCommand = ReactiveCommand.Create<string>(index => {
CursorTool = index == "1";
PenTool = index == "2";
PenPlusTool = index == "2+";
EraserTool = index == "3";
DrawPitchTool = index == "4";
OverwritePitchTool = index == "4+";
KnifeTool = index == "5";
});

Expand Down
18 changes: 18 additions & 0 deletions OpenUtau/ViewModels/NotesViewModelHitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,24 @@ public PitchPointHitInfo HitTestPitchPoint(Point point) {
return pitch;
}

public double? SampleOverwritePitch(Point point) {
if (viewModel.Part == null || viewModel.Part.renderPhrases.Count == 0) {
return null;
}
double tick = viewModel.PointToTick(point);
var phrase = viewModel.Part.renderPhrases.FirstOrDefault(p => p.position - p.leading >= tick);
if (phrase == null) {
phrase = viewModel.Part.renderPhrases.Last();
}
if (phrase == null || phrase.pitchesBeforeDeviation.Length == 0) {
return null;
}
var curve = phrase.pitchesBeforeDeviation;
var pitchIndex = (int)Math.Round((tick - phrase.position + phrase.leading) / 5);
pitchIndex = Math.Clamp(pitchIndex, 0, curve.Length - 1);
return curve[pitchIndex];
}

public VibratoHitInfo HitTestVibrato(Point mousePos) {
if (viewModel.Part == null || !viewModel.ShowVibrato) {
return default;
Expand Down
35 changes: 35 additions & 0 deletions OpenUtau/Views/NoteEditStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,41 @@ public override void Update(IPointer pointer, Point point) {
}
}

class OverwritePitchState : NoteEditState {
protected override bool ShowValueTip => false;
double? lastPitch;
Point lastPoint;
public OverwritePitchState(
Control control,
PianoRollViewModel vm,
IValueTip valueTip) : base(control, vm, valueTip) { }
public override void Begin(IPointer pointer, Point point) {
base.Begin(pointer, point);
lastPoint = point;
}
public override void Update(IPointer pointer, Point point) {
int tick = vm.NotesViewModel.PointToTick(point);
var samplePoint = vm.NotesViewModel.TickToneToPoint(
(int)Math.Round(tick / 5.0) * 5,
vm.NotesViewModel.PointToToneDouble(point));
double? pitch = vm.NotesViewModel.HitTest.SampleOverwritePitch(samplePoint);
if (pitch == null || vm.NotesViewModel.Part == null) {
return;
}
double tone = vm.NotesViewModel.PointToToneDouble(point);
DocManager.Inst.ExecuteCmd(new SetCurveCommand(
vm.NotesViewModel.Project,
vm.NotesViewModel.Part,
Core.Format.Ustx.PITD,
vm.NotesViewModel.PointToTick(point),
(int)Math.Round(tone * 100 - pitch.Value),
vm.NotesViewModel.PointToTick(lastPitch == null ? point : lastPoint),
(int)Math.Round(tone * 100 - (lastPitch ?? pitch.Value))));
lastPitch = pitch;
lastPoint = point;
}
}

class SmoothenPitchState : NoteEditState {
protected override bool ShowValueTip => false;
int brushRadius = 10;
Expand Down
15 changes: 15 additions & 0 deletions OpenUtau/Views/PianoRollWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,21 @@
</Path>
</Grid>
</ToggleButton>
<ToggleButton Classes="toolbar" Margin="0" Padding="1" Height="20" Width="20"
IsChecked="{Binding NotesViewModel.OverwritePitchTool, Mode=OneWay}"
Command="{Binding NotesViewModel.SelectToolCommand}" CommandParameter="4+"
ToolTip.Tip="{DynamicResource pianoroll.tool.overwritepitch}">
<Grid Width="18" Height="18">
<Path Classes="filled" Data="M9.75 20.85C11.53 20.15 11.14 18.22 10.24 17C9.35 15.75 8.12 14.89 6.88 14.06C6 13.5 5.19 12.8 4.54 12C4.26 11.67 3.69 11.06 4.27 10.94C4.86 10.82 5.88 11.4 6.4 11.62C7.31 12 8.21 12.44 9.05 12.96L10.06 11.26C8.5 10.23 6.5 9.32 4.64 9.05C3.58 8.89 2.46 9.11 2.1 10.26C1.78 11.25 2.29 12.25 2.87 13.03C4.24 14.86 6.37 15.74 7.96 17.32C8.3 17.65 8.71 18.04 8.91 18.5C9.12 18.94 9.07 18.97 8.6 18.97C7.36 18.97 5.81 18 4.8 17.36L3.79 19.06C5.32 20 7.88 21.47 9.75 20.85M20.84 5.25C21.06 5.03 21.06 4.67 20.84 4.46L19.54 3.16C19.33 2.95 18.97 2.95 18.76 3.16L17.74 4.18L19.82 6.26M11 10.92V13H13.08L19.23 6.85L17.15 4.77L11 10.92Z" >
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX=".7" ScaleY=".7" />
<TranslateTransform X="-2" Y="-2"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</ToggleButton>
<ToggleButton Classes="toolbar" Margin="0" Padding="1" Height="20" Width="20"
IsChecked="{Binding NotesViewModel.KnifeTool, Mode=OneWay}"
Command="{Binding NotesViewModel.SelectToolCommand}" CommandParameter="5"
Expand Down
19 changes: 14 additions & 5 deletions OpenUtau/Views/PianoRollWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,13 +400,17 @@ public void NotesCanvasPointerPressed(object sender, PointerPressedEventArgs arg
}

private void NotesCanvasLeftPointerPressed(Control control, PointerPoint point, PointerPressedEventArgs args) {
if (ViewModel.NotesViewModel.DrawPitchTool) {
if (ViewModel.NotesViewModel.DrawPitchTool || ViewModel.NotesViewModel.OverwritePitchTool) {
ViewModel.NotesViewModel.DeselectNotes();
if (args.KeyModifiers == KeyModifiers.Alt) {
editState = new SmoothenPitchState(control, ViewModel, this);
return;
} else if (args.KeyModifiers != cmdKey) {
editState = new DrawPitchState(control, ViewModel, this);
if (ViewModel.NotesViewModel.DrawPitchTool) {
editState = new DrawPitchState(control, ViewModel, this);
} else {
editState = new OverwritePitchState(control, ViewModel, this);
}
return;
}
}
Expand Down Expand Up @@ -482,7 +486,8 @@ private void NotesCanvasLeftPointerPressed(Control control, PointerPoint point,
if (ViewModel.NotesViewModel.CursorTool ||
ViewModel.NotesViewModel.PenTool && args.KeyModifiers == cmdKey ||
ViewModel.NotesViewModel.PenPlusTool && args.KeyModifiers == cmdKey ||
ViewModel.NotesViewModel.DrawPitchTool && args.KeyModifiers == cmdKey) {
ViewModel.NotesViewModel.DrawPitchTool && args.KeyModifiers == cmdKey ||
ViewModel.NotesViewModel.OverwritePitchTool && args.KeyModifiers == cmdKey) {
if (args.KeyModifiers == KeyModifiers.None) {
// New selection.
ViewModel.NotesViewModel.DeselectNotes();
Expand All @@ -506,7 +511,7 @@ private void NotesCanvasLeftPointerPressed(Control control, PointerPoint point,

private void NotesCanvasRightPointerPressed(Control control, PointerPoint point, PointerPressedEventArgs args) {
var selectedNotes = ViewModel.NotesViewModel.Selection.ToList();
if (ViewModel.NotesViewModel.DrawPitchTool) {
if (ViewModel.NotesViewModel.DrawPitchTool || ViewModel.NotesViewModel.OverwritePitchTool) {
editState = new ResetPitchState(control, ViewModel, this);
return;
}
Expand Down Expand Up @@ -624,7 +629,7 @@ public void NotesCanvasPointerMoved(object sender, PointerEventArgs args) {
if (ViewModel?.NotesViewModel?.HitTest == null) {
return;
}
if((ViewModel.NotesViewModel.DrawPitchTool && args.KeyModifiers != cmdKey) || ViewModel.NotesViewModel.EraserTool) {
if(((ViewModel.NotesViewModel.DrawPitchTool || ViewModel.NotesViewModel.OverwritePitchTool) && args.KeyModifiers != cmdKey) || ViewModel.NotesViewModel.EraserTool) {
Cursor = null;
return;
}
Expand Down Expand Up @@ -1096,6 +1101,10 @@ bool OnKeyExtendedHandler(KeyEventArgs args) {
expSelector4?.SelectExp();
return true;
}
if (isCtrl) {
notesVm.SelectToolCommand?.Execute("4+").Subscribe();
return true;
}
break;
case Key.D5:
if (isNone) {
Expand Down

0 comments on commit 447ec87

Please sign in to comment.