Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion OpenUtau.Core/Editing/LyricBatchEdits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, Do
}
// Determine the character that is the trigger
UTrack track = project.tracks[part.trackNo];
if (track.VoiceColorExp.options.Length <= 0) {
if (track.VoiceColorExp == null || track.VoiceColorExp.options.Length <= 0) {
return;
}
Dictionary<int, string> colors = new Dictionary<int, string>(); // index, trigger
Expand Down
11 changes: 11 additions & 0 deletions OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@
<system:String x:Key="lyrics.reset">Reset</system:String>
<system:String x:Key="lyrics.selectnotes">Select some notes first!</system:String>
<system:String x:Key="lyrics.separators">Separators</system:String>
<system:String x:Key="lyricsreplace.after">After :</system:String>
<system:String x:Key="lyricsreplace.before">Before :</system:String>
<system:String x:Key="lyricsreplace.presets">Presets</system:String>
<system:String x:Key="lyricsreplace.preview">Preview</system:String>
<system:String x:Key="lyricsreplace.regex">Regular expressions can be used</system:String>
<system:String x:Key="lyricsreplace.replace">General lyrics replacement</system:String>
<system:String x:Key="lyricsreplace.preset.rmvalphabet">Remove alphabet</system:String>
<system:String x:Key="lyricsreplace.preset.rmvnonhiragana">Remove non-hiragana</system:String>
<system:String x:Key="lyricsreplace.preset.rmvphonetichint">Remove phonetic hint</system:String>
<system:String x:Key="lyricsreplace.preset.rmvtone">Remove tone suffix</system:String>
<system:String x:Key="lyricsreplace.preset.rmvspace">Remove spaces and earlier</system:String>

<system:String x:Key="menu.edit">Edit</system:String>
<system:String x:Key="menu.edit.copy">Copy</system:String>
Expand Down
11 changes: 11 additions & 0 deletions OpenUtau/Strings/Strings.ja-JP.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@
<system:String x:Key="lyrics.reset">リセット</system:String>
<system:String x:Key="lyrics.selectnotes">音符を選択してください!</system:String>
<system:String x:Key="lyrics.separators">区切り文字</system:String>
<system:String x:Key="lyricsreplace.after">置換後 :</system:String>
<system:String x:Key="lyricsreplace.before">置換前 :</system:String>
<system:String x:Key="lyricsreplace.presets">プリセット</system:String>
<system:String x:Key="lyricsreplace.preview">プレビュー</system:String>
<system:String x:Key="lyricsreplace.regex">正規表現が使えます</system:String>
<system:String x:Key="lyricsreplace.replace">その他の歌詞置換</system:String>
<system:String x:Key="lyricsreplace.preset.rmvalphabet">アルファベットを削除</system:String>
<system:String x:Key="lyricsreplace.preset.rmvnonhiragana">ひらがな以外を削除</system:String>
<system:String x:Key="lyricsreplace.preset.rmvphonetichint">[音素の指定]を削除</system:String>
<system:String x:Key="lyricsreplace.preset.rmvtone">音程のSuffixを削除</system:String>
<system:String x:Key="lyricsreplace.preset.rmvspace">スペースとそれ以前を削除</system:String>

<system:String x:Key="menu.edit">編集</system:String>
<system:String x:Key="menu.edit.copy">コピー</system:String>
Expand Down
90 changes: 90 additions & 0 deletions OpenUtau/ViewModels/LyricsReplaceViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using DynamicData.Binding;
using OpenUtau.Core;
using OpenUtau.Core.Ustx;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace OpenUtau.App.ViewModels {
class LyricsReplaceViewModel : ViewModelBase {
[Reactive] public string OldValue { get; set; } = "";
[Reactive] public string NewValue { get; set; } = "";
[Reactive] public string Preview { get; set; } = "";
public List<ReplacePreset> PresetList { get; } = new List<ReplacePreset>() { //Increase!
new ReplacePreset("-", "", ""),
new ReplacePreset(ThemeManager.GetString("lyricsreplace.preset.rmvalphabet"), @"[a-zA-Z]", ""),
new ReplacePreset(ThemeManager.GetString("lyricsreplace.preset.rmvnonhiragana"), @"[^\p{IsHiragana}ヴ]+", ""),
new ReplacePreset(ThemeManager.GetString("lyricsreplace.preset.rmvphonetichint"), @"\[.*\]", ""),
new ReplacePreset(ThemeManager.GetString("lyricsreplace.preset.rmvtone"), @"_?[A-G](#|b)?[1-7]", ""),
new ReplacePreset(ThemeManager.GetString("lyricsreplace.preset.rmvspace"), ".* ", "")
};
[Reactive] public ReplacePreset SelectedPreset { get; set; } = new ReplacePreset();
public string[] Lyrics { get; private set; }

private UVoicePart part;
private UNote[] notes;
private string[] startLyrics;

public LyricsReplaceViewModel(UVoicePart part, UNote[] notes, string[] lyrics) {
this.part = part;
this.notes = notes;
startLyrics = lyrics.Clone() as string[];
Preview = string.Join(", ", lyrics);
Lyrics = lyrics;

this.WhenAnyValue(x => x.OldValue, x => x.NewValue)
.Subscribe(t => {
Preview = Replace();
});
this.WhenValueChanged(x => SelectedPreset)
.Subscribe(p => {
if (SelectedPreset != null) {
OldValue = SelectedPreset.OldValue;
NewValue = SelectedPreset.NewValue;
}
});
}

public string Replace() {

for (int i = 0; i < startLyrics.Length; i++) {
Lyrics[i] = Regex.Replace(startLyrics[i], OldValue, NewValue);
}
return string.Join(", ", Lyrics);
}

public void Finish() {
DocManager.Inst.StartUndoGroup();

for (int i = 0; i < Lyrics.Length && i < notes.Length; ++i) {
if (notes[i].lyric != Lyrics[i]) {
DocManager.Inst.ExecuteCmd(new ChangeNoteLyricCommand(part, notes[i], Lyrics[i]));
}
}

DocManager.Inst.EndUndoGroup();
}
}

public class ReplacePreset {
public string Name { get; private set; } = "";
public string OldValue { get; private set; } = "";
public string NewValue { get; private set; } = "";

public ReplacePreset() {

}

public ReplacePreset(string name, string oldValue, string newValue) {
Name = name;
OldValue = oldValue;
NewValue = newValue;
}

public override string ToString() {
return Name;
}
}
}
38 changes: 38 additions & 0 deletions OpenUtau/Views/LyricsReplaceDialog.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" MinWidth="200" MinHeight="200" Width="300" Height="350"
x:Class="OpenUtau.App.Views.LyricsReplaceDialog" WindowStartupLocation="CenterOwner"
Icon="/Assets/open-utau.ico"
Title="{StaticResource lyricsreplace.replace}">
<Grid Margin="10" RowDefinitions="auto,10,Auto,10,Auto,10,*,10,Auto">
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="{StaticResource lyricsreplace.before}" />
<TextBox Text="{Binding OldValue}" MinWidth="200" Margin="10,0"
Watermark="{StaticResource lyricsreplace.regex}"/>
</StackPanel>

<StackPanel Orientation="Horizontal" Grid.Row="2">
<TextBlock Text="{StaticResource lyricsreplace.after}" />
<TextBox Text="{Binding NewValue}" MinWidth="200" Margin="10,0" />
</StackPanel>

<StackPanel Grid.Row="4">
<TextBlock Text="{StaticResource lyricsreplace.preview}" />
<TextBlock Text="{Binding Preview}" Margin="5" MinHeight="15" />
</StackPanel>

<StackPanel Grid.Row="6">
<TextBlock Text="{StaticResource lyricsreplace.presets}" />
<ListBox Items="{Binding PresetList}"
SelectedItem="{Binding SelectedPreset}"
SelectionMode="Single" Margin="5" />
</StackPanel>

<StackPanel Grid.Row="8" Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
<!-- <Button Content="{StaticResource lyrics.cancel}" Margin="0" Click="OnCancel"/>-->
<Button Content="{StaticResource lyrics.apply}" Margin="0" MinWidth="50" Click="OnFinish"/>
</StackPanel>
</Grid>
</Window>
48 changes: 48 additions & 0 deletions OpenUtau/Views/LyricsReplaceDialog.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using OpenUtau.App.ViewModels;

namespace OpenUtau.App.Views {
public partial class LyricsReplaceDialog : Window {

public LyricsReplaceDialog() {
InitializeComponent();

#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent() {
AvaloniaXamlLoader.Load(this);
}

void OnCancel(object? sender, RoutedEventArgs e) {
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, KeyModifiers.None);
Close();
}

void OnFinish(object? sender, RoutedEventArgs e) {
(DataContext as LyricsReplaceViewModel)!.Finish();
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, KeyModifiers.None);
Close();
}

private void OnKeyDown(object? sender, KeyEventArgs e) {
switch (e.Key) {
case Key.Enter:
OnFinish(sender, e);
e.Handled = true;
break;
case Key.Escape:
OnCancel(sender, e);
e.Handled = true;
break;
default:
break;
}
}
}
}
23 changes: 23 additions & 0 deletions OpenUtau/Views/PianoRollWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public PianoRollWindow() {
#endif
DataContext = ViewModel = new PianoRollViewModel();

ViewModel.LyricBatchEdits.Add(new MenuItemViewModel() {
Header = ThemeManager.GetString("lyricsreplace.replace"),
Command = ReactiveCommand.Create(() => {
ReplaceLyrics();
})
});
lyricsDialogCommand = ReactiveCommand.Create(() => {
EditLyrics();
});
Expand Down Expand Up @@ -95,6 +101,23 @@ void OnMenuPointerLeave(object sender, PointerEventArgs args) {
Focus(); // Force unfocus menu for key down events.
}

void ReplaceLyrics() {
if (ViewModel.NotesViewModel.Selection.IsEmpty) {
_ = MessageBox.Show(
this,
ThemeManager.GetString("lyrics.selectnotes"),
ThemeManager.GetString("lyrics.caption"),
MessageBox.MessageBoxButtons.Ok);
return;
}
var (notes, lyrics) = ViewModel.NotesViewModel.PrepareInsertLyrics();
var vm = new LyricsReplaceViewModel(ViewModel.NotesViewModel.Part, notes, lyrics);
var dialog = new LyricsReplaceDialog() {
DataContext = vm,
};
dialog.ShowDialog(this);
}

void OnMenuEditLyrics(object? sender, RoutedEventArgs e) {
EditLyrics();
}
Expand Down