VPet.Solution 实装 CustomizedSetting DiagnosticSetting ModSetting

This commit is contained in:
Hakoyu 2024-01-16 04:46:14 +08:00
parent 262b3b4230
commit 7528763fd9
21 changed files with 1327 additions and 392 deletions

View File

@ -8,6 +8,16 @@
<c:StringFormatConverter x:Key="StringFormatConverter" /> <c:StringFormatConverter x:Key="StringFormatConverter" />
<c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" /> <c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" />
<c:BoolToVisibilityConverter x:Key="FalseToHiddenConverter" /> <c:BoolToVisibilityConverter x:Key="FalseToHiddenConverter" />
<c:BoolToVisibilityConverter
x:Key="FalseToVisibleConverter"
FalseVisibilityValue="Visible"
NullValue="True"
TrueVisibilityValue="Hidden" />
<c:NullToVisibilityConverter x:Key="NotNullToVisibleConverter" />
<c:NullToVisibilityConverter
x:Key="NullToVisibleConverter"
NotNullVisibilityValue="Hidden"
NullVisibilityValue="Visible" />
<c:EqualsConverter x:Key="EqualsConverter" /> <c:EqualsConverter x:Key="EqualsConverter" />
<c:EqualsConverter x:Key="NotEqualsConverter" Inverter="True" /> <c:EqualsConverter x:Key="NotEqualsConverter" Inverter="True" />
<c:ValueToBoolConverter x:Key="NullToFalse" Invert="True" /> <c:ValueToBoolConverter x:Key="NullToFalse" Invert="True" />

View File

@ -13,7 +13,7 @@ public class BoolInverter : ValueConverterBase
public static readonly DependencyProperty NullValueProperty = DependencyProperty.Register( public static readonly DependencyProperty NullValueProperty = DependencyProperty.Register(
nameof(NullValue), nameof(NullValue),
typeof(bool), typeof(bool),
typeof(AllIsBoolToVisibilityConverter), typeof(BoolInverter),
new PropertyMetadata(false) new PropertyMetadata(false)
); );

View File

@ -0,0 +1,60 @@
using System.ComponentModel;
using System.Globalization;
using System.Windows;
namespace HKW.WPF.Converters;
public class NullToVisibilityConverter : ValueConverterBase
{
/// <summary>
///
/// </summary>
public static readonly DependencyProperty NullVisibilityValueProperty =
DependencyProperty.Register(
nameof(NullVisibilityValue),
typeof(Visibility),
typeof(NullToVisibilityConverter),
new PropertyMetadata(Visibility.Hidden)
);
/// <summary>
/// NULL时的可见度
/// </summary>
[DefaultValue(Visibility.Hidden)]
public Visibility NullVisibilityValue
{
get => (Visibility)GetValue(NullVisibilityValueProperty);
set => SetValue(NullVisibilityValueProperty, value);
}
/// <summary>
///
/// </summary>
public static readonly DependencyProperty NotNullVisibilityValueProperty =
DependencyProperty.Register(
nameof(NotNullVisibilityValue),
typeof(Visibility),
typeof(NullToVisibilityConverter),
new PropertyMetadata(Visibility.Visible)
);
/// <summary>
/// 不为NULL时的可见度
/// </summary>
[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;
}
}

View File

@ -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;
/// <summary>
/// 模组加载器
/// </summary>
public class ModLoader
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; }
/// <summary>
/// 作者
/// </summary>
public string Author { get; }
/// <summary>
/// 如果是上传至Steam,则为SteamUserID
/// </summary>
public long AuthorID { get; }
/// <summary>
/// 上传至Steam的ItemID
/// </summary>
public ulong ItemID { get; }
/// <summary>
/// 简介
/// </summary>
public string Intro { get; }
/// <summary>
/// 模组路径
/// </summary>
public string ModPath { get; }
/// <summary>
/// 支持的游戏版本
/// </summary>
public int GameVer { get; }
/// <summary>
/// 版本
/// </summary>
public int Ver { get; }
/// <summary>
/// 标签
/// </summary>
public HashSet<string> Tags { get; } = new();
/// <summary>
/// 缓存数据
/// </summary>
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;
}
}
}
}

View File

@ -0,0 +1,55 @@
using System.Collections.ObjectModel;
namespace VPet.Solution.Models.SettingEditor;
public class CustomizedSettingModel : ObservableClass<CustomizedSettingModel>
{
public const string TargetName = "diy";
#region Links
private ObservableCollection<LinkModel> _links = new();
public ObservableCollection<LinkModel> Links
{
get => _links;
set => SetProperty(ref _links, value);
}
#endregion
}
public class LinkModel : ObservableClass<LinkModel>
{
#region Name
private string _name;
/// <summary>
/// 名称
/// </summary>
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Link
private string _link;
/// <summary>
/// 链接
/// </summary>
public string Link
{
get => _link;
set => SetProperty(ref _link, value);
}
#endregion
public LinkModel() { }
public LinkModel(string name, string link)
{
Name = name;
Link = link;
}
}

View File

