diff --git a/VPet.Solution/Converters.xaml b/VPet.Solution/Converters.xaml
index dae08b0..71ef646 100644
--- a/VPet.Solution/Converters.xaml
+++ b/VPet.Solution/Converters.xaml
@@ -8,6 +8,16 @@
+
+
+
diff --git a/VPet.Solution/Converters/BoolInverter.cs b/VPet.Solution/Converters/BoolInverter.cs
index 7ab221f..7033fbf 100644
--- a/VPet.Solution/Converters/BoolInverter.cs
+++ b/VPet.Solution/Converters/BoolInverter.cs
@@ -13,7 +13,7 @@ public class BoolInverter : ValueConverterBase
public static readonly DependencyProperty NullValueProperty = DependencyProperty.Register(
nameof(NullValue),
typeof(bool),
- typeof(AllIsBoolToVisibilityConverter),
+ typeof(BoolInverter),
new PropertyMetadata(false)
);
diff --git a/VPet.Solution/Converters/NullToVisibilityConverter.cs b/VPet.Solution/Converters/NullToVisibilityConverter.cs
new file mode 100644
index 0000000..5b7ee71
--- /dev/null
+++ b/VPet.Solution/Converters/NullToVisibilityConverter.cs
@@ -0,0 +1,60 @@
+using System.ComponentModel;
+using System.Globalization;
+using System.Windows;
+
+namespace HKW.WPF.Converters;
+
+public class NullToVisibilityConverter : ValueConverterBase
+{
+ ///
+ ///
+ ///
+ public static readonly DependencyProperty NullVisibilityValueProperty =
+ DependencyProperty.Register(
+ nameof(NullVisibilityValue),
+ typeof(Visibility),
+ typeof(NullToVisibilityConverter),
+ new PropertyMetadata(Visibility.Hidden)
+ );
+
+ ///
+ /// NULL时的可见度
+ ///
+ [DefaultValue(Visibility.Hidden)]
+ public Visibility NullVisibilityValue
+ {
+ get => (Visibility)GetValue(NullVisibilityValueProperty);
+ set => SetValue(NullVisibilityValueProperty, value);
+ }
+
+ ///
+ ///
+ ///
+ public static readonly DependencyProperty NotNullVisibilityValueProperty =
+ DependencyProperty.Register(
+ nameof(NotNullVisibilityValue),
+ typeof(Visibility),
+ typeof(NullToVisibilityConverter),
+ new PropertyMetadata(Visibility.Visible)
+ );
+
+ ///
+ /// 不为NULL时的可见度
+ ///
+ [DefaultValue(Visibility.Visible)]
+ public Visibility NotNullVisibilityValue
+ {
+ get => (Visibility)GetValue(NotNullVisibilityValueProperty);
+ set => SetValue(NotNullVisibilityValueProperty, value);
+ }
+
+ public override object Convert(
+ object value,
+ Type targetType,
+ object parameter,
+ CultureInfo culture
+ )
+ {
+ return value is null ? NullVisibilityValue : NotNullVisibilityValue;
+ }
+}
diff --git a/VPet.Solution/Models/ModLoader.cs b/VPet.Solution/Models/ModLoader.cs
new file mode 100644
index 0000000..a14cda3
--- /dev/null
+++ b/VPet.Solution/Models/ModLoader.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using LinePutScript;
+using LinePutScript.Converter;
+using LinePutScript.Dictionary;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using VPet_Simulator.Core;
+using VPet_Simulator.Windows.Interface;
+using System.Windows.Media.Imaging;
+
+namespace VPet.Solution.Models;
+
+///
+/// 模组加载器
+///
+public class ModLoader
+{
+ ///
+ /// 名称
+ ///
+ public string Name { get; }
+
+ ///
+ /// 作者
+ ///
+ public string Author { get; }
+
+ ///
+ /// 如果是上传至Steam,则为SteamUserID
+ ///
+ public long AuthorID { get; }
+
+ ///
+ /// 上传至Steam的ItemID
+ ///
+ public ulong ItemID { get; }
+
+ ///
+ /// 简介
+ ///
+ public string Intro { get; }
+
+ ///
+ /// 模组路径
+ ///
+ public string ModPath { get; }
+
+ ///
+ /// 支持的游戏版本
+ ///
+ public int GameVer { get; }
+
+ ///
+ /// 版本
+ ///
+ public int Ver { get; }
+
+ ///
+ /// 标签
+ ///
+ public HashSet Tags { get; } = new();
+
+ ///
+ /// 缓存数据
+ ///
+ public DateTime CacheDate { get; } = DateTime.MinValue;
+
+ public BitmapImage? Image { get; } = null;
+
+ public ModLoader(string path)
+ {
+ ModPath = path;
+ var modlps = new LpsDocument(File.ReadAllText(Path.Combine(path + @"\info.lps")));
+ Name = modlps.FindLine("vupmod").Info;
+ Intro = modlps.FindLine("intro").Info;
+ GameVer = modlps.FindSub("gamever").InfoToInt;
+ Ver = modlps.FindSub("ver").InfoToInt;
+ Author = modlps.FindSub("author").Info.Split('[').First();
+ if (modlps.FindLine("authorid") != null)
+ AuthorID = modlps.FindLine("authorid").InfoToInt64;
+ else
+ AuthorID = 0;
+ if (modlps.FindLine("itemid") != null)
+ ItemID = Convert.ToUInt64(modlps.FindLine("itemid").info);
+ else
+ ItemID = 0;
+ CacheDate = modlps.GetDateTime("cachedate", DateTime.MinValue);
+ var imagePath = Path.Combine(path, "icon.png");
+ if (File.Exists(imagePath))
+ {
+ try
+ {
+ Image = Utils.LoadImageToStream(imagePath);
+ }
+ catch { }
+ }
+ foreach (var dir in Directory.EnumerateDirectories(path))
+ {
+ switch (dir.ToLower())
+ {
+ case "pet":
+ //宠物模型
+ Tags.Add("pet");
+ break;
+ case "food":
+ Tags.Add("food");
+ break;
+ case "image":
+ Tags.Add("image");
+ break;
+ case "text":
+ Tags.Add("text");
+ break;
+ case "lang":
+ Tags.Add("lang");
+ break;
+ }
+ }
+ }
+}
diff --git a/VPet.Solution/Models/SettingEditor/CustomizedSettingModel.cs b/VPet.Solution/Models/SettingEditor/CustomizedSettingModel.cs
new file mode 100644
index 0000000..3cdc518
--- /dev/null
+++ b/VPet.Solution/Models/SettingEditor/CustomizedSettingModel.cs
@@ -0,0 +1,55 @@
+using System.Collections.ObjectModel;
+
+namespace VPet.Solution.Models.SettingEditor;
+
+public class CustomizedSettingModel : ObservableClass
+{
+ public const string TargetName = "diy";
+
+ #region Links
+ private ObservableCollection _links = new();
+ public ObservableCollection Links
+ {
+ get => _links;
+ set => SetProperty(ref _links, value);
+ }
+ #endregion
+}
+
+public class LinkModel : ObservableClass
+{
+ #region Name
+ private string _name;
+
+ ///
+ /// 名称
+ ///
+ public string Name
+ {
+ get => _name;
+ set => SetProperty(ref _name, value);
+ }
+ #endregion
+
+
+ #region Link
+ private string _link;
+
+ ///
+ /// 链接
+ ///
+ public string Link
+ {
+ get => _link;
+ set => SetProperty(ref _link, value);
+ }
+ #endregion
+
+ public LinkModel() { }
+
+ public LinkModel(string name, string link)
+ {
+ Name = name;
+ Link = link;
+ }
+}
diff --git a/VPet.Solution/Models/SettingEditor/DiagnosticSettingModel.cs b/VPet.Solution/Models/SettingEditor/DiagnosticSettingModel.cs
new file mode 100644
index 0000000..d9f9329
--- /dev/null
+++ b/VPet.Solution/Models/SettingEditor/DiagnosticSettingModel.cs
@@ -0,0 +1,68 @@
+using HKW.HKWUtils.Observable;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using VPet_Simulator.Windows.Interface;
+
+namespace VPet.Solution.Models.SettingEditor;
+
+public class DiagnosticSettingModel : ObservableClass
+{
+ #region AutoCal
+ private bool _autoCal;
+
+ ///
+ /// 自动修复超模
+ ///
+ public bool AutoCal
+ {
+ get => _autoCal;
+ set => SetProperty(ref _autoCal, value);
+ }
+ #endregion
+
+ #region Diagnosis
+ private bool _diagnosis;
+
+ ///
+ /// 是否启用数据收集
+ ///
+ [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Diagnosis))]
+ public bool Diagnosis
+ {
+ get => _diagnosis;
+ set => SetProperty(ref _diagnosis, value);
+ }
+ #endregion
+
+ #region DiagnosisInterval
+ private int _diagnosisInterval = 200;
+
+ ///
+ /// 数据收集频率
+ ///
+ [DefaultValue(200)]
+ [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.DiagnosisInterval))]
+ public int DiagnosisInterval
+ {
+ get => _diagnosisInterval;
+ set => SetProperty(ref _diagnosisInterval, value);
+ }
+ public static ObservableCollection DiagnosisIntervals { get; } =
+ new() { 200, 500, 1000, 2000, 5000, 10000, 20000 };
+ #endregion
+
+ public void GetAutoCalFromSetting(Setting setting)
+ {
+ AutoCal = setting["gameconfig"].GetBool("noAutoCal") is false;
+ }
+
+ public void SetAutoCalToSetting(Setting setting)
+ {
+ setting["gameconfig"].SetBool("noAutoCal", AutoCal is false);
+ }
+}
diff --git a/VPet.Solution/Models/SettingEditor/ModSettingModel.cs b/VPet.Solution/Models/SettingEditor/ModSettingModel.cs
new file mode 100644
index 0000000..6e3c122
--- /dev/null
+++ b/VPet.Solution/Models/SettingEditor/ModSettingModel.cs
@@ -0,0 +1,287 @@
+using HKW.HKWUtils.Observable;
+using LinePutScript;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using VPet_Simulator.Windows.Interface;
+
+namespace VPet.Solution.Models.SettingEditor;
+
+public class ModSettingModel : ObservableClass
+{
+ public const string ModLineName = "onmod";
+ public const string PassModLineName = "passmod";
+ public const string MsgModLineName = "msgmod";
+ public static string ModDirectory = Path.Combine(Environment.CurrentDirectory, "mod");
+ public static Dictionary LocalMods = Directory.Exists(ModDirectory) is false
+ ? new(StringComparer.OrdinalIgnoreCase)
+ : new(
+ Directory
+ .EnumerateDirectories(ModDirectory)
+ .Select(d => new ModLoader(d))
+ .ToDictionary(m => m.Name, m => m),
+ StringComparer.OrdinalIgnoreCase
+ );
+ #region Mods
+ private ObservableCollection _mods = new();
+ public ObservableCollection Mods
+ {
+ get => _mods;
+ set => SetProperty(ref _mods, value);
+ }
+
+ public ModSettingModel(Setting setting)
+ {
+ foreach (var item in setting[ModLineName])
+ {
+ var modName = item.Name;
+ if (LocalMods.TryGetValue(modName, out var loader))
+ {
+ var modModel = new ModModel(loader);
+ modModel.IsPass = setting[PassModLineName].Contains(modName);
+ modModel.IsMsg = setting[MsgModLineName].Contains(modModel.Name);
+ Mods.Add(modModel);
+ }
+ else
+ Mods.Add(new());
+ }
+ }
+
+ public void Close()
+ {
+ foreach (var modLoader in LocalMods)
+ {
+ modLoader.Value.Image.CloseStream();
+ }
+ }
+
+ public void Save(Setting setting)
+ {
+ setting.Remove(ModLineName);
+ setting.Remove(PassModLineName);
+ setting.Remove(MsgModLineName);
+ if (Mods.Any() is false)
+ return;
+ foreach (var mod in Mods)
+ {
+ setting[ModLineName].Add(new Sub(mod.Name.ToLower()));
+ setting[MsgModLineName].Add(new Sub(mod.Name, "True"));
+ if (mod.IsPass)
+ setting[PassModLineName].Add(new Sub(mod.Name.ToLower()));
+ }
+ }
+ #endregion
+}
+
+public class ModModel : ObservableClass
+{
+ #region Name
+ private string _name;
+
+ ///
+ /// 名称
+ ///
+ [ReflectionProperty(nameof(ModLoader.Name))]
+ public string Name
+ {
+ get => _name;
+ set => SetProperty(ref _name, value);
+ }
+ #endregion
+
+ #region Description
+ private string _description;
+
+ ///
+ /// 描述
+ ///
+ [ReflectionProperty(nameof(ModLoader.Intro))]
+ public string Description
+ {
+ get => _description;
+ set => SetProperty(ref _description, value);
+ }
+ #endregion
+
+ #region Author
+ private string _author;
+
+ ///
+ /// 作者
+ ///
+ [ReflectionProperty(nameof(ModLoader.Author))]
+ public string Author
+ {
+ get => _author;
+ set => SetProperty(ref _author, value);
+ }
+ #endregion
+
+ #region ModVersion
+ private int _modVersion;
+
+ ///
+ /// 模组版本
+ ///
+ [ReflectionProperty(nameof(ModLoader.Ver))]
+ public int ModVersion
+ {
+ get => _modVersion;
+ set => SetProperty(ref _modVersion, value);
+ }
+ #endregion
+
+ #region GameVersion
+ private int _gameVersion;
+
+ ///
+ /// 游戏版本
+ ///
+ [ReflectionProperty(nameof(ModLoader.GameVer))]
+ public int GameVersion
+ {
+ get => _gameVersion;
+ set => SetProperty(ref _gameVersion, value);
+ }
+ #endregion
+
+ #region Tags
+ private HashSet _tags;
+
+ ///
+ /// 功能
+ ///
+ [ReflectionProperty(nameof(ModLoader.Tags))]
+ public HashSet Tags
+ {
+ get => _tags;
+ set => SetProperty(ref _tags, value);
+ }
+ #endregion
+
+ #region Image
+ private BitmapImage _image;
+
+ ///
+ /// 图像
+ ///
+ [ReflectionProperty(nameof(ModLoader.Image))]
+ public BitmapImage Image
+ {
+ get => _image;
+ set => SetProperty(ref _image, value);
+ }
+ #endregion
+
+ #region ItemId
+ private ulong _itemId;
+
+ [ReflectionProperty(nameof(ModLoader.ItemID))]
+ public ulong ItemId
+ {
+ get => _itemId;
+ set => SetProperty(ref _itemId, value);
+ }
+ #endregion
+
+
+ #region ModPath
+
+ private string _modPath;
+
+ [ReflectionProperty(nameof(ModLoader.ModPath))]
+ public string ModPath
+ {
+ get => _modPath;
+ set => SetProperty(ref _modPath, value);
+ }
+ #endregion
+
+ #region IsEnabled
+ private bool? _isEnabled = true;
+
+ ///
+ /// 已启用
+ ///
+ public bool? IsEnabled
+ {
+ get => _isEnabled;
+ set => SetProperty(ref _isEnabled, value);
+ }
+ #endregion
+
+ #region IsPass
+ private bool _isPass;
+
+ ///
+ /// 是通过检查的代码模组
+ ///
+ public bool IsPass
+ {
+ get => _isPass;
+ set => SetProperty(ref _isPass, value);
+ }
+ #endregion
+
+ #region IsMsg
+ private bool _isMsg;
+
+ ///
+ /// 是含有代码的模组
+ ///
+ public bool IsMsg
+ {
+ get => _isMsg;
+ set => SetProperty(ref _isMsg, value);
+ }
+ #endregion
+
+ #region State
+ private string _state;
+ public string State
+ {
+ get => _state;
+ set => SetProperty(ref _state, value);
+ }
+ #endregion
+
+
+ public ModModel()
+ {
+ PropertyChanged += ModModel_PropertyChanged;
+ IsEnabled = null;
+ }
+
+ private void ModModel_PropertyChanged(
+ object sender,
+ System.ComponentModel.PropertyChangedEventArgs e
+ )
+ {
+ if (e.PropertyName == nameof(IsEnabled))
+ {
+ RefreshState();
+ }
+ }
+
+ public ModModel(ModLoader loader)
+ {
+ PropertyChanged += ModModel_PropertyChanged;
+ ReflectionUtils.SetValue(loader, this);
+ RefreshState();
+ }
+
+ public void RefreshState()
+ {
+ if (IsEnabled is true)
+ State = "已启用";
+ else if (IsEnabled is false)
+ State = "已关闭";
+ else
+ State = "已损坏";
+ }
+}
diff --git a/VPet.Solution/Models/SettingEditor/SettingModel.cs b/VPet.Solution/Models/SettingEditor/SettingModel.cs
index fc0c552..a3be916 100644
--- a/VPet.Solution/Models/SettingEditor/SettingModel.cs
+++ b/VPet.Solution/Models/SettingEditor/SettingModel.cs
@@ -50,12 +50,37 @@ public class SettingModel : ObservableClass
}
#endregion
- private static HashSet _settingProperties =
- new(typeof(Setting).GetProperties().Select(p => p.Name));
+ #region CustomizedSetting
+ private CustomizedSettingModel _CustomizedSetting;
+ public CustomizedSettingModel CustomizedSetting
+ {
+ get => _CustomizedSetting;
+ set => SetProperty(ref _CustomizedSetting, value);
+ }
+ #endregion
- private Setting _setting;
+ #region DiagnosticSetting
+ private DiagnosticSettingModel _diagnosticSetting;
+ public DiagnosticSettingModel DiagnosticSetting
+ {
+ get => _diagnosticSetting;
+ set => SetProperty(ref _diagnosticSetting, value);
+ }
+ #endregion
- private ReflectionOptions _saveReflectionOptions = new() { CheckValueEquals = true };
+ #region ModSetting
+ private ModSettingModel _modSetting;
+ public ModSettingModel ModSetting
+ {
+ get => _modSetting;
+ set => SetProperty(ref _modSetting, value);
+ }
+ #endregion
+
+
+ private readonly Setting _setting;
+
+ private readonly ReflectionOptions _saveReflectionOptions = new() { CheckValueEquals = true };
public SettingModel()
: this(new("")) { }
@@ -66,14 +91,39 @@ public class SettingModel : ObservableClass
GraphicsSetting = LoadSetting();
InteractiveSetting = LoadSetting();
SystemSetting = LoadSetting();
+ CustomizedSetting = LoadCustomizedSetting(setting);
+ DiagnosticSetting = LoadSetting();
+ DiagnosticSetting.SetAutoCalToSetting(setting);
+ ModSetting = LoadModSetting(setting);
+ }
+
+ private ModSettingModel LoadModSetting(Setting setting)
+ {
+ var settingModel = new ModSettingModel(setting);
+ return settingModel;
+ }
+
+ private CustomizedSettingModel LoadCustomizedSetting(Setting setting)
+ {
+ var model = new CustomizedSettingModel();
+ if (setting[CustomizedSettingModel.TargetName] is ILine line && line.Count > 0)
+ {
+ foreach (var sub in line)
+ model.Links.Add(new(sub.Name, sub.Info));
+ }
+ else
+ {
+ setting.Remove(CustomizedSettingModel.TargetName);
+ }
+ return model;
}
private T LoadSetting()
where T : new()
{
- var setting = new T();
- ReflectionUtils.SetValue(_setting, setting);
- return setting;
+ var settingModel = new T();
+ ReflectionUtils.SetValue(_setting, settingModel);
+ return settingModel;
}
public void Save()
@@ -81,11 +131,16 @@ public class SettingModel : ObservableClass
SaveSetting(GraphicsSetting);
SaveSetting(InteractiveSetting);
SaveSetting(SystemSetting);
+ SaveSetting(DiagnosticSetting);
+ DiagnosticSetting.SetAutoCalToSetting(_setting);
+ foreach (var link in CustomizedSetting.Links)
+ _setting[CustomizedSettingModel.TargetName].Add(new Sub(link.Name, link.Link));
+ ModSetting.Save(_setting);
File.WriteAllText(FilePath, _setting.ToString());
}
- private void SaveSetting(object setting)
+ private void SaveSetting(object settingModel)
{
- ReflectionUtils.SetValue(setting, _setting, _saveReflectionOptions);
+ ReflectionUtils.SetValue(settingModel, _setting, _saveReflectionOptions);
}
}
diff --git a/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs b/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs
index e5c5394..87b974a 100644
--- a/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs
+++ b/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs
@@ -9,34 +9,6 @@ public class SystemSettingModel : ObservableClass
///
public bool DiagnosisDayEnable { get; } = true;
- #region Diagnosis
- private bool _diagnosis;
-
- ///
- /// 是否启用数据收集
- ///
- [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Diagnosis))]
- public bool Diagnosis
- {
- get => _diagnosis;
- set => SetProperty(ref _diagnosis, value);
- }
- #endregion
-
- #region DiagnosisInterval
- private int _diagnosisInterval;
-
- ///
- /// 数据收集频率
- ///
- [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.DiagnosisInterval))]
- public int DiagnosisInterval
- {
- get => _diagnosisInterval;
- set => SetProperty(ref _diagnosisInterval, value);
- }
- #endregion
-
#region AutoSaveInterval
private int _autoSaveInterval;
diff --git a/VPet.Solution/SimpleObservable/ObservableCommand/ExecuteAsyncEventHandler.cs b/VPet.Solution/SimpleObservable/ObservableCommand/ExecuteAsyncEventHandler.cs
index 07004c4..6cb2552 100644
--- a/VPet.Solution/SimpleObservable/ObservableCommand/ExecuteAsyncEventHandler.cs
+++ b/VPet.Solution/SimpleObservable/ObservableCommand/ExecuteAsyncEventHandler.cs
@@ -8,5 +8,5 @@ public delegate Task ExecuteAsyncEventHandler();
///
/// 异步执行命令事件
///
-/// 值
+/// 参数
public delegate Task ExecuteAsyncEventHandler(T parameter);
diff --git a/VPet.Solution/Utils/Utils.cs b/VPet.Solution/Utils/Utils.cs
index 0e4e157..7b1aec3 100644
--- a/VPet.Solution/Utils/Utils.cs
+++ b/VPet.Solution/Utils/Utils.cs
@@ -18,21 +18,27 @@ public static class Utils
public const int DecodePixelHeight = 250;
public static char[] Separator { get; } = new char[] { '_' };
- //public static BitmapImage LoadImageToStream(string imagePath)
- //{
- // BitmapImage bitmapImage = new();
- // bitmapImage.BeginInit();
- // bitmapImage.DecodePixelWidth = DecodePixelWidth;
- // try
- // {
- // bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream;
- // }
- // finally
- // {
- // bitmapImage.EndInit();
- // }
- // return bitmapImage;
- //}
+ ///
+ /// 载入图片到流
+ ///
+ /// 图片路径
+ /// 图片
+ public static BitmapImage LoadImageToStream(string imagePath)
+ {
+ if (string.IsNullOrWhiteSpace(imagePath) || File.Exists(imagePath) is false)
+ return null;
+ BitmapImage bitmapImage = new();
+ bitmapImage.BeginInit();
+ try
+ {
+ bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream;
+ }
+ finally
+ {
+ bitmapImage.EndInit();
+ }
+ return bitmapImage;
+ }
///
/// 载入图片至内存流
@@ -100,7 +106,7 @@ public static class Utils
/// 打开文件
///
/// 文件路径
- public static void OpenFile(string filePath)
+ public static void OpenLink(string filePath)
{
System.Diagnostics.Process
.Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true })
diff --git a/VPet.Solution/VPet.Solution.csproj b/VPet.Solution/VPet.Solution.csproj
index 1087f57..dfd2f13 100644
--- a/VPet.Solution/VPet.Solution.csproj
+++ b/VPet.Solution/VPet.Solution.csproj
@@ -90,15 +90,20 @@
+
+
+
+
+
@@ -110,6 +115,7 @@
+
diff --git a/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs b/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs
index a12d9c2..f3a04ea 100644
--- a/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs
+++ b/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs
@@ -77,7 +77,7 @@ public class SaveWindowVM : ObservableClass
private void OpenFileCommand_ExecuteCommand(SaveModel parameter)
{
- Utils.OpenFile(parameter.FilePath);
+ Utils.OpenLink(parameter.FilePath);
}
public void RefreshShowSaves(string name)
diff --git a/VPet.Solution/ViewModels/SettingEditor/CustomizedSettingPageVM.cs b/VPet.Solution/ViewModels/SettingEditor/CustomizedSettingPageVM.cs
index 7f38a71..7ba1b9f 100644
--- a/VPet.Solution/ViewModels/SettingEditor/CustomizedSettingPageVM.cs
+++ b/VPet.Solution/ViewModels/SettingEditor/CustomizedSettingPageVM.cs
@@ -1,9 +1,112 @@
-using System;
+using HKW.HKWUtils.Observable;
+using LinePutScript.Localization.WPF;
+using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
+using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor;
-public class CustomizedSettingPageVM { }
+public class CustomizedSettingPageVM : ObservableClass
+{
+ #region ObservableProperty
+ #region CustomizedSetting
+
+ private CustomizedSettingModel _customizedSetting;
+ public CustomizedSettingModel CustomizedSetting
+ {
+ get => _customizedSetting;
+ set => SetProperty(ref _customizedSetting, value);
+ }
+ #endregion
+
+ #region SearchSetting
+ private string _searchSetting;
+ public string SearchLink
+ {
+ get => _searchSetting;
+ set
+ {
+ SetProperty(ref _searchSetting, value);
+ RefreshShowLinks(value);
+ }
+ }
+ #endregion
+
+ #region ShowLinks
+ private IEnumerable _showLinks;
+ public IEnumerable ShowLinks
+ {
+ get => _showLinks;
+ set => SetProperty(ref _showLinks, value);
+ }
+ #endregion
+ #endregion
+
+ #region Command
+ public ObservableCommand AddLinkCommand { get; } = new();
+ public ObservableCommand RemoveLinkCommand { get; } = new();
+ public ObservableCommand ClearLinksCommand { get; } = new();
+ #endregion
+ public CustomizedSettingPageVM()
+ {
+ SettingWindowVM.Current.PropertyChangedX += Current_PropertyChangedX;
+ AddLinkCommand.ExecuteCommand += AddLinkCommand_ExecuteCommand;
+ RemoveLinkCommand.ExecuteCommand += RemoveLinkCommand_ExecuteCommand;
+ ClearLinksCommand.ExecuteCommand += ClearLinksCommand_ExecuteCommand;
+ }
+
+ private void ClearLinksCommand_ExecuteCommand()
+ {
+ if (
+ MessageBox.Show(
+ "确定清空吗".Translate(),
+ "",
+ MessageBoxButton.YesNo,
+ MessageBoxImage.Warning
+ )
+ is not MessageBoxResult.Yes
+ )
+ return;
+ SearchLink = string.Empty;
+ CustomizedSetting.Links.Clear();
+ }
+
+ private void AddLinkCommand_ExecuteCommand()
+ {
+ SearchLink = string.Empty;
+ CustomizedSetting.Links.Add(new());
+ }
+
+ private void RemoveLinkCommand_ExecuteCommand(LinkModel parameter)
+ {
+ CustomizedSetting.Links.Remove(parameter);
+ }
+
+ private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
+ {
+ if (
+ e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
+ && sender.CurrentSetting is not null
+ )
+ {
+ CustomizedSetting = sender.CurrentSetting.CustomizedSetting;
+ SearchLink = string.Empty;
+ }
+ }
+
+ public void RefreshShowLinks(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ ShowLinks = CustomizedSetting.Links;
+ else
+ ShowLinks = CustomizedSetting.Links.Where(
+ s => s.Name.Contains(SearchLink, StringComparison.OrdinalIgnoreCase)
+ );
+ }
+}
diff --git a/VPet.Solution/ViewModels/SettingEditor/DiagnosticSettingPageVM.cs b/VPet.Solution/ViewModels/SettingEditor/DiagnosticSettingPageVM.cs
index 7d7b780..4e92bfa 100644
--- a/VPet.Solution/ViewModels/SettingEditor/DiagnosticSettingPageVM.cs
+++ b/VPet.Solution/ViewModels/SettingEditor/DiagnosticSettingPageVM.cs
@@ -3,7 +3,32 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor;
-public class DiagnosticSettingPageVM { }
+public class DiagnosticSettingPageVM : ObservableClass
+{
+ private DiagnosticSettingModel _diagnosticSetting;
+ public DiagnosticSettingModel DiagnosticSetting
+ {
+ get => _diagnosticSetting;
+ set => SetProperty(ref _diagnosticSetting, value);
+ }
+
+ public DiagnosticSettingPageVM()
+ {
+ SettingWindowVM.Current.PropertyChangedX += Current_PropertyChangedX;
+ }
+
+ private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
+ {
+ if (
+ e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
+ && sender.CurrentSetting is not null
+ )
+ {
+ DiagnosticSetting = sender.CurrentSetting.DiagnosticSetting;
+ }
+ }
+}
diff --git a/VPet.Solution/ViewModels/SettingEditor/ModSettingModelModel.cs b/VPet.Solution/ViewModels/SettingEditor/ModSettingModelModel.cs
new file mode 100644
index 0000000..709f687
--- /dev/null
+++ b/VPet.Solution/ViewModels/SettingEditor/ModSettingModelModel.cs
@@ -0,0 +1,5 @@
+namespace VPet.Solution.ViewModels.SettingEditor;
+
+internal class ModSettingModelModel
+{
+}
\ No newline at end of file
diff --git a/VPet.Solution/ViewModels/SettingEditor/ModSettingPageVM.cs b/VPet.Solution/ViewModels/SettingEditor/ModSettingPageVM.cs
index c5d63c4..cc277d2 100644
--- a/VPet.Solution/ViewModels/SettingEditor/ModSettingPageVM.cs
+++ b/VPet.Solution/ViewModels/SettingEditor/ModSettingPageVM.cs
@@ -1,9 +1,164 @@
-using System;
+using HKW.HKWUtils.Observable;
+using LinePutScript.Localization.WPF;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
+using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor;
-public class ModSettingPageVM { }
+public class ModSettingPageVM : ObservableClass
+{
+ #region ObservableProperty
+ private ModSettingModel _modSetting;
+ public ModSettingModel ModSetting
+ {
+ get => _modSetting;
+ set => SetProperty(ref _modSetting, value);
+ }
+
+ #region ShowMods
+ private IEnumerable _showMods;
+ public IEnumerable ShowMods
+ {
+ get => _showMods;
+ set => SetProperty(ref _showMods, value);
+ }
+ #endregion
+
+ #region SearchMod
+ private string _searchMod;
+ public string SearchMod
+ {
+ get => _searchMod;
+ set
+ {
+ SetProperty(ref _searchMod, value);
+ RefreshShowMods(value);
+ }
+ }
+ #endregion
+
+ #region CurrentModMoel
+ private ModModel _currentModModel;
+ public ModModel CurrentModMoel
+ {
+ get => _currentModModel;
+ set
+ {
+ if (_currentModModel is not null)
+ _currentModModel.PropertyChangingX -= CurrentModModel_PropertyChangingX;
+ SetProperty(ref _currentModModel, value);
+ if (value is not null)
+ _currentModModel.PropertyChangingX += CurrentModModel_PropertyChangingX;
+ }
+ }
+
+ private void CurrentModModel_PropertyChangingX(ModModel sender, PropertyChangingXEventArgs e)
+ {
+ if (e.PropertyName == nameof(ModModel.IsPass) && e.NewValue is true)
+ {
+ if (
+ MessageBox.Show(
+ "是否启用 {0} 的代码插件?\n一经启用,该插件将会允许访问该系统(包括外部系统)的所有数据\n如果您不确定,请先使用杀毒软件查杀检查".Translate(
+ sender.Name
+ ),
+ "启用 {0} 的代码插件?".Translate(sender.Name),
+ MessageBoxButton.YesNo,
+ MessageBoxImage.Warning
+ ) is MessageBoxResult.Yes
+ )
+ {
+ sender.IsEnabled = true;
+ }
+ else
+ e.Cancel = true;
+ }
+ }
+ #endregion
+
+
+ #endregion
+
+ #region Command
+ //public ObservableCommand AddModCommand { get; } = new();
+ //public ObservableCommand RemoveModCommand { get; } = new();
+ public ObservableCommand ClearFailModsCommand { get; } = new();
+ public ObservableCommand ClearModsCommand { get; } = new();
+ public ObservableCommand OpenModPathCommand { get; } = new();
+ public ObservableCommand OpenSteamCommunityCommand { get; } = new();
+ #endregion
+
+
+ public ModSettingPageVM()
+ {
+ SettingWindowVM.Current.PropertyChangedX += Current_PropertyChangedX;
+ ClearFailModsCommand.ExecuteCommand += ClearFailModsCommand_ExecuteCommand;
+ ClearModsCommand.ExecuteCommand += ClearModsCommand_ExecuteCommand;
+ OpenModPathCommand.ExecuteCommand += OpenModPathCommand_ExecuteCommand;
+ OpenSteamCommunityCommand.ExecuteCommand += OpenSteamCommunityCommand_ExecuteCommand;
+ }
+
+ private void ClearModsCommand_ExecuteCommand()
+ {
+ if (
+ MessageBox.Show("确定清除全部模组吗", "", MessageBoxButton.YesNo, MessageBoxImage.Warning)
+ is not MessageBoxResult.Yes
+ )
+ return;
+ ModSetting.Mods.Clear();
+ SearchMod = string.Empty;
+ }
+
+ private void ClearFailModsCommand_ExecuteCommand()
+ {
+ if (
+ MessageBox.Show("确定清除全部失效模组吗", "", MessageBoxButton.YesNo, MessageBoxImage.Warning)
+ is not MessageBoxResult.Yes
+ )
+ return;
+ foreach (var mod in ModSetting.Mods.AsEnumerable())
+ {
+ if (mod.IsEnabled is null)
+ ModSetting.Mods.Remove(mod);
+ }
+ SearchMod = string.Empty;
+ }
+
+ private void OpenSteamCommunityCommand_ExecuteCommand(ModModel parameter)
+ {
+ Utils.OpenLink(
+ "https://steamcommunity.com/sharedfiles/filedetails/?id=" + parameter.ItemId
+ );
+ }
+
+ private void OpenModPathCommand_ExecuteCommand(ModModel parameter)
+ {
+ Utils.OpenLink(parameter.ModPath);
+ }
+
+ private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
+ {
+ if (
+ e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
+ && sender.CurrentSetting is not null
+ )
+ {
+ ModSetting = sender.CurrentSetting.ModSetting;
+ SearchMod = string.Empty;
+ }
+ }
+
+ public void RefreshShowMods(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ ShowMods = ModSetting.Mods;
+ else
+ ShowMods = ModSetting.Mods.Where(
+ s => s.Name.Contains(SearchMod, StringComparison.OrdinalIgnoreCase)
+ );
+ }
+}
diff --git a/VPet.Solution/ViewModels/SettingEditor/SettingWindowVM.cs b/VPet.Solution/ViewModels/SettingEditor/SettingWindowVM.cs
index e86fcc6..f9ef59a 100644
--- a/VPet.Solution/ViewModels/SettingEditor/SettingWindowVM.cs
+++ b/VPet.Solution/ViewModels/SettingEditor/SettingWindowVM.cs
@@ -94,7 +94,7 @@ public class SettingWindowVM : ObservableClass
private void OpenFileCommand_ExecuteCommand(SettingModel parameter)
{
- Utils.OpenFile(parameter.FilePath);
+ Utils.OpenLink(parameter.FilePath);
}
private void SaveAllSettingCommand_ExecuteCommand()
diff --git a/VPet.Solution/Views/SettingEditor/CustomizedSettingPage.xaml b/VPet.Solution/Views/SettingEditor/CustomizedSettingPage.xaml
index 13ea90c..23c9235 100644
--- a/VPet.Solution/Views/SettingEditor/CustomizedSettingPage.xaml
+++ b/VPet.Solution/Views/SettingEditor/CustomizedSettingPage.xaml
@@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:h="clr-namespace:HKW.WPF.Helpers"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -15,43 +16,80 @@
mc:Ignorable="d">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml b/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml
index 98120bd..04755b5 100644
--- a/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml
+++ b/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml
@@ -13,107 +13,71 @@
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- :
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+ ItemsSource="{Binding DiagnosticSetting.DiagnosisIntervals}"
+ SelectedItem="{Binding DiagnosticSetting.DiagnosisInterval}"
+ Style="{DynamicResource ComboBox_BaseStyle}" />
+
-
-
+
+
diff --git a/VPet.Solution/Views/SettingEditor/ModSettingPage.xaml b/VPet.Solution/Views/SettingEditor/ModSettingPage.xaml
index eaa0bfd..9e35474 100644
--- a/VPet.Solution/Views/SettingEditor/ModSettingPage.xaml
+++ b/VPet.Solution/Views/SettingEditor/ModSettingPage.xaml
@@ -3,233 +3,231 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:h="clr-namespace:HKW.WPF.Helpers"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SettingEditor"
Title="ModSettingsPage"
- d:DataContext="{d:DesignInstance Type=vm:GraphicsSettingPageVM}"
+ d:DataContext="{d:DesignInstance Type=vm:ModSettingPageVM}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
-
-
-
+ FontWeight="Bold"
+ Style="{DynamicResource Label_BaseStyle}" />
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+ FontWeight="Bold"
+ Style="{DynamicResource Label_BaseStyle}" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+