diff --git a/.gitignore b/.gitignore
index 80c9c10a6..ba86bc667 100644
--- a/.gitignore
+++ b/.gitignore
@@ -340,3 +340,6 @@ appcast.*.xml
*.tar.gz
.vscode/
Microsoft.AI.DirectML
+
+# VS Code extensions autogen
+*.csproj.lscache
\ No newline at end of file
diff --git a/OpenUtau/Colors/CustomTheme.axaml b/OpenUtau/Colors/CustomTheme.axaml
index 7342a1b14..6479f8b79 100644
--- a/OpenUtau/Colors/CustomTheme.axaml
+++ b/OpenUtau/Colors/CustomTheme.axaml
@@ -45,4 +45,9 @@
#FF71A3
#FF347C
#FFFFFF
+
+
+ False
+ #4EA6EA
+ #FF347C
diff --git a/OpenUtau/Colors/CustomTheme.axaml.cs b/OpenUtau/Colors/CustomTheme.axaml.cs
index f889431a8..c82ac9284 100644
--- a/OpenUtau/Colors/CustomTheme.axaml.cs
+++ b/OpenUtau/Colors/CustomTheme.axaml.cs
@@ -154,7 +154,7 @@ public class ThemeYaml {
public string WhiteKeyColorLeft = "Transparent";
public string WhiteKeyColorRight = "Transparent";
- public string WhiteKeyNameColor = "#FF347c";
+ public string WhiteKeyNameColor = "#FF347C";
public string CenterKeyColorLeft = "#FFDDE6";
public string CenterKeyColorRight = "#FFCEDC";
@@ -163,6 +163,11 @@ public class ThemeYaml {
public string BlackKeyColorLeft = "#FF71A3";
public string BlackKeyColorRight = "#FF347C";
public string BlackKeyNameColor = "#FFFFFF";
+
+ public string MainColorA = "#4EA6EA";
+ public string MainColorB = "#FF347C";
+ public bool IsDarkModeEasy = false;
+
}
}
diff --git a/OpenUtau/Colors/LightTheme.axaml b/OpenUtau/Colors/LightTheme.axaml
index ff064d0d2..c8a6a0e90 100644
--- a/OpenUtau/Colors/LightTheme.axaml
+++ b/OpenUtau/Colors/LightTheme.axaml
@@ -38,7 +38,7 @@
Transparent
Transparent
- #FF347c
+ #FF347C
#FFDDE6
#FFCEDC
diff --git a/OpenUtau/Strings/Strings.axaml b/OpenUtau/Strings/Strings.axaml
index bfc779b45..168cdf084 100644
--- a/OpenUtau/Strings/Strings.axaml
+++ b/OpenUtau/Strings/Strings.axaml
@@ -158,6 +158,11 @@ Do you want to continue by splitting at the nearest position after current playh
Max Batch Duration (s)
One or more audio segments are very long and may consume large amount of memory when transcribing. This usually happens when the audio contains accompaniment. Still proceed?
+ Is Dark Mode
+ Main Color A
+ Main Color B
+ Switch to Accurate Mode
+
Error
Error Details
Error loading vocoder "{0}". Please download vocoder from {1}
@@ -578,6 +583,7 @@ Warning: this option removes custom presets.
Dark
Light
Edit Custom Theme
+ Edit Custom Theme Colorsets
Delete Custom Theme
Are you sure you want to delete this theme?
Create Custom Theme
@@ -744,7 +750,42 @@ The voicebank may not work on another OS.
Choose an encoding that make file contents look right.
Singer Setup
+ Accent Color 1
+ Accent Color 2
+ Accent Color 3
+ Background Color
+ Background Color Disabled
+ Background Color Pointer Over
+ Background Color Pressed
+ Bar Number Color
+ Black Key Color Left
+ Black Key Color Right
+ Black Key Name Color
+ Border Color
+ Border Color Pointer Over
+ Cancel
+ Center Key Color Left
+ Center Key Color Right
+ Center Key Name Color
+ Final Pitch Color
+ Foreground Color
+ Foreground Color Disabled
+ Foreground Color Pointer Over
+ Foreground Color Pressed
+ Is Darkmode
+ Neutral Accent Color
+ Neutral Accent Color Pointer Over
+ Save
+ Switch to Easy Modemer
+ System Accent Color
+ System Accent Color Light
+ System Accent Color Dark
+ Track Background Alt Color
+ Tick Line Color
Theme Editor
+ White Key Color Left
+ White Key Color Right
+ White Key Name Color
Override Alias
Numerical,Options Type
diff --git a/OpenUtau/ViewModels/ThemeEditorViewModel.cs b/OpenUtau/ViewModels/ThemeEditorViewModel.cs
index dd0dc0fd2..41cb5d340 100644
--- a/OpenUtau/ViewModels/ThemeEditorViewModel.cs
+++ b/OpenUtau/ViewModels/ThemeEditorViewModel.cs
@@ -2,13 +2,14 @@
using System.IO;
using System.Text;
using Avalonia;
+using Avalonia.Markup.Xaml.Templates;
using Avalonia.Media;
using Avalonia.Styling;
+using OpenUtau.Colors;
using OpenUtau.Core;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Serilog;
-using OpenUtau.Colors;
namespace OpenUtau.App.ViewModels {
public class ThemeEditorStateChangedEvent { }
@@ -59,6 +60,12 @@ public class ThemeEditorViewModel : ViewModelBase {
[Reactive] public Color BlackKeyColorRight { get; set; }
[Reactive] public Color BlackKeyNameColor { get; set; }
+ [Reactive] public Color MainColorA { get; set; }
+ [Reactive] public Color MainColorB { get; set; }
+ [Reactive] public bool IsDarkModeEasy { get; set; }
+
+ [Reactive] public bool IsEasyMode { get; set; } = true;
+
public ThemeEditorViewModel(string customThemePath) {
this.customThemePath = customThemePath;
@@ -110,6 +117,10 @@ public ThemeEditorViewModel(string customThemePath) {
BlackKeyColorRight = Color.Parse(themeYaml.BlackKeyColorRight);
BlackKeyNameColor = Color.Parse(themeYaml.BlackKeyNameColor);
+ MainColorA = Color.Parse(themeYaml.MainColorA);
+ MainColorB = Color.Parse(themeYaml.MainColorB);
+ IsDarkModeEasy = themeYaml.IsDarkModeEasy;
+
this.WhenAnyValue(vm => vm.IsDarkMode)
.Subscribe(v => {
Application.Current!.Resources["IsDarkMode"] = v;
@@ -121,6 +132,13 @@ public ThemeEditorViewModel(string customThemePath) {
ThemeManager.LoadTheme();
});
+
+ this.WhenAnyValue(vm => vm.IsDarkModeEasy)
+ .Subscribe(v => {
+ Application.Current!.Resources["IsDarkModeEasy"] = v;
+ UpdateColorsByMain();
+ });
+
this.WhenAnyValue(vm => vm.BackgroundColor)
.Subscribe(v => Application.Current!.Resources["BackgroundColor"] = v);
@@ -221,6 +239,18 @@ public ThemeEditorViewModel(string customThemePath) {
this.WhenAnyValue(vm => vm.BlackKeyNameColor)
.Subscribe(v => Application.Current!.Resources["BlackKeyNameColor"] = v);
+
+ this.WhenAnyValue(vm => vm.MainColorA)
+ .Subscribe(v => {
+ Application.Current!.Resources["MainColorA"] = v;
+ UpdateColorsByMain();
+ });
+
+ this.WhenAnyValue(vm => vm.MainColorB)
+ .Subscribe(v => {
+ Application.Current!.Resources["MainColorB"] = v;
+ UpdateColorsByMain();
+ });
}
public void Save() {
@@ -265,11 +295,117 @@ public void Save() {
BlackKeyColorLeft = BlackKeyColorLeft.ToString(),
BlackKeyColorRight = BlackKeyColorRight.ToString(),
- BlackKeyNameColor = BlackKeyNameColor.ToString()
+ BlackKeyNameColor = BlackKeyNameColor.ToString(),
+
+ MainColorA = MainColorA.ToString(),
+ MainColorB = MainColorB.ToString(),
+ IsDarkModeEasy = IsDarkModeEasy
};
File.WriteAllText(customThemePath, Yaml.DefaultSerializer.Serialize(themeYaml), Encoding.UTF8);
}
+ private void UpdateColorsByMain() {
+ if (IsDarkModeEasy) {
+ BackgroundColor = Color.FromUInt32(0xFF303030);
+ BackgroundColorPointerOver = Color.FromUInt32(0xFF505050);
+ BackgroundColorPressed = Color.FromUInt32(0xFF707070);
+ BackgroundColorDisabled = Color.FromUInt32(0xFF404040);
+
+ ForegroundColor = Color.FromUInt32(0xFFE0E0E0);
+ ForegroundColorPointerOver = Color.FromUInt32(0xFFFCFCFC);
+ ForegroundColorPressed = Color.FromUInt32(0xFFFFFFFF);
+ ForegroundColorDisabled = Color.FromUInt32(0xFFA0A0A0);
+
+ BorderColor = Color.FromUInt32(0xFF707070);
+ BorderColorPointerOver = Color.FromUInt32(0xFFB0B0B0);
+
+ SystemAccentColor = MainColorA;
+ SystemAccentColorLight1 = ColorShift(MainColorA, 32);
+ SystemAccentColorDark1 = ColorMultiply(MainColorA, 0.8f);
+
+ NeutralAccentColor = Color.FromUInt32(0xFF808080);
+ NeutralAccentColorPointerOver = Color.FromUInt32(0xFFA0A0A0);
+ AccentColor1 = MainColorA;
+ AccentColor2 = ColorShift(MainColorB, 32);
+ AccentColor3 = ColorMultiply(MainColorB, 0.8f);
+
+ TickLineColor = Color.FromUInt32(0xFF707070);
+ BarNumberColor = Color.FromUInt32(0xFFD0D0D0);
+ FinalPitchColor = Color.FromUInt32(0xFFD0D0D0);
+ TrackBackgroundAltColor = Color.FromUInt32(0xFF404040);
+
+ WhiteKeyColorLeft = ColorMultiply(MainColorB, 0.9f);
+ WhiteKeyColorRight = MainColorB;
+ WhiteKeyNameColor = Color.FromUInt32(0xFFFFFFFF);
+
+ CenterKeyColorLeft = ColorMultiply(ColorShift(MainColorB, 152), 0.9f);
+ CenterKeyColorRight = ColorShift(MainColorB, 152);
+ CenterKeyNameColor = MainColorB;
+
+ BlackKeyColorLeft = Color.FromUInt32(0x00000000);
+ BlackKeyColorRight = Color.FromUInt32(0x00000000);
+ BlackKeyNameColor = Color.FromUInt32(0xFFFFFFFF);
+ } else {
+ BackgroundColor = Color.FromUInt32(0xFFFFFFFF);
+ BackgroundColorPointerOver = Color.FromUInt32(0xFFF0F0F0);
+ BackgroundColorPressed = Color.FromUInt32(0xFFE0E0E0);
+ BackgroundColorDisabled = Color.FromUInt32(0xFFD0D0D0);
+
+ ForegroundColor = Color.FromUInt32(0xFF000000);
+ ForegroundColorPointerOver = Color.FromUInt32(0xFF000000);
+ ForegroundColorPressed = Color.FromUInt32(0xFF202020);
+ ForegroundColorDisabled = Color.FromUInt32(0xFF808080);
+
+ BorderColor = Color.FromUInt32(0xFF707070);
+ BorderColorPointerOver = Color.FromUInt32(0xFFB0B0B0);
+
+ SystemAccentColor = MainColorA;
+ SystemAccentColorLight1 = ColorShift(MainColorA, 32);
+ SystemAccentColorDark1 = ColorMultiply(MainColorA, 0.8f);
+
+ NeutralAccentColor = Color.FromUInt32(0xFFA7A7A7);
+ NeutralAccentColorPointerOver = Color.FromUInt32(0xFF909090);
+ AccentColor1 = MainColorA;
+ AccentColor2 = ColorShift(MainColorB, 32);
+ AccentColor3 = ColorMultiply(MainColorB, 0.8f);
+
+ TickLineColor = Color.FromUInt32(0xFFB0B0B0);
+ BarNumberColor = Color.FromUInt32(0xFFB0B0B0);
+ FinalPitchColor = Color.FromUInt32(0xFFC0C0C0);
+ TrackBackgroundAltColor = Color.FromUInt32(0xFFF0F0F0);
+
+ WhiteKeyColorLeft = Color.FromUInt32(0x00000000);
+ WhiteKeyColorRight = Color.FromUInt32(0x00000000);
+ WhiteKeyNameColor = MainColorB;
+
+ CenterKeyColorLeft = ColorShift(MainColorB, 144);
+ CenterKeyColorRight = ColorShift(MainColorB, 152);
+ CenterKeyNameColor = MainColorB;
+
+ BlackKeyColorLeft = ColorShift(MainColorB, 32);
+ BlackKeyColorRight = MainColorB;
+ BlackKeyNameColor = Color.FromUInt32(0xFFFFFFFF);
+ }
+ IsDarkMode = IsDarkModeEasy;
+ }
+
+ public static Color ColorMultiply(Color color, float ratio) {
+ return Color.FromArgb(
+ color.A,
+ (byte)((color.R * ratio) > 255 ? 255 : color.R * ratio),
+ (byte)((color.G * ratio) > 255 ? 255 : color.G * ratio),
+ (byte)((color.B * ratio) > 255 ? 255 : color.B * ratio)
+ );
+ }
+ public static Color ColorShift(Color color, int delta) {
+ return Color.FromArgb(
+ color.A,
+ (byte)((color.R + delta) > 255 ? 255 : ((color.R + delta) < 0 ? 0 : color.R + delta)),
+ (byte)((color.G + delta) > 255 ? 255 : ((color.G + delta) < 0 ? 0 : color.G + delta)),
+ (byte)((color.B + delta) > 255 ? 255 : ((color.B + delta) < 0 ? 0 : color.B + delta))
+ );
+ }
+
}
}
diff --git a/OpenUtau/Views/ThemeEditorWindow.axaml b/OpenUtau/Views/ThemeEditorWindow.axaml
index 815797e4f..b194919c3 100644
--- a/OpenUtau/Views/ThemeEditorWindow.axaml
+++ b/OpenUtau/Views/ThemeEditorWindow.axaml
@@ -1,157 +1,198 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenUtau/Views/ThemeEditorWindow.axaml.cs b/OpenUtau/Views/ThemeEditorWindow.axaml.cs
index f75a864c6..83ffadd04 100644
--- a/OpenUtau/Views/ThemeEditorWindow.axaml.cs
+++ b/OpenUtau/Views/ThemeEditorWindow.axaml.cs
@@ -3,6 +3,7 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml.Templates;
using OpenUtau.App.ViewModels;
using ReactiveUI;
@@ -16,6 +17,37 @@ public partial class ThemeEditorWindow : Window {
private ThemeEditorWindow(string customThemePath) {
InitializeComponent();
DataContext = new ThemeEditorViewModel(customThemePath);
+ UpdateTemplate();
+ if (DataContext is ThemeEditorViewModel vm) {
+ vm.PropertyChanged += (s, e) =>
+ {
+ if (e.PropertyName == nameof(ThemeEditorViewModel.IsEasyMode)) {
+ UpdateTemplate();
+ }
+ };
+ }
+ }
+
+ private void UpdateTemplate() {
+ if (DataContext is ThemeEditorViewModel vm && ContentControl != null) {
+ var template = vm.IsEasyMode
+ ? this.FindResource("EasyMode") as DataTemplate
+ : this.FindResource("AccurateMode") as DataTemplate;
+ ContentControl.ContentTemplate = template;
+ ContentControl.Content = vm;
+ }
+ }
+
+ void SwitchToAccurateMode(object? sender, RoutedEventArgs e) {
+ if (DataContext is ThemeEditorViewModel vm) {
+ vm.IsEasyMode = false;
+ }
+ }
+
+ void SwitchToEasyMode(object? sender, RoutedEventArgs e) {
+ if (DataContext is ThemeEditorViewModel vm) {
+ vm.IsEasyMode = true;
+ }
}
void OnCancel(object? sender, RoutedEventArgs e) {