@ -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<DiagnosticSettingModel>
{
#region AutoCal
private bool _autoCal;
/// <summary>
/// 自动修复超模
/// </summary>
public bool AutoCal
{
get => _autoCal;
set => SetProperty(ref _autoCal, value);
}
#endregion
#region Diagnosis
private bool _diagnosis;
/// <summary>
/// 是否启用数据收集
/// </summary>
[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;
/// <summary>
/// 数据收集频率
/// </summary>
[DefaultValue(200)]
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.DiagnosisInterval))]
public int DiagnosisInterval
{
get => _diagnosisInterval;
set => SetProperty(ref _diagnosisInterval, value);
}
public static ObservableCollection<int> 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);
}
}

View File

@ -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<ModSettingModel>
{
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<string, ModLoader> 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<ModModel> _mods = new();
public ObservableCollection<ModModel> 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<ModModel>
{
#region Name
private string _name;
/// <summary>
/// 名称
/// </summary>
[ReflectionProperty(nameof(ModLoader.Name))]
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Description
private string _description;
/// <summary>
/// 描述
/// </summary>
[ReflectionProperty(nameof(ModLoader.Intro))]
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
#region Author
private string _author;
/// <summary>
/// 作者
/// </summary>
[ReflectionProperty(nameof(ModLoader.Author))]
public string Author
{
get => _author;
set => SetProperty(ref _author, value);
}
#endregion
#region ModVersion
private int _modVersion;
/// <summary>
/// 模组版本
/// </summary>
[ReflectionProperty(nameof(ModLoader.Ver))]
public int ModVersion
{
get => _modVersion;
set => SetProperty(ref _modVersion, value);
}
#endregion
#region GameVersion
private int _gameVersion;
/// <summary>
/// 游戏版本
/// </summary>
[ReflectionProperty(nameof(ModLoader.GameVer))]
public int GameVersion
{
get => _gameVersion;
set => SetProperty(ref _gameVersion, value);
}
#endregion
#region Tags
private HashSet<string> _tags;
/// <summary>
/// 功能
/// </summary>
[ReflectionProperty(nameof(ModLoader.Tags))]
public HashSet<string> Tags
{
get => _tags;
set => SetProperty(ref _tags, value);
}
#endregion
#region Image
private BitmapImage _image;
/// <summary>
/// 图像
/// </summary>
[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;
/// <summary>
/// 已启用
/// </summary>
public bool? IsEnabled
{
get => _isEnabled;
set => SetProperty(ref _isEnabled, value);
}
#endregion
#region IsPass
private bool _isPass;
/// <summary>
/// 是通过检查的代码模组
/// </summary>
public bool IsPass
{
get => _isPass;
set => SetProperty(ref _isPass, value);
}
#endregion
#region IsMsg
private bool _isMsg;
/// <summary>
/// 是含有代码的模组
/// </summary>
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 = "已损坏";
}
}

View File

@ -50,12 +50,37 @@ public class SettingModel : ObservableClass<SettingModel>
} }
#endregion #endregion
private static HashSet<string> _settingProperties = #region CustomizedSetting
new(typeof(Setting).GetProperties().Select(p => p.Name)); 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() public SettingModel()
: this(new("")) { } : this(new("")) { }
@ -66,14 +91,39 @@ public class SettingModel : ObservableClass<SettingModel>
GraphicsSetting = LoadSetting<GraphicsSettingModel>(); GraphicsSetting = LoadSetting<GraphicsSettingModel>();
InteractiveSetting = LoadSetting<InteractiveSettingModel>(); InteractiveSetting = LoadSetting<InteractiveSettingModel>();
SystemSetting = LoadSetting<SystemSettingModel>(); SystemSetting = LoadSetting<SystemSettingModel>();
CustomizedSetting = LoadCustomizedSetting(setting);
DiagnosticSetting = LoadSetting<DiagnosticSettingModel>();
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<T>() private T LoadSetting<T>()
where T : new() where T : new()
{ {
var setting = new T(); var settingModel = new T();
ReflectionUtils.SetValue(_setting, setting); ReflectionUtils.SetValue(_setting, settingModel);
return setting; return settingModel;
} }
public void Save() public void Save()
@ -81,11 +131,16 @@ public class SettingModel : ObservableClass<SettingModel>
SaveSetting(GraphicsSetting); SaveSetting(GraphicsSetting);
SaveSetting(InteractiveSetting); SaveSetting(InteractiveSetting);
SaveSetting(SystemSetting); 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()); 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);
} }
} }

View File

@ -9,34 +9,6 @@ public class SystemSettingModel : ObservableClass<SystemSettingModel>
/// </summary> /// </summary>
public bool DiagnosisDayEnable { get; } = true; public bool DiagnosisDayEnable { get; } = true;
#region Diagnosis
private bool _diagnosis;
/// <summary>
/// 是否启用数据收集
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Diagnosis))]
public bool Diagnosis
{
get => _diagnosis;
set => SetProperty(ref _diagnosis, value);
}
#endregion
#region DiagnosisInterval
private int _diagnosisInterval;
/// <summary>
/// 数据收集频率
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.DiagnosisInterval))]
public int DiagnosisInterval
{
get => _diagnosisInterval;
set => SetProperty(ref _diagnosisInterval, value);
}
#endregion
#region AutoSaveInterval #region AutoSaveInterval
private int _autoSaveInterval; private int _autoSaveInterval;

View File

@ -8,5 +8,5 @@ public delegate Task ExecuteAsyncEventHandler();
/// <summary> /// <summary>
/// 异步执行命令事件 /// 异步执行命令事件
/// </summary> /// </summary>
/// <param name="parameter"></param> /// <param name="parameter">参数</param>
public delegate Task ExecuteAsyncEventHandler<T>(T parameter); public delegate Task ExecuteAsyncEventHandler<T>(T parameter);

