diff --git a/OngekiFumenEditor/App.config b/OngekiFumenEditor/App.config
index 92e5f623..61ab28dc 100644
--- a/OngekiFumenEditor/App.config
+++ b/OngekiFumenEditor/App.config
@@ -155,6 +155,21 @@
False
+
+ Red
+
+
+ Lime
+
+
+ Blue
+
+
+ 35, 4, 117
+
+
+ 136, 3, 152
+
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Models/ColorPropertyWrapper.cs b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Models/ColorPropertyWrapper.cs
new file mode 100644
index 00000000..48ef1ea6
--- /dev/null
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Models/ColorPropertyWrapper.cs
@@ -0,0 +1,75 @@
+using Caliburn.Micro;
+using OngekiFumenEditor.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+
+namespace OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.Models
+{
+ public class ColorPropertyWrapper : PropertyChangedBase
+ {
+ private readonly PropertyInfo propertyInfo;
+ private readonly object owner;
+ private SolidColorBrush cachedColorBrush;
+ private SolidColorBrush cachedReverseColorBrush;
+
+ public ColorPropertyWrapper(PropertyInfo propertyInfo, object owner)
+ {
+ this.propertyInfo = propertyInfo;
+ this.owner = owner;
+
+ RefreshBrush();
+ }
+
+ private void RefreshBrush()
+ {
+ var color = Color;
+ cachedColorBrush = new SolidColorBrush(color.ToMediaColor());
+ cachedReverseColorBrush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(color.A, (byte)(255 - color.R), (byte)(255 - color.G), (byte)(255 - color.B)));
+
+ NotifyOfPropertyChange(nameof(Brush));
+ NotifyOfPropertyChange(nameof(ReverseBrush));
+ }
+
+ public System.Drawing.Color Color
+ {
+ get => (System.Drawing.Color)propertyInfo.GetValue(owner, null);
+ set
+ {
+ propertyInfo.SetValue(owner, value, null);
+ RefreshBrush();
+
+ NotifyOfPropertyChange(nameof(Color));
+ NotifyOfPropertyChange(nameof(ColorString));
+ }
+ }
+
+ public SolidColorBrush Brush => cachedColorBrush;
+ public SolidColorBrush ReverseBrush => cachedReverseColorBrush;
+
+ public string Name => propertyInfo.Name;
+
+ public string ColorString
+ {
+ get
+ {
+ var r = Color;
+ return $"{r.R}, {r.G}, {r.B}, {r.A}";
+ }
+ set
+ {
+ var split = value.Split(',');
+ var r = int.Parse(split[0].Trim());
+ var g = int.Parse(split[1].Trim());
+ var b = int.Parse(split[2].Trim());
+ var a = split.Length > 3 ? int.Parse(split[3]) : 255;
+
+ Color = System.Drawing.Color.FromArgb(a, r, g, b);
+ }
+ }
+ }
+}
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorColorSettingViewModel.cs b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorColorSettingViewModel.cs
new file mode 100644
index 00000000..941a66bf
--- /dev/null
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorColorSettingViewModel.cs
@@ -0,0 +1,53 @@
+using Caliburn.Micro;
+using Gemini.Modules.Settings;
+using OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.Models;
+using OngekiFumenEditor.Properties;
+using OngekiFumenEditor.UI.Dialogs;
+using OngekiFumenEditor.Utils;
+using System.ComponentModel.Composition;
+using System.Linq;
+
+namespace OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ViewModels
+{
+ [Export(typeof(ISettingsEditor))]
+ [PartCreationPolicy(CreationPolicy.Shared)]
+ public class FumenVisualEditorColorSettingViewModel : PropertyChangedBase, ISettingsEditor
+ {
+ public EditorGlobalSetting Setting => EditorGlobalSetting.Default;
+
+ public FumenVisualEditorColorSettingViewModel()
+ {
+ ColorsProperties = typeof(EditorGlobalSetting)
+ .GetProperties()
+ .Where(x => x.Name.StartsWith("Color") && x.PropertyType == typeof(System.Drawing.Color))
+ .Select(x => new ColorPropertyWrapper(x, EditorGlobalSetting.Default))
+ .ToArray();
+ }
+
+ public string SettingsPagePath => Resources.TabDocument + "\\" + Resources.TabEditor;
+
+ public string SettingsPageName => "渲染色彩管理";
+
+ public ColorPropertyWrapper[] ColorsProperties { get; private set; }
+
+ public void ApplyChanges()
+ {
+ EditorGlobalSetting.Default.Save();
+ }
+
+ public void OnSelectColor(ActionExecutionContext context)
+ {
+ if (context.Source.DataContext is not ColorPropertyWrapper colorProperty)
+ return;
+
+ var dialog = new CommonColorPicker(() =>
+ {
+ return colorProperty.Color.ToMediaColor();
+ }, color =>
+ {
+ colorProperty.Color = color.ToDrawingColor();
+ }, $"设置新的 {colorProperty.Name} 颜色");
+ dialog.Show();
+ }
+ }
+}
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorGlobalSettingViewModel.cs b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorGlobalSettingViewModel.cs
index d17ccb29..7f1f49ec 100644
--- a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorGlobalSettingViewModel.cs
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/ViewModels/FumenVisualEditorGlobalSettingViewModel.cs
@@ -13,11 +13,11 @@ namespace OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ViewModels
[PartCreationPolicy(CreationPolicy.Shared)]
public class FumenVisualEditorGlobalSettingViewModel : PropertyChangedBase, ISettingsEditor
{
- public Properties.EditorGlobalSetting Setting => Properties.EditorGlobalSetting.Default;
+ public EditorGlobalSetting Setting => EditorGlobalSetting.Default;
public FumenVisualEditorGlobalSettingViewModel()
{
- Properties.EditorGlobalSetting.Default.PropertyChanged += SettingPropertyChanged;
+ EditorGlobalSetting.Default.PropertyChanged += SettingPropertyChanged;
}
private void SettingPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -31,7 +31,7 @@ private void SettingPropertyChanged(object sender, System.ComponentModel.Propert
public void ApplyChanges()
{
- Properties.EditorGlobalSetting.Default.Save();
+ EditorGlobalSetting.Default.Save();
}
public void ClearRecentOpen()
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml
new file mode 100644
index 00000000..8416308a
--- /dev/null
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml.cs b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml.cs
new file mode 100644
index 00000000..484fc735
--- /dev/null
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorColorSettingView.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.Views
+{
+ ///
+ /// FumenVisualEditorGlobalSettingView.xaml 的交互逻辑
+ ///
+ public partial class FumenVisualEditorColorSettingView : UserControl
+ {
+ public FumenVisualEditorColorSettingView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/CommonHorizonalDrawingTarget.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/CommonHorizonalDrawingTarget.cs
index c4a301ad..3a525aa0 100644
--- a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/CommonHorizonalDrawingTarget.cs
+++ b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/CommonHorizonalDrawingTarget.cs
@@ -28,14 +28,16 @@ public CommonHorizonalDrawingTarget()
{
lineDrawing = IoC.Get();
stringDrawing = IoC.Get();
+
+
}
- public override IEnumerable DrawTargetID { get; } = new[]
- {
- "MET","SFL","BPM","EST","CLK","LBK","[LBK_End]","[SFL_End]","[CMT]","[INTP_SFL]","[INTP_SFL_End]","[KEY_SFL]"
- };
+ public override IEnumerable DrawTargetID { get; } =
+ [
+ "MET","SFL","BPM","EST","CLK","LBK","[LBK_End]","[SFL_End]","[CMT]","[INTP_SFL]","[INTP_SFL_End]","[KEY_SFL]"
+ ];
- private static Dictionary colors = new()
+ private Dictionary colors = new()
{
{"MET", FSColor.LightGreen },
{"SFL", FSColor.LightCyan },
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/Holds/HoldDrawingTarget.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/Holds/HoldDrawingTarget.cs
index 94d40b2a..bf4cca66 100644
--- a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/Holds/HoldDrawingTarget.cs
+++ b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/TargetImpl/OngekiObjects/Holds/HoldDrawingTarget.cs
@@ -10,107 +10,143 @@
using System.ComponentModel.Composition;
using System.Linq;
using System.Numerics;
+using System.Runtime.CompilerServices;
using static OngekiFumenEditor.Kernel.Graphics.ILineDrawing;
namespace OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.TargetImpl.OngekiObjects.Holds
{
- [Export(typeof(IFumenEditorDrawingTarget))]
- public class HoldDrawingTarget : CommonDrawTargetBase
- {
- public override IEnumerable DrawTargetID { get; } = new string[] { "HLD", "CHD", "XHD" };
-
- public override int DefaultRenderOrder => 500;
-
- private ILineDrawing lineDrawing;
-
- public HoldDrawingTarget() : base()
- {
- lineDrawing = IoC.Get();
- }
-
- public override void Draw(IFumenEditorDrawingContext target, Hold hold)
- {
- var start = hold.ReferenceLaneStart;
- var holdEnd = hold.HoldEnd;
- var laneType = start?.LaneType;
-
- var color = laneType switch
- {
- LaneType.Left => new Vector4(1, 0, 0, 0.75f),
- LaneType.Center => new Vector4(0, 1, 0, 0.75f),
- LaneType.Right => new Vector4(0, 0, 1, 0.75f),
- LaneType.WallLeft => new Vector4(35 / 255.0f, 4 / 255.0f, 117 / 255.0f, 0.75f),
- LaneType.WallRight => new Vector4(136 / 255.0f, 3 / 255.0f, 152 / 255.0f, 0.75f),
- _ => new Vector4(1, 1, 1, 0.75f),
- };
-
- if (holdEnd != null)
- {
- Vector2 PostPoint2(double tGridUnit, double xGridUnit)
- {
- var x = (float)XGridCalculator.ConvertXGridToX(xGridUnit, target.Editor);
- var y = (float)target.ConvertToY(tGridUnit);
-
- return new(x, y);
- }
-
- var holdPoint = PostPoint2(hold.TGrid.TotalUnit, hold.XGrid.TotalUnit);
- var holdEndPoint = PostPoint2(holdEnd.TGrid.TotalUnit, holdEnd.XGrid.TotalUnit);
-
- bool checkDiscardByHorizon(Vector2 prev, Vector2 end, Vector2 cur)
- {
- //判断三个点是否都在一个水平上
- if (prev.Y == cur.Y && end.Y == cur.Y)
- {
- /*
+ [Export(typeof(IFumenEditorDrawingTarget))]
+ public class HoldDrawingTarget : CommonDrawTargetBase
+ {
+ public override IEnumerable DrawTargetID { get; } = new string[] { "HLD", "CHD", "XHD" };
+
+ public override int DefaultRenderOrder => 500;
+
+ private ILineDrawing lineDrawing;
+
+ private Vector4 colorHoldLeft;
+ private Vector4 colorHoldCenter;
+ private Vector4 colorHoldRight;
+ private Vector4 colorHoldWallLeft;
+ private Vector4 colorHoldWallRight;
+
+ public HoldDrawingTarget() : base()
+ {
+ lineDrawing = IoC.Get();
+
+ Properties.EditorGlobalSetting.Default.PropertyChanged += EditorGlobalSettingPropertyChanged;
+ RebuildColors();
+ }
+
+ private void EditorGlobalSettingPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (!e.PropertyName.StartsWith("ColorHold"))
+ return;
+
+ RebuildColors();
+ }
+
+ private void RebuildColors()
+ {
+ static void build(ref Vector4 v, System.Drawing.Color c)
+ {
+ v = c.ToVector4();
+ v.W = 0.75f;
+ }
+
+ build(ref colorHoldLeft, Properties.EditorGlobalSetting.Default.ColorHoldLeft);
+ build(ref colorHoldCenter, Properties.EditorGlobalSetting.Default.ColorHoldCenter);
+ build(ref colorHoldRight, Properties.EditorGlobalSetting.Default.ColorHoldRight);
+
+ build(ref colorHoldWallLeft, Properties.EditorGlobalSetting.Default.ColorHoldWallLeft);
+ build(ref colorHoldWallRight, Properties.EditorGlobalSetting.Default.ColorHoldWallRight);
+
+ //Log.LogInfo($"hold color has been rebuild.");
+ }
+
+ public override void Draw(IFumenEditorDrawingContext target, Hold hold)
+ {
+ var start = hold.ReferenceLaneStart;
+ var holdEnd = hold.HoldEnd;
+ var laneType = start?.LaneType;
+
+ var color = laneType switch
+ {
+ LaneType.Left => colorHoldLeft,
+ LaneType.Center => colorHoldCenter,
+ LaneType.Right => colorHoldRight,
+ LaneType.WallLeft => colorHoldWallLeft,
+ LaneType.WallRight => colorHoldWallRight,
+ _ => new Vector4(1, 1, 1, 0.75f),
+ };
+
+ if (holdEnd != null)
+ {
+ Vector2 PostPoint2(double tGridUnit, double xGridUnit)
+ {
+ var x = (float)XGridCalculator.ConvertXGridToX(xGridUnit, target.Editor);
+ var y = (float)target.ConvertToY(tGridUnit);
+
+ return new(x, y);
+ }
+
+ var holdPoint = PostPoint2(hold.TGrid.TotalUnit, hold.XGrid.TotalUnit);
+ var holdEndPoint = PostPoint2(holdEnd.TGrid.TotalUnit, holdEnd.XGrid.TotalUnit);
+
+ bool checkDiscardByHorizon(Vector2 prev, Vector2 end, Vector2 cur)
+ {
+ //判断三个点是否都在一个水平上
+ if (prev.Y == cur.Y && end.Y == cur.Y)
+ {
+ /*
good discard
o-----------x---------o----------x----------------
| | | |
prevX curX_1 endPosX curX_2
*/
- var checkX = cur.X;
- if (checkX < MathF.Min(prev.X, end.X) || checkX > MathF.Max(prev.X, end.X))
- return true;
- }
- return false;
- }
-
- using var d = ObjectPool>.GetWithUsingDisposable(out var list, out _);
- list.Clear();
- VisibleLineVerticesQuery.QueryVisibleLineVertices(target, start, VertexDash.Solider, color, list);
- if (list.Count > 0)
- {
- while (list.Count > 0 && holdPoint.Y > list[0].Point.Y)
- list.RemoveAt(0);
- if (list.Count >= 2)
- {
- var outSide = list[0];
- var inSide = list[1];
-
- if (checkDiscardByHorizon(inSide.Point, holdPoint, outSide.Point))
- list.RemoveAt(0);
- }
- list.Insert(0, new LineVertex(holdPoint, color, VertexDash.Solider));
- while (list.Count > 0 && holdEndPoint.Y < list[list.Count - 1].Point.Y)
- list.RemoveAt(list.Count - 1);
- if (list.Count >= 2)
- {
- var outSide = list[list.Count - 1];
- var inSide = list[list.Count - 2];
-
- if (checkDiscardByHorizon(inSide.Point, holdEndPoint, outSide.Point))
- list.RemoveAt(list.Count - 1);
- }
- list.Add(new LineVertex(holdEndPoint, color, VertexDash.Solider));
- }
- else
- {
- list.Add(new LineVertex(holdPoint, color, VertexDash.Solider));
- list.Add(new LineVertex(holdEndPoint, color, VertexDash.Solider));
- }
-
- lineDrawing.Draw(target, list, 13);
- }
- }
- }
+ var checkX = cur.X;
+ if (checkX < MathF.Min(prev.X, end.X) || checkX > MathF.Max(prev.X, end.X))
+ return true;
+ }
+ return false;
+ }
+
+ using var d = ObjectPool>.GetWithUsingDisposable(out var list, out _);
+ list.Clear();
+ VisibleLineVerticesQuery.QueryVisibleLineVertices(target, start, VertexDash.Solider, color, list);
+ if (list.Count > 0)
+ {
+ while (list.Count > 0 && holdPoint.Y > list[0].Point.Y)
+ list.RemoveAt(0);
+ if (list.Count >= 2)
+ {
+ var outSide = list[0];
+ var inSide = list[1];
+
+ if (checkDiscardByHorizon(inSide.Point, holdPoint, outSide.Point))
+ list.RemoveAt(0);
+ }
+ list.Insert(0, new LineVertex(holdPoint, color, VertexDash.Solider));
+ while (list.Count > 0 && holdEndPoint.Y < list[list.Count - 1].Point.Y)
+ list.RemoveAt(list.Count - 1);
+ if (list.Count >= 2)
+ {
+ var outSide = list[list.Count - 1];
+ var inSide = list[list.Count - 2];
+
+ if (checkDiscardByHorizon(inSide.Point, holdEndPoint, outSide.Point))
+ list.RemoveAt(list.Count - 1);
+ }
+ list.Add(new LineVertex(holdEndPoint, color, VertexDash.Solider));
+ }
+ else
+ {
+ list.Add(new LineVertex(holdPoint, color, VertexDash.Solider));
+ list.Add(new LineVertex(holdEndPoint, color, VertexDash.Solider));
+ }
+
+ lineDrawing.Draw(target, list, 13);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs b/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
index 965d0e58..4314c27b 100644
--- a/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
+++ b/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
@@ -394,5 +394,65 @@ public bool EnableShowPlayerLocation {
this["EnableShowPlayerLocation"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Red")]
+ public global::System.Drawing.Color ColorHoldLeft {
+ get {
+ return ((global::System.Drawing.Color)(this["ColorHoldLeft"]));
+ }
+ set {
+ this["ColorHoldLeft"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Lime")]
+ public global::System.Drawing.Color ColorHoldCenter {
+ get {
+ return ((global::System.Drawing.Color)(this["ColorHoldCenter"]));
+ }
+ set {
+ this["ColorHoldCenter"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Blue")]
+ public global::System.Drawing.Color ColorHoldRight {
+ get {
+ return ((global::System.Drawing.Color)(this["ColorHoldRight"]));
+ }
+ set {
+ this["ColorHoldRight"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("35, 4, 117")]
+ public global::System.Drawing.Color ColorHoldWallRight {
+ get {
+ return ((global::System.Drawing.Color)(this["ColorHoldWallRight"]));
+ }
+ set {
+ this["ColorHoldWallRight"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("136, 3, 152")]
+ public global::System.Drawing.Color ColorHoldWallLeft {
+ get {
+ return ((global::System.Drawing.Color)(this["ColorHoldWallLeft"]));
+ }
+ set {
+ this["ColorHoldWallLeft"] = value;
+ }
+ }
}
}
diff --git a/OngekiFumenEditor/Properties/EditorGlobalSetting.settings b/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
index 92d8a4c6..d55429e4 100644
--- a/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
+++ b/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
@@ -95,5 +95,20 @@
False
+
+ Red
+
+
+ Lime
+
+
+ Blue
+
+
+ 35, 4, 117
+
+
+ 136, 3, 152
+
\ No newline at end of file