Skip to content
Open
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: 2 additions & 0 deletions OpenUtau.Core/Classic/ClassicSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class ClassicSinger : USinger {
public override string Portrait => voicebank.Portrait == null ? null : Path.Combine(Location, voicebank.Portrait);
public override float PortraitOpacity => voicebank.PortraitOpacity;
public override int PortraitHeight => voicebank.PortraitHeight;
public override int PortraitHeightCap => voicebank.PortraitHeightCap;
public override int PortraitPosition => voicebank.PortraitPosition;
public override string DefaultPhonemizer => voicebank.DefaultPhonemizer;
public override string Sample => voicebank.Sample == null ? null : Path.Combine(Location, voicebank.Sample);
public override Encoding TextFileEncoding => voicebank.TextFileEncoding;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Classic/VoiceBank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class Voicebank {
public string Portrait;
public float PortraitOpacity;
public int PortraitHeight;
public int PortraitHeightCap;
public int PortraitPosition;
public string Author;
public string Voice;
public string Web;
Expand Down
4 changes: 3 additions & 1 deletion OpenUtau.Core/Classic/VoicebankConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ public class VoicebankConfig {
public string TextFileEncoding;
public string Image;
public string Portrait;
public float PortraitOpacity = 0.67f;
public int PortraitHeight = 0;
public float PortraitOpacity = 0;
public int PortraitHeightCap = 0;
public int PortraitPosition = -1;
public string Author;
public string Voice;
public string Web;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Classic/VoicebankLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ public static void ApplyConfig(Voicebank bank, VoicebankConfig bankConfig) {
bank.Portrait = bankConfig.Portrait;
bank.PortraitOpacity = bankConfig.PortraitOpacity;
bank.PortraitHeight = bankConfig.PortraitHeight;
bank.PortraitHeightCap = bankConfig.PortraitHeightCap;
bank.PortraitPosition = bankConfig.PortraitPosition;
}
if (!string.IsNullOrWhiteSpace(bankConfig.Author)) {
bank.Author = bankConfig.Author;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/DiffSinger/DiffSingerSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class DiffSingerSinger : USinger {
public override string Portrait => voicebank.Portrait == null ? null : Path.Combine(Location, voicebank.Portrait);
public override float PortraitOpacity => voicebank.PortraitOpacity;
public override int PortraitHeight => voicebank.PortraitHeight;
public override int PortraitHeightCap => voicebank.PortraitHeightCap;
public override int PortraitPosition => voicebank.PortraitPosition;
public override string Sample => voicebank.Sample == null ? null : Path.Combine(Location, voicebank.Sample);
public override string DefaultPhonemizer => voicebank.DefaultPhonemizer;
public override Encoding TextFileEncoding => voicebank.TextFileEncoding;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Enunu/EnunuSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class EnunuSinger : USinger {
public override string Portrait => voicebank.Portrait == null ? null : Path.Combine(Location, voicebank.Portrait);
public override float PortraitOpacity => voicebank.PortraitOpacity;
public override int PortraitHeight => voicebank.PortraitHeight;
public override int PortraitHeightCap => voicebank.PortraitHeightCap;
public override int PortraitPosition => voicebank.PortraitPosition;
public override string Sample => voicebank.Sample == null ? null : Path.Combine(Location, voicebank.Sample);
public override string DefaultPhonemizer => voicebank.DefaultPhonemizer;
public override Encoding TextFileEncoding => voicebank.TextFileEncoding;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Ustx/USinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ public class USinger : INotifyPropertyChanged, IEquatable<USinger> {
public virtual string Portrait { get; }
public virtual float PortraitOpacity { get; }
public virtual int PortraitHeight { get; }
public virtual int PortraitHeightCap { get; }
public virtual int PortraitPosition { get; }
public virtual string Sample { get; }
public virtual string DefaultPhonemizer { get; }
public virtual Encoding TextFileEncoding => Encoding.UTF8;
Expand Down
3 changes: 3 additions & 0 deletions OpenUtau.Core/Util/Preferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ public class SerializablePreferences {
";
public string RecoveryPath = string.Empty;
public bool DetachPianoRoll = false;
public int PortraitHeightCap = 80;
public int PortraitPosition = 30;
public float PortraitOpacity = 0.67f;
}
}
}
2 changes: 2 additions & 0 deletions OpenUtau.Core/Vogen/VogenSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class VogenSinger : USinger {
public override string Portrait => meta.portrait;
public override float PortraitOpacity => meta.portraitOpacity;
public override int PortraitHeight => meta.portraitHeight;
public override int PortraitHeightCap => meta.portraitHeightCap;
public override int PortraitPosition => meta.portraitPosition;
public override string DefaultPhonemizer => "OpenUtau.Core.Vogen.VogenMandarinPhonemizer";
public override Encoding TextFileEncoding => Encoding.UTF8;
public override IList<USubbank> Subbanks => subbanks;
Expand Down
4 changes: 3 additions & 1 deletion OpenUtau.Core/Vogen/VogenSingerLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ class VogenMeta {
public string voiceBy;
public string avatar;
public string portrait;
public float portraitOpacity = 0.67f;
public float portraitOpacity = 0;
public int portraitHeight = 0;
public int portraitHeightCap = 0;
public int portraitPosition = 0;
public string web;
public string misc;
}
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Voicevox/VoicevoxSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class VoicevoxSinger : USinger {
public override string Portrait => voicebank.Portrait == null ? voicevoxConfig == null ? null : voicevoxConfig.portraitPath == null ? null : voicevoxConfig.style_infos[0].portrait : Path.Combine(Location, voicebank.Portrait);
public override float PortraitOpacity => voicebank.PortraitOpacity;
public override int PortraitHeight => voicebank.PortraitHeight;
public override int PortraitHeightCap => voicebank.PortraitHeightCap;
public override int PortraitPosition => voicebank.PortraitPosition;
public override string Sample => voicebank.Sample == null ? null : Path.Combine(Location, voicebank.Sample);
public override string DefaultPhonemizer => voicebank.DefaultPhonemizer;
public override Encoding TextFileEncoding => voicebank.TextFileEncoding;
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Test/Classic/VoicebankConfigTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ static VoicebankConfig CreateConfig() {
return new VoicebankConfig() {
PortraitOpacity = 0.75f,
PortraitHeight = 675,
PortraitHeightCap = 80,
PortraitPosition = 30,
Sample = "sample.wav",
SymbolSet = new SymbolSet() {
Preset = SymbolSetPreset.hiragana,
Expand Down
7 changes: 4 additions & 3 deletions OpenUtau/Controls/PianoRoll.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@
SnapDiv="{Binding NotesViewModel.SnapDiv, Mode=OneWay}"
SnapTicks="{Binding NotesViewModel.SnapTicks}"
ShowBarNumber="True"/>
<Image Grid.Row="3" Grid.RowSpan="3" Grid.Column="1" HorizontalAlignment="Right" Margin="0,10,10,10"
MaxHeight="{Binding NotesViewModel.Portrait.Size.Height}"
Source="{Binding NotesViewModel.Portrait}" OpacityMask="{Binding NotesViewModel.PortraitMask}" Stretch="Uniform"/>
<Viewbox Grid.Row="3" Grid.RowSpan="3" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,100,0">
<Image HorizontalAlignment="Right" Source="{Binding NotesViewModel.Portrait}" Stretch="None"
OpacityMask="{Binding NotesViewModel.PortraitMask}" Margin="{Binding NotesViewModel.PortraitMargin}"/>
</Viewbox>
<Border Grid.Row="3" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Margin="0,0,0,60" Height="60" IsHitTestVisible="False">
<c:WaveformImage DataContext="{Binding NotesViewModel, Mode=OneWay}"
Expand Down
3 changes: 3 additions & 0 deletions OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,9 @@ Warning: this option removes custom presets.</system:String>
<system:String x:Key="prefs.appearance.showicon">Show icon on piano roll</system:String>
<system:String x:Key="prefs.appearance.showportrait">Show portrait on piano roll</system:String>
<system:String x:Key="prefs.appearance.sortorder">Singer name display language</system:String>
<system:String x:Key="prefs.appearance.defaultportraitheightcap">Default portrait height cap</system:String>
<system:String x:Key="prefs.appearance.defaultportraitposition">Default portrait position</system:String>
<system:String x:Key="prefs.appearance.defaultportraitopacity">Default portrait opacity</system:String>
<system:String x:Key="prefs.appearance.theme">Theme</system:String>
<system:String x:Key="prefs.appearance.theme.dark">Dark</system:String>
<system:String x:Key="prefs.appearance.theme.light">Light</system:String>
Expand Down
29 changes: 28 additions & 1 deletion OpenUtau/ViewModels/NotesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class NotesViewModel : ViewModelBase, ICmdSubscriber {
[Reactive] public Bitmap? Avatar { get; set; }
[Reactive] public Bitmap? Portrait { get; set; }
[Reactive] public IBrush? PortraitMask { get; set; }
[Reactive] public Thickness PortraitMargin { get; set; }
[Reactive] public string WindowTitle { get; set; } = "Piano Roll";
[Reactive] public SolidColorBrush TrackAccentColor { get; set; } = ThemeManager.GetTrackColor("Blue").AccentColor;
public double ViewportTicks => viewportTicks.Value;
Expand All @@ -96,6 +97,7 @@ public class NotesViewModel : ViewModelBase, ICmdSubscriber {
public double HScrollBarMax => Math.Max(0, TickCount - ViewportTicks);
public double VScrollBarMax => Math.Max(0, TrackCount - ViewportTracks);
public UProject Project => DocManager.Inst.Project;
public USinger? Singer => Part != null ? Project.tracks[Part.trackNo].Singer : null;
[Reactive] public List<MenuItemViewModel> SnapDivs { get; set; }
[Reactive] public List<MenuItemViewModel> Keys { get; set; }

Expand Down Expand Up @@ -316,6 +318,12 @@ public NotesViewModel() {
case "Portrait":
LoadPortrait(Part, Project);
break;
case "PortraitHeight":
UpdatePortraitHeight();
break;
case "PortraitOpacity":
UpdatePortraitOpacity();
break;
case "TrackColor":
LoadTrackColor(Part, Project);
break;
Expand All @@ -332,6 +340,21 @@ public NotesViewModel() {
});
}

private void UpdatePortraitHeight() {
if (Preferences.Default.ShowPortrait && Singer != null && Portrait != null) {
double cap = 1 - ((double) (Singer.PortraitHeightCap > 0 ? Singer.PortraitHeightCap : Preferences.Default.PortraitHeightCap) / 100);
double pos = (double) (Singer.PortraitPosition > -1 ? Singer.PortraitPosition : Preferences.Default.PortraitPosition) / 100;
double margin = Portrait.Size.Height * cap;
PortraitMargin = new(0, margin * pos, 0, margin * (1 - pos));
}
}

private void UpdatePortraitOpacity() {
if (Singer?.PortraitOpacity <= 0) {
PortraitMask = new SolidColorBrush(Avalonia.Media.Colors.White, Preferences.Default.PortraitOpacity);
}
}

private void UpdateSnapDiv() {
if (userSnapDiv > 0) {
SnapDiv = userSnapDiv;
Expand Down Expand Up @@ -531,7 +554,10 @@ private void LoadPortrait(UPart? part, UProject? project) {
Portrait = null;
portraitSource = null;
}
PortraitMask = new SolidColorBrush(Avalonia.Media.Colors.White, singer.PortraitOpacity);
var opacity = singer.PortraitOpacity <= 0
? Preferences.Default.PortraitOpacity
: singer.PortraitOpacity;
PortraitMask = new SolidColorBrush(Avalonia.Media.Colors.White, opacity);
Task.Run(() => {
lock (portraitLock) {
try {
Expand All @@ -544,6 +570,7 @@ private void LoadPortrait(UPart? part, UProject? project) {
Portrait = ResizePortrait(new Bitmap(stream), singer.PortraitHeight);
portraitSource = singer.Portrait;
}
UpdatePortraitHeight();
}
} catch (Exception e) {
Portrait?.Dispose();
Expand Down
23 changes: 23 additions & 0 deletions OpenUtau/ViewModels/PreferencesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ public int SafeMaxThreadCount {
[Reactive] public bool UseTrackColor { get; set; }
[Reactive] public bool ShowPortrait { get; set; }
[Reactive] public int PortraitHeightCap { get; set; }
[Reactive] public int PortraitPosition { get; set; }
[Reactive] public float PortraitOpacity { get; set; }
[Reactive] public bool ShowIcon { get; set; }
[Reactive] public bool ShowGhostNotes { get; set; }
[Reactive] public bool ThemeEditable { get; set; }
Expand Down Expand Up @@ -190,6 +192,9 @@ public PreferencesViewModel() {
RememberUst = Preferences.Default.RememberUst;
RememberVsqx = Preferences.Default.RememberVsqx;
ClearCacheOnQuit = Preferences.Default.ClearCacheOnQuit;
PortraitHeightCap = Preferences.Default.PortraitHeightCap;
PortraitPosition = Preferences.Default.PortraitPosition;
PortraitOpacity = Preferences.Default.PortraitOpacity;

MessageBus.Current.Listen<ThemeEditorStateChangedEvent>()
.Subscribe(_ => this.RaisePropertyChanged(nameof(IsThemeEditorOpen)));
Expand Down Expand Up @@ -284,6 +289,24 @@ public PreferencesViewModel() {
Preferences.Save();
MessageBus.Current.SendMessage(new PianorollRefreshEvent("Portrait"));
});
this.WhenAnyValue(vm => vm.PortraitHeightCap)
.Subscribe(portraitHeightCap => {
Preferences.Default.PortraitHeightCap = portraitHeightCap;
Preferences.Save();
MessageBus.Current.SendMessage(new PianorollRefreshEvent("PortraitHeight"));
});
this.WhenAnyValue(vm => vm.PortraitPosition)
.Subscribe(portraitPosition => {
Preferences.Default.PortraitPosition = portraitPosition;
Preferences.Save();
MessageBus.Current.SendMessage(new PianorollRefreshEvent("PortraitHeight"));
});
this.WhenAnyValue(vm => vm.PortraitOpacity)
.Subscribe(portraitOpacity => {
Preferences.Default.PortraitOpacity = portraitOpacity;
Preferences.Save();
MessageBus.Current.SendMessage(new PianorollRefreshEvent("PortraitOpacity"));
});
this.WhenAnyValue(vm => vm.ShowIcon)
.Subscribe(showIcon => {
Preferences.Default.ShowIcon = showIcon;
Expand Down
18 changes: 15 additions & 3 deletions OpenUtau/Views/PreferencesDialog.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,24 @@
<TextBlock Text="{DynamicResource prefs.appearance.showportrait}" HorizontalAlignment="Left"/>
<ToggleSwitch IsChecked="{Binding ShowPortrait}"/>
</Grid>
<Grid Margin="0,5,0,0" ColumnDefinitions="Auto,8,24,8,*">
<TextBlock Grid.Column="0" Text="Potrait size cap (window height %)" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="2" Text="{Binding PortraitHeightCap}" HorizontalAlignment="Center" />
<Grid Margin="0,5,0,0" ColumnDefinitions="Auto,*,40,8,125">
<TextBlock Grid.Column="0" Text="{DynamicResource prefs.appearance.defaultportraitheightcap}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="2" Text="{Binding PortraitHeightCap, StringFormat='{}{0}%'}" HorizontalAlignment="Center" />
<Slider Grid.Column="4" Classes="fader" Value="{Binding PortraitHeightCap}" Minimum="1" Maximum="100"
IsEnabled="{Binding ShowPortrait}"/>
</Grid>
<Grid Margin="0,5,0,0" ColumnDefinitions="Auto,*,40,8,125">
<TextBlock Grid.Column="0" Text="{DynamicResource prefs.appearance.defaultportraitposition}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="2" Text="{Binding PortraitPosition, StringFormat='{}{0}%'}" HorizontalAlignment="Center" />
<Slider Grid.Column="4" Classes="fader" Value="{Binding PortraitPosition}" Minimum="0" Maximum="100"
IsEnabled="{Binding ShowPortrait}"/>
</Grid>
<Grid Margin="0,5,0,0" ColumnDefinitions="Auto,*,40,8,125">
<TextBlock Grid.Column="0" Text="{DynamicResource prefs.appearance.defaultportraitopacity}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="2" Text="{Binding PortraitOpacity, StringFormat={}{0:0.00}}" HorizontalAlignment="Center" />
<Slider Grid.Column="4" Classes="fader" Value="{Binding PortraitOpacity}" Minimum="0" Maximum="1"
SmallChange="0.01" IsEnabled="{Binding ShowPortrait}"/>
</Grid>
<Grid Margin="0,5,0,0">
<TextBlock Text="{DynamicResource prefs.appearance.showicon}" HorizontalAlignment="Left"/>
<ToggleSwitch IsChecked="{Binding ShowIcon}"/>
Expand Down