View File

@ -18,21 +18,27 @@ public static class Utils
public const int DecodePixelHeight = 250; public const int DecodePixelHeight = 250;
public static char[] Separator { get; } = new char[] { '_' }; public static char[] Separator { get; } = new char[] { '_' };
//public static BitmapImage LoadImageToStream(string imagePath) /// <summary>
//{ /// 载入图片到流
// BitmapImage bitmapImage = new(); /// </summary>
// bitmapImage.BeginInit(); /// <param name="imagePath">图片路径</param>
// bitmapImage.DecodePixelWidth = DecodePixelWidth; /// <returns>图片</returns>
// try public static BitmapImage LoadImageToStream(string imagePath)
// { {
// bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream; if (string.IsNullOrWhiteSpace(imagePath) || File.Exists(imagePath) is false)
// } return null;
// finally BitmapImage bitmapImage = new();
// { bitmapImage.BeginInit();
// bitmapImage.EndInit(); try
// } {
// return bitmapImage; bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream;
//} }
finally
{
bitmapImage.EndInit();
}
return bitmapImage;
}
/// <summary> /// <summary>
/// 载入图片至内存流 /// 载入图片至内存流
@ -100,7 +106,7 @@ public static class Utils
/// 打开文件 /// 打开文件
/// </summary> /// </summary>
/// <param name="filePath">文件路径</param> /// <param name="filePath">文件路径</param>
public static void OpenFile(string filePath) public static void OpenLink(string filePath)
{ {
System.Diagnostics.Process System.Diagnostics.Process
.Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true }) .Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true })

View File

@ -90,15 +90,20 @@
<Compile Include="Converters\IsBoolConverter.cs" /> <Compile Include="Converters\IsBoolConverter.cs" />
<Compile Include="Converters\MarginConverter.cs" /> <Compile Include="Converters\MarginConverter.cs" />
<Compile Include="Converters\MediaColorToBrushConverter.cs" /> <Compile Include="Converters\MediaColorToBrushConverter.cs" />
<Compile Include="Converters\NullToVisibilityConverter.cs" />
<Compile Include="Converters\StringFormatConverter.cs" /> <Compile Include="Converters\StringFormatConverter.cs" />
<Compile Include="Converters\BoolToVisibilityConverter.cs" /> <Compile Include="Converters\BoolToVisibilityConverter.cs" />
<Compile Include="Converters\MaxConverter.cs" /> <Compile Include="Converters\MaxConverter.cs" />
<Compile Include="Converters\ValueToBoolConverter.cs" /> <Compile Include="Converters\ValueToBoolConverter.cs" />
<Compile Include="Converters\BoolInverter.cs" /> <Compile Include="Converters\BoolInverter.cs" />
<Compile Include="Models\ModLoader.cs" />
<Compile Include="Models\SaveViewer\SaveModel.cs" /> <Compile Include="Models\SaveViewer\SaveModel.cs" />
<Compile Include="Models\SaveViewer\StatisticDataModel.cs" /> <Compile Include="Models\SaveViewer\StatisticDataModel.cs" />
<Compile Include="Models\SettingEditor\CustomizedSettingModel.cs" />
<Compile Include="Models\SettingEditor\DiagnosticSettingModel.cs" />
<Compile Include="Models\SettingEditor\GraphicsSettingModel.cs" /> <Compile Include="Models\SettingEditor\GraphicsSettingModel.cs" />
<Compile Include="Models\SettingEditor\InteractiveSettingModel.cs" /> <Compile Include="Models\SettingEditor\InteractiveSettingModel.cs" />
<Compile Include="Models\SettingEditor\ModSettingModel.cs" />
<Compile Include="Models\SettingEditor\SystemSettingModel.cs" /> <Compile Include="Models\SettingEditor\SystemSettingModel.cs" />
<Compile Include="Utils\ClearFocus.cs" /> <Compile Include="Utils\ClearFocus.cs" />
<Compile Include="Utils\ElementHelper.cs" /> <Compile Include="Utils\ElementHelper.cs" />
@ -110,6 +115,7 @@
<Compile Include="ViewModels\SaveViewer\SaveWindowVM.cs" /> <Compile Include="ViewModels\SaveViewer\SaveWindowVM.cs" />
<Compile Include="ViewModels\SettingEditor\CustomizedSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\CustomizedSettingPageVM.cs" />
<Compile Include="ViewModels\SettingEditor\DiagnosticSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\DiagnosticSettingPageVM.cs" />
<Compile Include="ViewModels\SettingEditor\ModSettingModelModel.cs" />
<Compile Include="ViewModels\SettingEditor\ModSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\ModSettingPageVM.cs" />
<Compile Include="Models\SettingEditor\SettingModel.cs" /> <Compile Include="Models\SettingEditor\SettingModel.cs" />
<Compile Include="ViewModels\SettingEditor\SystemSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\SystemSettingPageVM.cs" />

View File

@ -77,7 +77,7 @@ public class SaveWindowVM : ObservableClass<SaveWindowVM>
private void OpenFileCommand_ExecuteCommand(SaveModel parameter) private void OpenFileCommand_ExecuteCommand(SaveModel parameter)
{ {
Utils.OpenFile(parameter.FilePath); Utils.OpenLink(parameter.FilePath);
} }
public void RefreshShowSaves(string name) public void RefreshShowSaves(string name)

View File

@ -1,9 +1,112 @@
using System; using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor; namespace VPet.Solution.ViewModels.SettingEditor;
public class CustomizedSettingPageVM { } public class CustomizedSettingPageVM : ObservableClass<CustomizedSettingPageVM>
{
#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<LinkModel> _showLinks;
public IEnumerable<LinkModel> ShowLinks
{
get => _showLinks;
set => SetProperty(ref _showLinks, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddLinkCommand { get; } = new();
public ObservableCommand<LinkModel> 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)
);
}
}

View File

@ -3,7 +3,32 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor; namespace VPet.Solution.ViewModels.SettingEditor;
public class DiagnosticSettingPageVM { } public class DiagnosticSettingPageVM : ObservableClass<DiagnosticSettingPageVM>
{
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;
}
}
}

View File

@ -0,0 +1,5 @@
namespace VPet.Solution.ViewModels.SettingEditor;
internal class ModSettingModelModel
{
}

View File

@ -1,9 +1,164 @@
using System; using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using VPet.Solution.Models.SettingEditor;
namespace VPet.Solution.ViewModels.SettingEditor; namespace VPet.Solution.ViewModels.SettingEditor;
public class ModSettingPageVM { } public class ModSettingPageVM : ObservableClass<ModSettingPageVM>
{
#region ObservableProperty
private ModSettingModel _modSetting;
public ModSettingModel ModSetting
{
get => _modSetting;
set => SetProperty(ref _modSetting, value);
}
#region ShowMods
private IEnumerable<ModModel> _showMods;
public IEnumerable<ModModel> 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<ModModel> RemoveModCommand { get; } = new();
public ObservableCommand ClearFailModsCommand { get; } = new();
public ObservableCommand ClearModsCommand { get; } = new();
public ObservableCommand<ModModel> OpenModPathCommand { get; } = new();
public ObservableCommand<ModModel> 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)
);
}
}

View File

@ -94,7 +94,7 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
private void OpenFileCommand_ExecuteCommand(SettingModel parameter) private void OpenFileCommand_ExecuteCommand(SettingModel parameter)
{ {
Utils.OpenFile(parameter.FilePath); Utils.OpenLink(parameter.FilePath);
} }
private void SaveAllSettingCommand_ExecuteCommand() private void SaveAllSettingCommand_ExecuteCommand()

View File

@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 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:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor" xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -15,43 +16,80 @@
mc:Ignorable="d"> mc:Ignorable="d">
<Grid> <Grid>
<StackPanel> <Grid.RowDefinitions>
<TextBlock Background="{x:Null}" TextWrapping="Wrap"> <RowDefinition Height="Auto" />
<Run <RowDefinition Height="Auto" />
FontSize="18" <RowDefinition Height="Auto" />
FontWeight="Bold" <RowDefinition />
Text="{ll:Str 自定义链接}" /><LineBreak /> </Grid.RowDefinitions>
<Run Text="{ll:Str '在自定栏添加快捷方式/网页/快捷键, 可以便携启动想要的功能'}" /><LineBreak /> <TextBlock TextWrapping="Wrap">
<Run Text="{ll:Str '键盘快捷键编写方法请参考'}" /> <Hyperlink d:Click="sendkey_click"> <Run
<Run Text="{ll:Str '键盘快捷键 通用注解'}" /> FontSize="18"
</Hyperlink><LineBreak /> FontWeight="Bold"
<Run Text="{ll:Str '右键进行排序/删除等操作'}" /> Text="{ll:Str 自定义链接}" /><LineBreak />
</TextBlock> <Run Text="{ll:Str '在自定栏添加快捷方式/网页/快捷键, 可以便携启动想要的功能'}" /><LineBreak />
<Grid> <Run Text="{ll:Str '键盘快捷键编写方法请参考'}" /> <Hyperlink>
<Grid.ColumnDefinitions> <Run Text="{ll:Str '键盘快捷键 通用注解'}" />
<ColumnDefinition Width="*" /> </Hyperlink><LineBreak />
<ColumnDefinition Width="*" /> </TextBlock>
</Grid.ColumnDefinitions> <Grid Grid.Row="1">
<Button <Grid.ColumnDefinitions>
x:Name="btn_DIY" <ColumnDefinition />
Margin="4" <ColumnDefinition />
Padding="1" </Grid.ColumnDefinitions>
d:Click="DIY_ADD_Click" <Button
pu:ButtonHelper.CornerRadius="4" x:Name="btn_DIY"
Background="{DynamicResource SecondaryLight}" Padding="20,5,20,5"
Content="{ll:Str 添加新链接}" /> Command="{Binding AddLinkCommand}"
<Button Content="{ll:Str 添加新链接}"
Grid.Column="1" Style="{DynamicResource Button_BaseStyle}" />
Margin="4" <Button
Padding="1" Grid.Column="1"
d:Click="DIY_Save_Click" Padding="20,5,20,5"
pu:ButtonHelper.CornerRadius="4" d:Click="DIY_Save_Click"
Background="{DynamicResource SecondaryLight}" Command="{Binding ClearLinksCommand}"
Content="{ll:Str 保存设置}" /> Content="{ll:Str 清空全部}"
</Grid> Style="{DynamicResource Button_BaseStyle}" />
<ScrollViewer> </Grid>
<StackPanel x:Name="StackDIY" /> <TextBox
</ScrollViewer> Grid.Row="2"
</StackPanel> pu:TextBoxHelper.Watermark="{ll:Str 搜索名称}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding SearchLink, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
Grid.Row="3"
d:ItemsSource="{d:SampleData ItemCount=10}"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding ShowLinks}"
VerticalScrollBarVisibility="Auto">
<DataGrid.RowStyle>
<Style BasedOn="{StaticResource {x:Type DataGridRow}}" TargetType="DataGridRow">
<Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Page}}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=Self}}">
<MenuItem
Command="{Binding PlacementTarget.Tag.RemoveLinkCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"
Header="{ll:Str 删除}" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
EditingElementStyle="{DynamicResource TextBox_LeftCenter}"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 名称}" />
<DataGridTextColumn
Binding="{Binding Link, UpdateSourceTrigger=PropertyChanged}"
EditingElementStyle="{DynamicResource TextBox_LeftCenter}"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 链接}" />
</DataGrid.Columns>
</DataGrid>
</Grid> </Grid>
</Page> </Page>

View File

@ -13,107 +13,71 @@
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid> <StackPanel>
<ScrollViewer> <TextBlock
<StackPanel> HorizontalAlignment="Left"
<TextBlock VerticalAlignment="Top"
HorizontalAlignment="Left" Background="{x:Null}"
VerticalAlignment="Top" TextWrapping="Wrap">
Background="{x:Null}" <Run
TextWrapping="Wrap"> FontSize="18"
<Run FontWeight="Bold"
FontSize="18" Text="{ll:Str 自动超模MOD优化}" /><LineBreak />
FontWeight="Bold" <Run Text="{ll:Str '对于超模内容,游戏会自动计算合理价格\&#13;如果未使用任何超模数据,数据菜单栏将会显示图标方便您进行炫耀数据'}" />
Text="{ll:Str 自动超模MOD优化}" /><LineBreak /> </TextBlock>
<Run Text="{ll:Str '对于超模内容,游戏会自动计算合理价格\&#13;如果未使用任何超模数据,数据菜单栏将会显示图标方便您进行炫耀数据'}" /> <pu:Switch
</TextBlock> x:Name="swAutoCal"
<pu:Switch Grid.Column="2"
x:Name="swAutoCal" Content="{ll:Str '自动计算合理价格'}"
Grid.Column="2" IsChecked="{Binding DiagnosticSetting.AutoCal}"
Margin="20,0,0,0" Style="{DynamicResource Switch_BaseStyle}" />
HorizontalAlignment="Left" <TextBlock
d:Checked="swAutoCal_Checked" Margin="0,20,0,0"
d:Unchecked="swAutoCal_Checked" HorizontalAlignment="Left"
Background="Transparent" VerticalAlignment="Top"
BorderBrush="{DynamicResource PrimaryDark}" Background="{x:Null}"
BoxHeight="18" FontSize="13"
BoxWidth="35" TextWrapping="Wrap">
CheckedBackground="{DynamicResource Primary}" <Run
CheckedBorderBrush="{DynamicResource Primary}" FontSize="18"
CheckedToggleBrush="{DynamicResource DARKPrimaryText}" FontWeight="Bold"
Content="{ll:Str '自动计算合理价格'}" Text="{ll:Str 诊断与反馈}" /> <LineBreak />
ToggleBrush="{DynamicResource PrimaryDark}" <Run Text="{ll:Str '选择要发送给 LBGame 的诊断数据,诊断数据用于保护和及时更新 虚拟桌宠模拟器, 解决问题并改进产品.'}" /><LineBreak />
ToggleShadowColor="{x:Null}" <Run Text="{ll:Str '无论选择哪个选项,游戏都可以安全正常地运行.'}" /> <Hyperlink d:Click="hyper_moreInfo">
ToggleSize="14" <Run Text="{ll:Str 获取有关这些设置的更多信息}" />
ToolTip="{ll:Str '该选项重启后生效'}" /> </Hyperlink>
<TextBlock <LineBreak /> <Run FontWeight="Bold" Text="{ll:Str '当前存档Hash验证信息'}" />
Margin="0,20,0,0" :<Run
HorizontalAlignment="Left" x:Name="RHashCheck"
VerticalAlignment="Top" FontWeight="Bold"
Background="{x:Null}" Text="通过" />
FontSize="13" </TextBlock>
TextWrapping="Wrap"> <pu:Switch
<Run x:Name="RBDiagnosisYES"
FontSize="18" CheckedContent="{ll:Str '发送诊断数据: 发送游戏存档, 包括饱腹,状态等各种游戏内\&#13;数据. 可能会包括该游戏内存和CPU使用情况'}"
FontWeight="Bold" Content="{ll:Str '不发送诊断数据: 适用于启用修改器,修改过游戏数据等不\&#13;符合分析数据条件. 或不希望提供游戏数据的玩家'}"
Text="{ll:Str 诊断与反馈}" /> <LineBreak /> IsChecked="{Binding DiagnosticSetting.Diagnosis}"
<Run Text="{ll:Str '选择要发送给 LBGame 的诊断数据,诊断数据用于保护和及时更新 虚拟桌宠模拟器, 解决问题并改进产品.'}" /><LineBreak /> Style="{DynamicResource Switch_BaseStyle}" />
<Run Text="{ll:Str '无论选择哪个选项,游戏都可以安全正常地运行.'}" /> <Hyperlink d:Click="hyper_moreInfo"> <StackPanel>
<Run Text="{ll:Str 获取有关这些设置的更多信息}" /> <TextBlock
</Hyperlink> Margin="0,15,0,0"
<LineBreak /> <Run FontWeight="Bold" Text="{ll:Str '当前存档Hash验证信息'}" /> HorizontalAlignment="Left"
:<Run VerticalAlignment="Top"
x:Name="RHashCheck" Background="{x:Null}"
FontWeight="Bold" TextWrapping="Wrap">
Text="通过" /> <Run FontWeight="Bold" Text="{ll:Str 反馈频率}" /><LineBreak />
</TextBlock> <Run Text="{ll:Str 'VOS 应寻求我反馈按以下频率'}" />
<RadioButton </TextBlock>
x:Name="RBDiagnosisYES" <StackPanel Orientation="Horizontal">
Margin="10,10,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
d:Checked="RBDiagnosisYES_Checked"
Content="{ll:Str '发送诊断数据: 发送游戏存档, 包括饱腹,状态等各种游戏内\&#13;数据. 可能会包括该游戏内存和CPU使用情况'}"
GroupName="diagnosis"
Style="{DynamicResource StandardRadioButtonStyle}" />
<RadioButton
x:Name="RBDiagnosisNO"
Margin="10,10,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
d:Checked="RBDiagnosisNO_Checked"
Content="{ll:Str '不发送诊断数据: 适用于启用修改器,修改过游戏数据等不\&#13;符合分析数据条件. 或不希望提供游戏数据的玩家'}"
GroupName="diagnosis"
IsChecked="True"
Style="{DynamicResource StandardRadioButtonStyle}" />
<TextBlock
Margin="0,15,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="{x:Null}"
TextWrapping="Wrap">
<Run FontWeight="Bold" Text="{ll:Str 反馈频率}" /><LineBreak />
<Run Text="{ll:Str 'VOS 应寻求我反馈按以下频率'}" />
</TextBlock>
<ComboBox <ComboBox
x:Name="CBDiagnosis" x:Name="CBDiagnosis"
Width="200" Width="200"
Margin="10,5,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" ItemsSource="{Binding DiagnosticSetting.DiagnosisIntervals}"
d:SelectionChanged="CBDiagnosis_SelectionChanged" SelectedItem="{Binding DiagnosticSetting.DiagnosisInterval}"
IsEnabled="False" Style="{DynamicResource ComboBox_BaseStyle}" />
SelectedIndex="1" <Label Content="{ll:Str 每周期一次}" Style="{DynamicResource Label_BaseStyle}" />
Style="{DynamicResource StandardComboBoxStyle}">
<ComboBoxItem Content="{ll:Str '每 两百 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 五百 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 一千 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 两千 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 五千 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 一万 周期一次'}" />
<ComboBoxItem Content="{ll:Str '每 两万 周期一次'}" />
</ComboBox>
</StackPanel> </StackPanel>
</ScrollViewer> </StackPanel>
</Grid> </StackPanel>
</Page> </Page>

View File

@ -3,233 +3,231 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 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:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor" xmlns:local="clr-namespace:VPet.Solution.Views.SettingEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui" xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SettingEditor" xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SettingEditor"
Title="ModSettingsPage" Title="ModSettingsPage"
d:DataContext="{d:DesignInstance Type=vm:GraphicsSettingPageVM}" d:DataContext="{d:DesignInstance Type=vm:ModSettingPageVM}"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="120" /> <ColumnDefinition Width="Auto" MinWidth="120" />
<ColumnDefinition Width="15" /> <ColumnDefinition Width="10" />
<ColumnDefinition Width="*" /> <ColumnDefinition MinWidth="200" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<ListBox <Grid>
x:Name="ListMod" <Grid.RowDefinitions>
VerticalAlignment="Top" <RowDefinition Height="Auto" />
d:SelectionChanged="ListMod_SelectionChanged" <RowDefinition />
Background="Transparent" <RowDefinition Height="Auto" />
BorderThickness="0" <RowDefinition Height="Auto" />
SelectionMode="Single" </Grid.RowDefinitions>
Style="{DynamicResource SideMenuListBoxStyle}" /> <TextBox
<StackPanel Grid.Column="2"> pu:TextBoxHelper.Watermark="{ll:Str 搜索模组}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding SearchMod, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
x:Name="DataGrid_Mods"
Grid.Row="1"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding ShowMods}"
SelectedItem="{Binding CurrentModMoel}">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name}"
ElementStyle="{DynamicResource TextBlock_BaseStyle}"
Header="{ll:Str 名称}"
IsReadOnly="True" />
<DataGridTextColumn
Binding="{Binding State}"
ElementStyle="{DynamicResource TextBlock_BaseStyle}"
Header="{ll:Str 状态}"
IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
<Button
Grid.Row="2"
Margin="0"
HorizontalAlignment="Stretch"
Command="{Binding ClearFailModsCommand}"
Content="{ll:Str 清除失效模组}"
Style="{DynamicResource Button_BaseStyle}" />
<Button
Grid.Row="3"
Margin="0"
HorizontalAlignment="Stretch"
Command="{Binding ClearModsCommand}"
Content="{ll:Str 清除全部模组}"
Style="{DynamicResource Button_BaseStyle}" />
</Grid>
<Grid
Grid.Column="2"
d:DataContext="{Binding ModSetting.Mods[0]}"
DataContext="{Binding SelectedItem, ElementName=DataGrid_Mods}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="7" />
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image <Image
x:Name="ImageMOD" Width="150"
Width="120" Height="150"
Height="120" Source="{Binding Image}"
Margin="0,5,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Stretch="Fill" /> Stretch="Fill" />
<StackPanel Grid.Column="2"> <ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Auto">
<Label <StackPanel>
x:Name="LabelModName" <StackPanel Orientation="Horizontal">
Margin="-5,2,0,0" <Label
HorizontalAlignment="Left" Margin="10,0,10,0"
VerticalAlignment="Top" h:ElementHelper.UniformMinWidthGroup="A"
Background="{x:Null}" Content="{ll:Str '模组名称:'}"
Content="Core" Style="{DynamicResource Label_BaseStyle}" />
FontSize="20" <TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Name}" />
FontWeight="Bold" </StackPanel>
Foreground="{DynamicResource PrimaryText}" /> <StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,0,0" TextWrapping="Wrap"> <Label
<Run FontWeight="Bold" Text="{ll:Str '模组作者: '}" /><LineBreak /> Margin="10,0,10,0"
<Run x:Name="runMODAuthor" Text="LorisYounger" /> h:ElementHelper.UniformMinWidthGroup="A"
<LineBreak /><Run FontWeight="Bold" Text="{ll:Str '模组版本: '}" /><Run x:Name="runMODVer" Text="1.0" /> Content="{ll:Str '作者:'}"
<LineBreak /><Run FontWeight="Bold" Text="{ll:Str '游戏版本: '}" /><Run x:Name="runMODGameVer" Text="1.0" /> Style="{DynamicResource Label_BaseStyle}" />
</TextBlock> <TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Author}" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal">
<Label
Margin="10,0,10,0"
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str '模组版本:'}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding ModVersion}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label
Margin="10,0,10,0"
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str '游戏版本:'}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding GameVersion}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label
Margin="10,0,10,0"
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str '模组路径:'}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding ModPath}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid> </Grid>
<Label <Grid Grid.Row="1">
Margin="-5,0,0,0" <Grid.RowDefinitions>
Padding="5,5,5,0" <RowDefinition Height="Auto" />
HorizontalAlignment="Left" <RowDefinition />
VerticalAlignment="Center" </Grid.RowDefinitions>
Background="{x:Null}" <Label
Content="{ll:Str MOD介绍}" HorizontalAlignment="Left"
FontSize="18" Content="{ll:Str MOD介绍}"
FontWeight="Bold" /> FontSize="18"
<ScrollViewer FontWeight="Bold"
Height="80" Style="{DynamicResource Label_BaseStyle}" />
HorizontalAlignment="Left" <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
VerticalAlignment="Top" <TextBlock
pu:ScrollViewerHelper.ScrollBarThickness="10" x:Name="GameInfo"
VerticalScrollBarVisibility="Auto"> FontSize="14"
<TextBlock Style="{DynamicResource TextBlock_Wrap}"
x:Name="GameInfo" Text="{Binding Description}" />
VerticalAlignment="Top" </ScrollViewer>
FontSize="14" </Grid>
Text="这里是MOD的介绍内容,你的介绍就是你的介绍&#xA;" <Grid Grid.Row="2">
TextWrapping="Wrap" />
</ScrollViewer>
<Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition /> <ColumnDefinition />
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel> <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Label <Label
Margin="-5,0,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="{x:Null}"
Content="{ll:Str 内容}" Content="{ll:Str 内容}"
FontSize="18" FontSize="18"
FontWeight="Bold" /> FontWeight="Bold"
<ScrollViewer Style="{DynamicResource Label_BaseStyle}" />
Height="140" <ItemsControl Grid.Row="1" ItemsSource="{Binding Tags}" />
Margin="0,0,0,0" </Grid>
HorizontalAlignment="Left" <Grid
VerticalAlignment="Top" Grid.Column="1"
pu:ScrollViewerHelper.ScrollBarThickness="10" h:ElementHelper.IsEnabled="{Binding IsEnabled, Converter={StaticResource NullToFalse}}"
VerticalScrollBarVisibility="Auto"> IsEnabled="False">
<TextBlock <Grid.RowDefinitions>
x:Name="GameHave" <RowDefinition Height="Auto" />
HorizontalAlignment="Left" <RowDefinition />
VerticalAlignment="Top" </Grid.RowDefinitions>
FontSize="14"
Text="该mod有许多功能&#xA;比如说功能1&#xA;比如说功能1&#xA;比如说功能1&#xA;比如说功能1&#xA;比如说功能1"
TextWrapping="Wrap" />
</ScrollViewer>
</StackPanel>
<StackPanel Grid.Column="1">
<Label <Label
Margin="-5,0,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="{x:Null}"
Content="{ll:Str 操作}" Content="{ll:Str 操作}"
FontSize="18" FontSize="18"
FontWeight="Bold" /> FontWeight="Bold"
<TextBlock Style="{DynamicResource Label_BaseStyle}" />
x:Name="ButtonOpenModFolder" <Grid Grid.Row="1">
Margin="0,0,0,0" <Grid.ColumnDefinitions>
HorizontalAlignment="Left" <ColumnDefinition />
VerticalAlignment="Top" <ColumnDefinition />
d:MouseDown="ButtonOpenModFolder_MouseDown" </Grid.ColumnDefinitions>
Cursor="Hand" <StackPanel>
FontSize="14" <pu:Switch
Foreground="{DynamicResource DARKPrimaryDarker}" Content="{ll:Str 启用模组}"
Text="{ll:Str '所在文件夹'}" IsChecked="{Binding IsEnabled}"
TextDecorations="Underline" Style="{DynamicResource Switch_BaseStyle}" />
TextWrapping="Wrap" /> <pu:Switch
<TextBlock Content="{ll:Str 启用模组代码}"
x:Name="ButtonEnable" IsChecked="{Binding IsPass}"
Margin="0,2,0,0" IsEnabled="{Binding IsMsg}"
HorizontalAlignment="Left" Style="{DynamicResource Switch_BaseStyle}" />
VerticalAlignment="Top" </StackPanel>
d:MouseDown="ButtonEnable_MouseDown" <StackPanel Grid.Column="1">
Cursor="Hand" <Button
FontSize="14" HorizontalAlignment="Left"
Foreground="{DynamicResource DARKPrimaryDarker}" Command="{Binding DataContext.OpenModPathCommand, RelativeSource={RelativeSource AncestorType=Page}}"
Text="{ll:Str '启用该模组'}" CommandParameter="{Binding}"
TextDecorations="Underline" Content="{ll:Str '打开所在文件夹'}"
TextWrapping="Wrap" /> Style="{DynamicResource Button_BaseStyle}" />
<TextBlock <!--<TextBlock
x:Name="ButtonDisEnable" x:Name="ButtonPublish"
Margin="0,2,0,0" Margin="0,2,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
d:MouseDown="ButtonDisEnable_MouseDown" d:MouseDown="ButtonPublish_MouseDown"
Cursor="Hand" Cursor="Hand"
FontSize="14" FontSize="14"
Foreground="{DynamicResource DARKPrimaryDarker}" Foreground="DimGray"
Text="{ll:Str '停用该模组'}" Text="{ll:Str 更新至Steam}"
TextDecorations="Underline" TextDecorations="Underline"
TextWrapping="Wrap" /> TextWrapping="Wrap" />-->
<TextBlock <Button
x:Name="ButtonPublish" x:Name="ButtonSteam"
Margin="0,2,0,0" HorizontalAlignment="Left"
HorizontalAlignment="Left" Command="{Binding DataContext.OpenSteamCommunityCommand, RelativeSource={RelativeSource AncestorType=Page}}"
VerticalAlignment="Top" CommandParameter="{Binding}"
d:MouseDown="ButtonPublish_MouseDown" Content="{ll:Str 打开创意工坊页面}"
Cursor="Hand" Style="{DynamicResource Button_BaseStyle}" />
FontSize="14" </StackPanel>
Foreground="DimGray" </Grid>
Text="{ll:Str 更新至Steam}" </Grid>
TextDecorations="Underline"
TextWrapping="Wrap" />
<TextBlock
x:Name="ButtonSteam"
Margin="0,2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
d:MouseDown="ButtonSteam_MouseDown"
Cursor="Hand"
FontSize="14"
Foreground="DimGray"
Text="{ll:Str 创意工坊页面}"
TextDecorations="Underline"
TextWrapping="Wrap" />
<ProgressBar
x:Name="ProgressBarUpload"
Height="30"
Margin="0,2,0,0"
VerticalAlignment="Top"
pu:ProgressBarHelper.CornerRadius="2"
pu:ProgressBarHelper.IsPercentVisible="True"
Background="{DynamicResource Primary}"
BorderBrush="{DynamicResource PrimaryDarker}"
BorderThickness="2"
Foreground="{DynamicResource DARKPrimary}"
Visibility="Collapsed"
Value="60" />
<TextBlock
x:Name="ButtonSetting"
Margin="0,2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
d:MouseDown="ButtonSetting_MouseDown"
Cursor="Hand"
FontSize="14"
Foreground="{DynamicResource DARKPrimaryDarker}"
Text="{ll:Str MOD设置}"
TextDecorations="Underline"
TextWrapping="Wrap" />
<Button
x:Name="ButtonAllow"
HorizontalAlignment="Left"
VerticalAlignment="Top"
d:Click="ButtonAllow_Click"
Background="#FFFF2C2C"
Content="{ll:Str 启用代码插件}"
FontSize="12"
Foreground="White"
ToolTip="{ll:Str '启用该模组的代码内容,不能保证系统安全性'}" />
</StackPanel>
<Button
x:Name="ButtonRestart"
Grid.ColumnSpan="2"
Margin="0,2,0,0"
VerticalAlignment="Bottom"
d:Click="ButtonRestart_Click"
Background="{DynamicResource DARKPrimary}"
Content="{ll:Str 重启软件以应用更改}"
Foreground="{DynamicResource DARKPrimaryText}"
Visibility="Collapsed" />
</Grid> </Grid>
</StackPanel> </Grid>
</Grid> </Grid>
</Page> </Page>