diff --git a/VPet-Simulator.Windows/MainWindow.cs b/VPet-Simulator.Windows/MainWindow.cs index 8eb91cb..a83ea6d 100644 --- a/VPet-Simulator.Windows/MainWindow.cs +++ b/VPet-Simulator.Windows/MainWindow.cs @@ -35,6 +35,8 @@ using Line = LinePutScript.Line; using static VPet_Simulator.Windows.Interface.ExtensionFunction; using Image = System.Windows.Controls.Image; +using VPet.Solution; + namespace VPet_Simulator.Windows { public partial class MainWindow : IMainWindow diff --git a/VPet-Simulator.Windows/VPet-Simulator.Windows.csproj b/VPet-Simulator.Windows/VPet-Simulator.Windows.csproj index fd04f6b..d41dd05 100644 --- a/VPet-Simulator.Windows/VPet-Simulator.Windows.csproj +++ b/VPet-Simulator.Windows/VPet-Simulator.Windows.csproj @@ -128,6 +128,7 @@ + diff --git a/VPet-Simulator.Windows/WinDesign/winCharacterPanel.xaml.cs b/VPet-Simulator.Windows/WinDesign/winCharacterPanel.xaml.cs index ea0d329..a1805c4 100644 --- a/VPet-Simulator.Windows/WinDesign/winCharacterPanel.xaml.cs +++ b/VPet-Simulator.Windows/WinDesign/winCharacterPanel.xaml.cs @@ -699,6 +699,7 @@ namespace VPet_Simulator.Windows btn_r_save.IsEnabled = true; pb_r_genRank.Visibility = Visibility.Collapsed; Width = 800; + Height = 800; }); } private string px_tocm(long px, out string cm) diff --git a/VPet-Simulator.Windows/mod/0000_core/food/timelimit.lps b/VPet-Simulator.Windows/mod/0000_core/food/timelimit.lps index 903e4b7..9bd6da5 100644 --- a/VPet-Simulator.Windows/mod/0000_core/food/timelimit.lps +++ b/VPet-Simulator.Windows/mod/0000_core/food/timelimit.lps @@ -2,7 +2,7 @@ /// food:|name#五仁月饼:|type#Meal:|Exp#100:|Strength#80:|StrengthDrink#-6:|StrengthFood#160:|Likability#1:|Health#5:|Feeling#0:|price#38:|graph#eat:|desc#举头望明月,低头思故乡。无论身在何处,离家多远,家人在不在身边,心情好不好,萝莉丝都为你做了五仁月饼,快说谢谢萝莉丝。:| /// food:|name#巧克力花生月饼:|type#Functional:|Exp#400:|Strength#20:|StrengthDrink#0:|StrengthFood#40:|Likability#2:|Health#5:|Feeling#20:|price#62:|graph#eat:|desc#明月几时有,把酒问青天。无论考的如何,作业有多少,老师怎么说,家长怎么批评,萝莉丝都为你做了巧克力花生月饼,快说谢谢萝莉丝。:| -food:|name#圣诞帽:|type#Gift:|Exp#200:|Likability#4:|Health#5:|Feeling#50:|price#40.0:|graph#gift:|desc#圣诞帽_giftintor:| +food:|name#圣诞帽:|type#Gift:|Exp#200:|Likability#4:|Health#5:|Feeling#50:|price#45.0:|graph#gift:|desc#圣诞帽_giftintor:| food:|name#礼物盒子:|type#Gift:|Exp#1000:|Likability#5:|Feeling#100:|price#150.0:|graph#gift:|desc#礼物盒子_giftintor:| food:|name#糖果棒:|type#Snack:|Exp#200:|Strength#40:|StrengthFood#40:|Likability#2:|Feeling#40:|price#35:|graph#eat:|desc#糖果棒_giftintor:| food:|name#圣诞草莓奶茶:|type#Drink:|Exp#200:|StrengthDrink#80:|Likability#2:|Feeling#60:|price#35:|graph#drink:|desc#圣诞草莓奶茶_giftintor:| diff --git a/VPet.Solution/Models/SaveViewer/SaveModel.cs b/VPet.Solution/Models/SaveViewer/SaveModel.cs new file mode 100644 index 0000000..58e26d0 --- /dev/null +++ b/VPet.Solution/Models/SaveViewer/SaveModel.cs @@ -0,0 +1,226 @@ +using HKW.HKWUtils.Observable; +using LinePutScript.Localization.WPF; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VPet_Simulator.Windows.Interface; + +namespace VPet.Solution.Models.SaveViewer; + +/// +/// 存档模型 +/// +public class SaveModel : ObservableClass +{ + /// + /// 名称 + /// + [ReflectionPropertyIgnore] + public string Name { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + /// + /// 统计数据 + /// + public ObservableCollection Statistics { get; set; } = new(); + + /// + /// 是损坏的 + /// + public bool IsDamaged { get; set; } + + #region DateSaved + private DateTime _dateSaved; + public DateTime DateSaved + { + get => _dateSaved; + set => SetProperty(ref _dateSaved, value); + } + #endregion + + + #region PetName + private string _petName; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Name))] + public string PetName + { + get => _petName; + set => SetProperty(ref _petName, value); + } + #endregion + + #region Level + private int _level; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Level))] + public int Level + { + get => _level; + set => SetProperty(ref _level, value); + } + #endregion + + #region Money + private double _money = 100; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Money))] + public double Money + { + get => _money; + set => SetProperty(ref _money, value); + } + #endregion + + #region Exp + private double _exp = 0; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Exp))] + public double Exp + { + get => _exp; + set => SetProperty(ref _exp, value); + } + #endregion + + #region Feeling + private double _feeling = 60; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Feeling))] + public double Feeling + { + get => _feeling; + set => SetProperty(ref _feeling, value); + } + #endregion + + #region Health + private double _health = 100; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Health))] + public double Health + { + get => _health; + set => SetProperty(ref _health, value); + } + #endregion + + #region Likability + private double _likability = 0; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Likability))] + public double Likability + { + get => _likability; + set => SetProperty(ref _likability, value); + } + #endregion + + #region Mode + private VPet_Simulator.Core.GameSave.ModeType _mode; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Mode))] + public VPet_Simulator.Core.GameSave.ModeType Mode + { + get => _mode; + set => SetProperty(ref _mode, value); + } + #endregion + + #region Strength + private double _strength = 100; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Strength))] + public double Strength + { + get => _strength; + set => SetProperty(ref _strength, value); + } + #endregion + + #region StrengthFood + private double _strengthFood = 100; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.StrengthFood))] + public double StrengthFood + { + get => _strengthFood; + set => SetProperty(ref _strengthFood, value); + } + #endregion + + #region StrengthDrink + private double _strengthDrink = 100; + + [ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.StrengthDrink))] + public double StrengthDrink + { + get => _strengthDrink; + set => SetProperty(ref _strengthDrink, value); + } + #endregion + + + #region HashChecked + private bool _hashChecked; + + /// + /// Hash已检查 + /// + public bool HashChecked + { + get => _hashChecked; + set => SetProperty(ref _hashChecked, value); + } + #endregion + + + + #region TotalTime + private long _totalTime; + + /// + /// 游玩总时长 + /// + public long TotalTime + { + get => _totalTime; + set => SetProperty(ref _totalTime, value); + } + #endregion + + + public SaveModel(string filePath, GameSave_v2 save) + { + Name = Path.GetFileNameWithoutExtension(filePath); + FilePath = filePath; + DateSaved = File.GetLastWriteTime(filePath); + LoadSave(save.GameSave); + if (save.Statistics.Data.TryGetValue("stat_total_time", out var time)) + TotalTime = time.GetInteger64(); + HashChecked = save.HashCheck; + foreach (var data in save.Statistics.Data) + { + Statistics.Add( + new() + { + Id = data.Key, + Name = data.Key.Translate(), + Value = data.Value + } + ); + } + } + + private void LoadSave(VPet_Simulator.Core.GameSave save) + { + ReflectionUtils.SetValue(save, this); + } +} diff --git a/VPet.Solution/Models/SaveViewer/StatisticDataModel.cs b/VPet.Solution/Models/SaveViewer/StatisticDataModel.cs new file mode 100644 index 0000000..37358bc --- /dev/null +++ b/VPet.Solution/Models/SaveViewer/StatisticDataModel.cs @@ -0,0 +1,46 @@ +namespace VPet.Solution.Models.SaveViewer; + +/// +/// 统计数据模型 +/// +public class StatisticDataModel : ObservableClass +{ + #region Id + private string _id; + + /// + /// ID + /// + public string Id + { + get => _id; + set => SetProperty(ref _id, value); + } + #endregion + + #region Name + private string _name; + + /// + /// 名称 + /// + public string Name + { + get => _name; + set => SetProperty(ref _name, value); + } + #endregion + + #region Value + private object _value; + + /// + /// 值 + /// + public object Value + { + get => _value; + set => SetProperty(ref _value, value); + } + #endregion +} diff --git a/VPet.Solution/Models/SettingEditor/GraphicsSettingModel.cs b/VPet.Solution/Models/SettingEditor/GraphicsSettingModel.cs index 983c2ab..ea6047a 100644 --- a/VPet.Solution/Models/SettingEditor/GraphicsSettingModel.cs +++ b/VPet.Solution/Models/SettingEditor/GraphicsSettingModel.cs @@ -1,4 +1,6 @@ using HKW.HKWUtils.Observable; +using LinePutScript.Localization.WPF; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; @@ -6,13 +8,14 @@ namespace VPet.Solution.Models.SettingEditor; public class GraphicsSettingModel : ObservableClass { - #region + #region ZoomLevel private double _zoomLevel = 1; /// /// 缩放倍率 /// [DefaultValue(1)] + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.ZoomLevel))] public double ZoomLevel { get => _zoomLevel; @@ -37,23 +40,29 @@ public class GraphicsSettingModel : ObservableClass set => SetProperty(ref _zoomLevelMaximum, value); } #endregion + + #region Resolution private int _resolution = 1000; /// /// 桌宠图形渲染的分辨率,越高图形越清晰 /// [DefaultValue(1000)] + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Resolution))] public int Resolution { get => _resolution; set => SetProperty(ref _resolution, value); } + #endregion + #region IsBiggerScreen private bool _isBiggerScreen; /// /// 是否为更大的屏幕 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.IsBiggerScreen))] public bool IsBiggerScreen { get => _isBiggerScreen; @@ -66,94 +75,125 @@ public class GraphicsSettingModel : ObservableClass ZoomLevelMaximum = 3; } } + #endregion + #region TopMost private bool _topMost; /// /// 是否置于顶层 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.TopMost))] public bool TopMost { get => _topMost; set => SetProperty(ref _topMost, value); } + #endregion + #region HitThrough private bool _hitThrough; /// /// 是否鼠标穿透 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.HitThrough))] public bool HitThrough { get => _hitThrough; set => SetProperty(ref _hitThrough, value); } + #endregion - private string _language; + #region Language + private string _language = Languages.First(); /// /// 语言 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Language))] public string Language { get => _language; set => SetProperty(ref _language, value); } + + public static ObservableCollection Languages { get; } = + new() { "zh-Hans", "zh-Hant", "en" }; + // NOTE: 实际上这里面并没有文化 new(LocalizeCore.AvailableCultures); + + #endregion + + #region Font private string _font; /// /// 字体 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Font))] public string Font { get => _font; set => SetProperty(ref _font, value); } + #endregion + + #region Theme private string _theme; /// /// 主题 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Theme))] public string Theme { get => _theme; set => SetProperty(ref _theme, value); } + #endregion + #region StartUPBoot private bool _startUPBoot; /// /// 开机启动 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartUPBoot))] public bool StartUPBoot { get => _startUPBoot; set => SetProperty(ref _startUPBoot, value); } + #endregion + #region StartUPBootSteam private bool _startUPBootSteam; /// /// 开机启动 Steam /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartUPBootSteam))] public bool StartUPBootSteam { get => _startUPBootSteam; set => SetProperty(ref _startUPBootSteam, value); } + #endregion + #region StartRecordLast private bool _startRecordLast = true; /// /// 是否记录游戏退出位置 /// [DefaultValue(true)] + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartRecordLast))] public bool StartRecordLast { get => _startRecordLast; set => SetProperty(ref _startRecordLast, value); } - + #endregion //private Point _startRecordLastPoint; ///// @@ -165,26 +205,92 @@ public class GraphicsSettingModel : ObservableClass // set => SetProperty(ref _startRecordLastPoint, value); //} + #region StartRecordPoint private ObservablePoint _startRecordPoint; /// /// 设置中桌宠启动的位置 /// - [ReflectionPropertyInfo(typeof(ObservablePointToPointConverter))] + [ReflectionProperty] + [ReflectionPropertyConverter(typeof(ObservablePointToPointConverter))] public ObservablePoint StartRecordPoint { get => _startRecordPoint; set => SetProperty(ref _startRecordPoint, value); } + #endregion + #region HideFromTaskControl private bool _hideFromTaskControl; /// /// 在任务切换器(Alt+Tab)中隐藏窗口 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.HideFromTaskControl))] public bool HideFromTaskControl { get => _hideFromTaskControl; set => SetProperty(ref _hideFromTaskControl, value); } + #endregion + + #region MessageBarOutside + private bool _messageBarOutside; + + /// + /// 消息框外置 + /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MessageBarOutside))] + public bool MessageBarOutside + { + get => _messageBarOutside; + set => SetProperty(ref _messageBarOutside, value); + } + #endregion + + #region PetHelper + private bool _petHelper; + + /// + /// 是否显示宠物帮助窗口 + /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelper))] + public bool PetHelper + { + get => _petHelper; + set => SetProperty(ref _petHelper, value); + } + #endregion + + #region PetHelpLeft + private double _petHelpLeft; + + // TODO 加入 PetHelpLeft + + /// + /// 快捷穿透按钮X坐标 + /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelpLeft))] + public double PetHelpLeft + { + get => _petHelpLeft; + set => SetProperty(ref _petHelpLeft, value); + } + #endregion + + #region PetHelpTop + private double _petHelpTop; + + // TODO 加入 PetHelpTop + + /// + /// 快捷穿透按钮Y坐标 + /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelpTop))] + public double PetHelpTop + { + get => _petHelpTop; + set => SetProperty(ref _petHelpTop, value); + } + #endregion } diff --git a/VPet.Solution/Models/SettingEditor/InteractiveSettingModel.cs b/VPet.Solution/Models/SettingEditor/InteractiveSettingModel.cs index 50e0f61..6ab7376 100644 --- a/VPet.Solution/Models/SettingEditor/InteractiveSettingModel.cs +++ b/VPet.Solution/Models/SettingEditor/InteractiveSettingModel.cs @@ -1,251 +1,311 @@ using HKW.HKWUtils.Observable; +using System.Collections.ObjectModel; +using System.ComponentModel; using VPet_Simulator.Core; namespace VPet.Solution.Models.SettingEditor; public class InteractiveSettingModel : ObservableClass { - private string _petName; + // NOTE: 这玩意其实在存档里 而不是设置里 + //#region PetName + //private string _petName; - /// - /// 宠物名称 - /// - public string PetName - { - get => _petName; - set => SetProperty(ref _petName, value); - } + ///// + ///// 宠物名称 + ///// + //[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetName))] + //public string PetName + //{ + // get => _petName; + // set => SetProperty(ref _petName, value); + //} + //#endregion + #region VoiceVolume private double _voiceVolume; /// /// 播放声音大小 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.VoiceVolume))] public double VoiceVolume { get => _voiceVolume; set => SetProperty(ref _voiceVolume, value); } + #endregion + #region EnableFunction + private bool _enableFunction; + + /// + /// 启用计算等数据功能 + /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.EnableFunction))] + public bool EnableFunction + { + get => _enableFunction; + set => SetProperty(ref _enableFunction, value); + } + #endregion + + #region CalFunState private GameSave.ModeType _calFunState; /// /// 非计算模式下默认模式 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.CalFunState))] public GameSave.ModeType CalFunState { get => _calFunState; set => SetProperty(ref _calFunState, value); } - private bool _petHelper; - - /// - /// 是否显示宠物帮助窗口 - /// - public bool PetHelper - { - get => _petHelper; - set => SetProperty(ref _petHelper, value); - } + public ObservableCollection ModeTypes { get; } = + new(Enum.GetValues(typeof(GameSave.ModeType)).Cast()); + #endregion + #region LastCacheDate private DateTime _lastCacheDate; /// /// 上次清理缓存日期 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.LastCacheDate))] public DateTime LastCacheDate { get => _lastCacheDate; set => SetProperty(ref _lastCacheDate, value); } + #endregion + #region SaveTimes private int _saveTimes; /// /// 储存顺序次数 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SaveTimes))] public int SaveTimes { get => _saveTimes; set => SetProperty(ref _saveTimes, value); } + #endregion + #region PressLength private int _pressLength; /// /// 按多久视为长按 单位毫秒 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PressLength))] public int PressLength { get => _pressLength; set => SetProperty(ref _pressLength, value); } + #endregion + #region InteractionCycle private int _interactionCycle; /// /// 互动周期 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.InteractionCycle))] public int InteractionCycle { get => _interactionCycle; set => SetProperty(ref _interactionCycle, value); } + #endregion + #region LogicInterval private double _logicInterval; /// /// 计算间隔 (秒) /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.LogicInterval))] public double LogicInterval { get => _logicInterval; set => SetProperty(ref _logicInterval, value); } + #endregion - private double _petHelpLeft; - - /// - /// 计算间隔 - /// - public double PetHelpLeft - { - get => _petHelpLeft; - set => SetProperty(ref _petHelpLeft, value); - } - - private double _petHelpTop; - - /// - /// 计算间隔 - /// - public double PetHelpTop - { - get => _petHelpTop; - set => SetProperty(ref _petHelpTop, value); - } - + #region AllowMove private bool _allowMove; /// /// 允许移动事件 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AllowMove))] public bool AllowMove { get => _allowMove; set => SetProperty(ref _allowMove, value); } + #endregion + #region SmartMove private bool _smartMove; /// /// 智能移动 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SmartMove))] public bool SmartMove { get => _smartMove; set => SetProperty(ref _smartMove, value); } + #endregion - private bool _enableFunction; - - /// - /// 启用计算等数据功能 - /// - public bool EnableFunction - { - get => _enableFunction; - set => SetProperty(ref _enableFunction, value); - } - - private int _smartMoveInterval; + #region SmartMoveInterval + private int _smartMoveInterval = 0; /// /// 智能移动周期 (秒) /// + [DefaultValue(1)] + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SmartMoveInterval))] + [ReflectionPropertyConverter(typeof(SecondToMinuteConverter))] public int SmartMoveInterval { get => _smartMoveInterval; set => SetProperty(ref _smartMoveInterval, value); } - private bool _messageBarOutside; - - /// - /// 消息框外置 - /// - public bool MessageBarOutside - { - get => _messageBarOutside; - set => SetProperty(ref _messageBarOutside, value); - } + public static ObservableCollection SmartMoveIntervals { get; } = + new() { 1, 2, 5, 10, 20, 30, 40, 50, 60 }; + #endregion + #region PetGraph private string _petGraph; /// /// 桌宠选择内容 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetGraph))] public string PetGraph { get => _petGraph; set => SetProperty(ref _petGraph, value); } + #endregion - private double _musicCatch; + #region MusicCatch + private int _musicCatch; /// /// 当实时播放音量达到该值时运行音乐动作 /// - public double MusicCatch + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MusicCatch))] + [ReflectionPropertyConverter(typeof(DoubleToInt32Converter))] + public int MusicCatch { get => _musicCatch; set => SetProperty(ref _musicCatch, value); } + #endregion - private double _musicMax; + #region MusicMax + private int _musicMax; /// /// 当实时播放音量达到该值时运行特殊音乐动作 /// - public double MusicMax + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MusicMax))] + [ReflectionPropertyConverter(typeof(DoubleToInt32Converter))] + public int MusicMax { get => _musicMax; set => SetProperty(ref _musicMax, value); } + #endregion + #region AutoBuy private bool _autoBuy; + // TODO 加入 AutoBuy /// /// 允许桌宠自动购买食品 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoBuy))] public bool AutoBuy { get => _autoBuy; set => SetProperty(ref _autoBuy, value); } + #endregion + #region AutoGift private bool _autoGift; + // TODO 加入 AutoGift /// /// 允许桌宠自动购买礼物 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoGift))] public bool AutoGift { get => _autoGift; set => SetProperty(ref _autoGift, value); } + #endregion + #region MoveAreaDefault private bool _moveAreaDefault; + + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MoveAreaDefault))] public bool MoveAreaDefault { get => _moveAreaDefault; set => SetProperty(ref _moveAreaDefault, value); } + #endregion + + #region MoveArea private System.Drawing.Rectangle _moveArea; + + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MoveArea))] public System.Drawing.Rectangle MoveArea { get => _moveArea; set => SetProperty(ref _moveArea, value); } + #endregion +} + +public class SecondToMinuteConverter : ReflectionConverterBase +{ + public override int Convert(int sourceValue) + { + return sourceValue * 60; + } + + public override int ConvertBack(int targetValue) + { + if (targetValue == 30) + return 1; + else + return targetValue / 60; + } +} + +public class DoubleToInt32Converter : ReflectionConverterBase +{ + public override double Convert(int sourceValue) + { + return sourceValue; + } + + public override int ConvertBack(double targetValue) + { + return System.Convert.ToInt32(targetValue); + } } diff --git a/VPet.Solution/Models/SettingEditor/SettingModel.cs b/VPet.Solution/Models/SettingEditor/SettingModel.cs index 1dcf46f..fc0c552 100644 --- a/VPet.Solution/Models/SettingEditor/SettingModel.cs +++ b/VPet.Solution/Models/SettingEditor/SettingModel.cs @@ -12,35 +12,26 @@ namespace VPet.Solution.Models.SettingEditor; public class SettingModel : ObservableClass { - private string _name; - /// /// 名称 /// - public string Name - { - get => _name; - set => SetProperty(ref _name, value); - } - - private string _filePath; + public string Name { get; set; } /// /// 文件路径 /// - public string FilePath - { - get => _filePath; - set => SetProperty(ref _filePath, value); - } + public string FilePath { get; set; } + #region GraphicsSetting private GraphicsSettingModel _graphicsSetting; public GraphicsSettingModel GraphicsSetting { get => _graphicsSetting; set => SetProperty(ref _graphicsSetting, value); } + #endregion + #region SystemSetting private SystemSettingModel _systemSetting; public SystemSettingModel SystemSetting @@ -48,13 +39,16 @@ public class SettingModel : ObservableClass get => _systemSetting; set => SetProperty(ref _systemSetting, value); } + #endregion + #region InteractiveSetting private InteractiveSettingModel _interactiveSetting; public InteractiveSettingModel InteractiveSetting { get => _interactiveSetting; set => SetProperty(ref _interactiveSetting, value); } + #endregion private static HashSet _settingProperties = new(typeof(Setting).GetProperties().Select(p => p.Name)); @@ -63,27 +57,35 @@ public class SettingModel : ObservableClass private ReflectionOptions _saveReflectionOptions = new() { CheckValueEquals = true }; + public SettingModel() + : this(new("")) { } + public SettingModel(Setting setting) { _setting = setting; - GraphicsSetting = LoadGraphicsSettings(); + GraphicsSetting = LoadSetting(); + InteractiveSetting = LoadSetting(); + SystemSetting = LoadSetting(); } - private GraphicsSettingModel LoadGraphicsSettings() + private T LoadSetting() + where T : new() { - var graphicsSetting = new GraphicsSettingModel(); - ReflectionUtils.SetValue(_setting, graphicsSetting); - return graphicsSetting; + var setting = new T(); + ReflectionUtils.SetValue(_setting, setting); + return setting; } public void Save() { - SaveGraphicsSettings(); + SaveSetting(GraphicsSetting); + SaveSetting(InteractiveSetting); + SaveSetting(SystemSetting); File.WriteAllText(FilePath, _setting.ToString()); } - private void SaveGraphicsSettings() + private void SaveSetting(object setting) { - ReflectionUtils.SetValue(GraphicsSetting, _setting, _saveReflectionOptions); + ReflectionUtils.SetValue(setting, _setting, _saveReflectionOptions); } } diff --git a/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs b/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs index 2386dd0..e5c5394 100644 --- a/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs +++ b/VPet.Solution/Models/SettingEditor/SystemSettingModel.cs @@ -1,4 +1,6 @@ -namespace VPet.Solution.Models.SettingEditor; +using System.Collections.ObjectModel; + +namespace VPet.Solution.Models.SettingEditor; public class SystemSettingModel : ObservableClass { @@ -7,47 +9,62 @@ 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; /// /// 自动保存频率 (min) /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoSaveInterval))] public int AutoSaveInterval { get => _autoSaveInterval; set => SetProperty(ref _autoSaveInterval, value); } + public static ObservableCollection SaveIntervals { get; } = + new() { -1, 2, 5, 10, 20, 30, 60 }; + #endregion + + #region BackupSaveMaxNum private int _backupSaveMaxNum; /// /// 备份保存最大数量 /// + [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.BackupSaveMaxNum))] public int BackupSaveMaxNum { get => _backupSaveMaxNum; set => SetProperty(ref _backupSaveMaxNum, value); } + #endregion } diff --git a/VPet.Solution/Styles.xaml b/VPet.Solution/Styles.xaml index 0b1c5b7..98cecb4 100644 --- a/VPet.Solution/Styles.xaml +++ b/VPet.Solution/Styles.xaml @@ -56,7 +56,7 @@ x:Key="TextBlock_BaseStyle" BasedOn="{StaticResource {x:Type TextBlock}}" TargetType="TextBlock"> - + @@ -139,7 +139,7 @@ \ No newline at end of file diff --git a/VPet.Solution/Utils/ReflectionUtils.cs b/VPet.Solution/Utils/ReflectionUtils.cs index 5358bb4..b271418 100644 --- a/VPet.Solution/Utils/ReflectionUtils.cs +++ b/VPet.Solution/Utils/ReflectionUtils.cs @@ -11,8 +11,13 @@ namespace HKW.HKWUtils; public static class ReflectionUtils { + private static readonly BindingFlags _propertyBindingFlags = + BindingFlags.Instance | BindingFlags.Public; + + private static readonly Dictionary _reflectionConverters = new(); + /// - /// 目标名称 + /// 类型信息 /// /// (TargetType, (PropertyName, TargetPropertyName)) /// @@ -20,15 +25,11 @@ public static class ReflectionUtils private static readonly Dictionary _typePropertyReflectionInfos = new(); - public static void SetValue( - TSource source, - TTarget target, - ReflectionOptions options = null! - ) + public static void SetValue(object source, object target, ReflectionOptions options = null!) { options ??= new(); - var sourceType = typeof(TSource); - var targetType = typeof(TTarget); + var sourceType = source.GetType(); + var targetType = target.GetType(); if (_typePropertyReflectionInfos.TryGetValue(sourceType, out var sourceInfo) is false) sourceInfo = _typePropertyReflectionInfos[sourceType] = GetReflectionObjectInfo( sourceType @@ -41,24 +42,26 @@ public static class ReflectionUtils var sourceAccessor = ObjectAccessor.Create(source); var targetAccessor = ObjectAccessor.Create(target); - foreach (var property in sourceType.GetProperties()) + foreach (var property in targetType.GetProperties(_propertyBindingFlags)) { - // 获取源属性名 - var sourcePropertyName = sourceInfo.PropertyInfos.TryGetValue( - property.Name, - out var sourceReflectionInfo - ) - ? sourceReflectionInfo.PropertyName - : property.Name; - if (targetInfo.PropertyNames.Contains(sourcePropertyName) is false) + // 尝试获取目标属性信息 + targetInfo.PropertyInfos.TryGetValue(property.Name, out var targetReflectionInfo); + // 检测忽视 + if (targetReflectionInfo?.IsIgnore is true) continue; - // 获取目标属性名 - var targetPropertyName = targetInfo.PropertyInfos.TryGetValue( - sourcePropertyName, - out var targetReflectionInfo - ) - ? targetReflectionInfo.PropertyName - : property.Name; + // 获取源属性名 + var sourcePropertyName = targetReflectionInfo is null + ? property.Name + : targetReflectionInfo.TargetName; + // 获取源属性信息 + sourceInfo.PropertyInfos.TryGetValue(sourcePropertyName, out var sourceReflectionInfo); + if (sourceInfo.PropertyNames.Contains(sourcePropertyName) is false) + { + if (targetReflectionInfo?.IsRequired is true) + options.UnassignedRequiredProperties.Add(property.Name); + continue; + } + // 获取源值 var sourceValue = sourceAccessor[sourcePropertyName]; // 转换源值 @@ -69,26 +72,62 @@ public static class ReflectionUtils // 比较源值和目标值 if (options.CheckValueEquals) { - var targetValue = targetAccessor[targetPropertyName]; + var targetValue = targetAccessor[property.Name]; if (sourceValue.Equals(targetValue)) continue; } - targetAccessor[targetPropertyName] = sourceValue; + targetAccessor[property.Name] = sourceValue; } } private static ReflectionObjectInfo GetReflectionObjectInfo(Type type) { var objectInfo = new ReflectionObjectInfo(type); - foreach (var property in type.GetProperties()) + foreach (var property in type.GetProperties(_propertyBindingFlags)) { - if (property.IsDefined(typeof(ReflectionPropertyInfoAttribute))) + // 获取是否被忽视 + if (property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute))) { - var reflectionInfo = property.GetCustomAttribute(); - if (string.IsNullOrWhiteSpace(reflectionInfo.PropertyName)) - reflectionInfo.PropertyName = property.Name; - objectInfo.PropertyInfos[property.Name] = reflectionInfo; + objectInfo.PropertyInfos[property.Name] = new(property.Name) { IsIgnore = true }; + continue; } + if ( + property.IsDefined(typeof(ReflectionPropertyAttribute)) is false + && property.IsDefined(typeof(ReflectionPropertyConverterAttribute)) is false + ) + continue; + var propertyInfo = new ReflectionPropertyInfo(property.Name); + // 获取属性信息 + if ( + property.GetCustomAttribute() + is ReflectionPropertyAttribute propertyInfoAttribute + ) + { + if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetPropertyName) is false) + propertyInfo.TargetName = propertyInfoAttribute.TargetPropertyName; + propertyInfo.IsRequired = propertyInfoAttribute.IsRequired; + } + // 获取属性转换器 + if ( + property.GetCustomAttribute() + is ReflectionPropertyConverterAttribute propertyConverterAttribute + ) + { + if ( + _reflectionConverters.TryGetValue( + propertyConverterAttribute.ConverterType, + out var converter + ) + is false + ) + converter = _reflectionConverters[propertyConverterAttribute.ConverterType] = + (IReflectionConverter) + TypeAccessor + .Create(propertyConverterAttribute.ConverterType) + .CreateNew(); + propertyInfo.Converter = converter; + } + objectInfo.PropertyInfos[property.Name] = propertyInfo; } return objectInfo; } @@ -101,41 +140,97 @@ public class ReflectionObjectInfo { public HashSet PropertyNames { get; } - public Dictionary PropertyInfos { get; } = new(); + public Dictionary PropertyInfos { get; } = new(); public ReflectionObjectInfo(Type type) { - PropertyNames = new(type.GetProperties().Select(p => p.Name)); + PropertyNames = new( + type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => p.Name) + ); + } +} + +public class ReflectionPropertyInfo +{ + /// + /// 目标属性名称 + /// + public string TargetName { get; set; } + + /// + /// 是必要的 + /// + [DefaultValue(false)] + public bool IsRequired { get; set; } = false; + + /// + /// 是忽视的 + /// + public bool IsIgnore { get; set; } = false; + + /// + /// 反射值转换器 + /// + public IReflectionConverter? Converter { get; set; } = null; + + public ReflectionPropertyInfo(string propertyName) + { + TargetName = propertyName; } } /// /// 反射属性信息 /// -public class ReflectionPropertyInfoAttribute : Attribute +[AttributeUsage(AttributeTargets.Property)] +public class ReflectionPropertyAttribute : Attribute { /// - /// 目标属性名称 + /// 属性名称 /// - public string PropertyName { get; set; } + public string TargetPropertyName { get; } + /// + /// 是必要的 + /// + [DefaultValue(true)] + public bool IsRequired { get; } = true; + + public ReflectionPropertyAttribute(bool isRequired = true) + { + IsRequired = isRequired; + } + + public ReflectionPropertyAttribute(string targetPropertyName, bool isRequired = true) + { + TargetPropertyName = targetPropertyName; + IsRequired = isRequired; + } +} + +/// +/// 反射属性转换器 +/// +[AttributeUsage(AttributeTargets.Property)] +public class ReflectionPropertyConverterAttribute : Attribute +{ /// /// 反射转换器 /// - public IReflectionConverter? Converter { get; } = null; + public Type ConverterType { get; } - public ReflectionPropertyInfoAttribute(Type converterType) - : this(string.Empty, converterType) { } - - public ReflectionPropertyInfoAttribute(string name, Type? converterType = null) + public ReflectionPropertyConverterAttribute(Type converterType) { - PropertyName = name; - if (converterType is null) - return; - Converter = (IReflectionConverter)TypeAccessor.Create(converterType).CreateNew(); + ConverterType = converterType; } } +/// +/// 反射属性忽视 +/// +[AttributeUsage(AttributeTargets.Property)] +public class ReflectionPropertyIgnoreAttribute : Attribute { } + /// /// 反射设置 /// @@ -146,6 +241,11 @@ public class ReflectionOptions /// [DefaultValue(false)] public bool CheckValueEquals { get; set; } = false; + + /// + /// 未赋值的必要属性 + /// + public List UnassignedRequiredProperties { get; set; } = new(); } /// diff --git a/VPet.Solution/Utils/Utils.cs b/VPet.Solution/Utils/Utils.cs index 367f70c..0e4e157 100644 --- a/VPet.Solution/Utils/Utils.cs +++ b/VPet.Solution/Utils/Utils.cs @@ -77,6 +77,13 @@ public static class Utils return bitmapImage; } + /// + /// 获取布尔值 + /// + /// 值 + /// 目标布尔值 + /// 为空时布尔值 + /// public static bool GetBool(object value, bool boolValue, bool nullValue) { if (value is null) @@ -88,4 +95,26 @@ public static class Utils else return false; } + + /// + /// 打开文件 + /// + /// 文件路径 + public static void OpenFile(string filePath) + { + System.Diagnostics.Process + .Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true }) + ?.Close(); + } + + /// + /// 从资源管理器打开文件 + /// + /// 文件路径 + public static void OpenFileInExplorer(string filePath) + { + System.Diagnostics.Process + .Start("Explorer", $"/select,{Path.GetFullPath(filePath)}") + ?.Close(); + } } diff --git a/VPet.Solution/VPet.Solution.csproj b/VPet.Solution/VPet.Solution.csproj index 3ecc9ff..1087f57 100644 --- a/VPet.Solution/VPet.Solution.csproj +++ b/VPet.Solution/VPet.Solution.csproj @@ -95,6 +95,8 @@ + + @@ -103,11 +105,23 @@ + + + + + SaveDataPage.xaml + + + SaveStatisticPage.xaml + + + SaveWindow.xaml + SettingWindow.xaml @@ -135,6 +149,18 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -250,10 +276,6 @@ VPet-Simulator.Windows.Interface - - - - - + \ No newline at end of file diff --git a/VPet.Solution/ViewModels/SaveViewer/SaveDataPageVM.cs b/VPet.Solution/ViewModels/SaveViewer/SaveDataPageVM.cs new file mode 100644 index 0000000..9bc73ee --- /dev/null +++ b/VPet.Solution/ViewModels/SaveViewer/SaveDataPageVM.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VPet.Solution.Models.SaveViewer; +using VPet.Solution.Views.SaveViewer; + +namespace VPet.Solution.ViewModels.SaveViewer; + +public class SaveDataPageVM : ObservableClass +{ + private SaveModel _save; + public SaveModel Save + { + get => _save; + set => SetProperty(ref _save, value); + } + + public SaveDataPageVM() + { + SaveWindowVM.Current.PropertyChangedX += Current_PropertyChangedX; + } + + private void Current_PropertyChangedX(SaveWindowVM sender, PropertyChangedXEventArgs e) + { + if (e.PropertyName == nameof(SaveWindowVM.CurrentSave) && sender.CurrentSave is not null) + { + Save = sender.CurrentSave; + } + } +} diff --git a/VPet.Solution/ViewModels/SaveViewer/SaveStatisticPageVM.cs b/VPet.Solution/ViewModels/SaveViewer/SaveStatisticPageVM.cs new file mode 100644 index 0000000..fd5f8ed --- /dev/null +++ b/VPet.Solution/ViewModels/SaveViewer/SaveStatisticPageVM.cs @@ -0,0 +1,71 @@ +using HKW.HKWUtils.Observable; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VPet.Solution.Models.SaveViewer; + +namespace VPet.Solution.ViewModels.SaveViewer; + +public class SaveStatisticPageVM : ObservableClass +{ + #region Properties + #region Save + private SaveModel _save; + public SaveModel Save + { + get => _save; + set => SetProperty(ref _save, value); + } + #endregion + + #region ShowStatistics + private IEnumerable _showStatistics; + public IEnumerable ShowStatistics + { + get => _showStatistics; + set => SetProperty(ref _showStatistics, value); + } + #endregion + + #region SearchStatistic + private string _searchStatistic; + public string SearchStatistic + { + get => _searchStatistic; + set + { + SetProperty(ref _searchStatistic, value); + RefreshShowStatistics(value); + } + } + #endregion + #endregion + + + public SaveStatisticPageVM() + { + SaveWindowVM.Current.PropertyChangedX += Current_PropertyChangedX; + } + + private void Current_PropertyChangedX(SaveWindowVM sender, PropertyChangedXEventArgs e) + { + if (e.PropertyName == nameof(SaveWindowVM.CurrentSave) && sender.CurrentSave is not null) + { + Save = sender.CurrentSave; + ShowStatistics = Save.Statistics; + } + } + + public void RefreshShowStatistics(string name) + { + if (string.IsNullOrWhiteSpace(name)) + ShowStatistics = Save.Statistics; + else + ShowStatistics = Save.Statistics.Where( + s => s.Name.Contains(SearchStatistic, StringComparison.OrdinalIgnoreCase) + ); + } +} diff --git a/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs b/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs new file mode 100644 index 0000000..a12d9c2 --- /dev/null +++ b/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs @@ -0,0 +1,114 @@ +using HKW.HKWUtils.Observable; +using LinePutScript; +using LinePutScript.Localization.WPF; +using Panuon.WPF.UI; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using VPet.Solution.Models; +using VPet.Solution.Models.SaveViewer; +using VPet.Solution.Models.SettingEditor; +using VPet.Solution.Views.SettingEditor; +using VPet_Simulator.Windows.Interface; + +namespace VPet.Solution.ViewModels.SaveViewer; + +public class SaveWindowVM : ObservableClass +{ + public static SaveWindowVM Current { get; private set; } + + #region Properties + private SaveModel _currentSave; + public SaveModel CurrentSave + { + get => _currentSave; + set => SetProperty(ref _currentSave, value); + } + + private readonly ObservableCollection _saves = new(); + + private IEnumerable _showSaves; + public IEnumerable ShowSaves + { + get => _showSaves; + set => SetProperty(ref _showSaves, value); + } + + private string _searchSave; + public string SearchSave + { + get => _searchSave; + set => SetProperty(ref _searchSave, value); + } + + #endregion + + #region Command + /// + /// 打开文件 + /// + public ObservableCommand OpenFileCommand { get; } = new(); + + /// + /// 从资源管理器打开 + /// + public ObservableCommand OpenFileInExplorerCommand { get; } = new(); + #endregion + public SaveWindowVM() + { + Current = this; + ShowSaves = _saves; + LoadSaves(); + + PropertyChanged += SaveWindowVM_PropertyChanged; + OpenFileCommand.ExecuteCommand += OpenFileCommand_ExecuteCommand; + OpenFileInExplorerCommand.ExecuteCommand += OpenFileInExplorerCommand_ExecuteCommand; + } + + private void OpenFileInExplorerCommand_ExecuteCommand(SaveModel parameter) + { + Utils.OpenFileInExplorer(parameter.FilePath); + } + + private void OpenFileCommand_ExecuteCommand(SaveModel parameter) + { + Utils.OpenFile(parameter.FilePath); + } + + public void RefreshShowSaves(string name) + { + if (string.IsNullOrWhiteSpace(name)) + ShowSaves = _saves; + else + ShowSaves = _saves.Where( + s => s.Name.Contains(SearchSave, StringComparison.OrdinalIgnoreCase) + ); + } + + private void SaveWindowVM_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(SearchSave)) + { + RefreshShowSaves(SearchSave); + } + } + + private void LoadSaves() + { + var saveDirectory = Path.Combine(Environment.CurrentDirectory, "Saves"); + if (Directory.Exists(saveDirectory) is false) + return; + foreach (var file in Directory.EnumerateFiles(saveDirectory).Where(s => s.EndsWith(".lps"))) + { + var lps = new LPS(File.ReadAllText(file)); + var save = new GameSave_v2(lps); + var saveModel = new SaveModel(file, save); + _saves.Add(saveModel); + } + } +} diff --git a/VPet.Solution/ViewModels/SettingEditor/InteractiveSettingPageVM.cs b/VPet.Solution/ViewModels/SettingEditor/InteractiveSettingPageVM.cs index d368ebb..2eda9c8 100644 --- a/VPet.Solution/ViewModels/SettingEditor/InteractiveSettingPageVM.cs +++ b/VPet.Solution/ViewModels/SettingEditor/InteractiveSettingPageVM.cs @@ -24,7 +24,10 @@ public class InteractiveSettingPageVM : ObservableClass #endregion #region Command + /// + /// 打开文件 + /// + public ObservableCommand OpenFileCommand { get; } = new(); + + /// + /// 从资源管理器打开 + /// + public ObservableCommand OpenFileInExplorerCommand { get; } = new(); + + /// + /// 重置 + /// public ObservableCommand ResetSettingCommand { get; } = new(); + + /// + /// 保存 + /// public ObservableCommand SaveSettingCommand { get; } = new(); + + /// + /// 保存全部 + /// public ObservableCommand SaveAllSettingCommand { get; } = new(); #endregion public SettingWindowVM() { Current = this; ShowSettings = _settings; - - foreach (var s in LoadSettings()) - _settings.Add(s); + LoadSettings(); PropertyChanged += MainWindowVM_PropertyChanged; + OpenFileCommand.ExecuteCommand += OpenFileCommand_ExecuteCommand; + OpenFileInExplorerCommand.ExecuteCommand += OpenFileInExplorerCommand_ExecuteCommand; ResetSettingCommand.ExecuteCommand += ResetSettingCommand_ExecuteCommand; SaveSettingCommand.ExecuteCommand += SaveSettingCommand_ExecuteCommand; SaveAllSettingCommand.ExecuteCommand += SaveAllSettingCommand_ExecuteCommand; } + private void OpenFileInExplorerCommand_ExecuteCommand(SettingModel parameter) + { + Utils.OpenFileInExplorer(parameter.FilePath); + } + + private void OpenFileCommand_ExecuteCommand(SettingModel parameter) + { + Utils.OpenFile(parameter.FilePath); + } + private void SaveAllSettingCommand_ExecuteCommand() { + if ( + MessageBox.Show( + SettingWindow.Instance, + "确定全部保存吗".Translate(), + "", + MessageBoxButton.YesNo, + MessageBoxImage.Warning + ) + is not MessageBoxResult.Yes + ) + return; foreach (var setting in _settings) setting.Save(); } @@ -90,9 +132,7 @@ public class SettingWindowVM : ObservableClass is not MessageBoxResult.Yes ) return; - CurrentSetting = _settings[_settings.IndexOf(CurrentSetting)] = new SettingModel( - new Setting("") - ) + CurrentSetting = _settings[_settings.IndexOf(CurrentSetting)] = new SettingModel() { Name = CurrentSetting.Name, FilePath = CurrentSetting.FilePath @@ -118,27 +158,47 @@ public class SettingWindowVM : ObservableClass } } - public static IEnumerable LoadSettings() + private void LoadSettings() { - foreach ( - var file in Directory - .EnumerateFiles(Environment.CurrentDirectory) - .Where( - (s) => - { - if (s.EndsWith(".lps") is false) - return false; - return Path.GetFileName(s).StartsWith("Setting"); - } - ) - ) + foreach (var file in GetSettingFiles()) { - var setting = new Setting(File.ReadAllText(file)); - yield return new SettingModel(setting) + var fileName = Path.GetFileNameWithoutExtension(file); + try { - Name = Path.GetFileNameWithoutExtension(file), - FilePath = file - }; + var setting = new Setting(File.ReadAllText(file)); + var settingModel = new SettingModel(setting) { Name = fileName, FilePath = file }; + _settings.Add(settingModel); + } + catch (Exception ex) + { + if ( + MessageBox.Show( + "设置载入失败, 是否强制载入并重置\n[是]: 载入并重置\t[否]: 取消载入\n名称: {0}\n路径: {1}\n异常: {2}".Translate( + fileName, + file, + ex.ToString() + ), + "载入设置出错".Translate(), + MessageBoxButton.YesNo, + MessageBoxImage.Warning + ) is MessageBoxResult.Yes + ) + _settings.Add(new SettingModel() { Name = fileName, FilePath = file }); + } } } + + private static IEnumerable GetSettingFiles() + { + return Directory + .EnumerateFiles(Environment.CurrentDirectory) + .Where( + (s) => + { + if (s.EndsWith(".lps") is false) + return false; + return Path.GetFileName(s).StartsWith("Setting"); + } + ); + } } diff --git a/VPet.Solution/ViewModels/SettingEditor/SystemSettingPageVM.cs b/VPet.Solution/ViewModels/SettingEditor/SystemSettingPageVM.cs index 2055e24..9556195 100644 --- a/VPet.Solution/ViewModels/SettingEditor/SystemSettingPageVM.cs +++ b/VPet.Solution/ViewModels/SettingEditor/SystemSettingPageVM.cs @@ -11,12 +11,15 @@ namespace VPet.Solution.ViewModels.SettingEditor; public class SystemSettingPageVM : ObservableClass { + #region SystemSetting + private SystemSettingModel _systemSetting; public SystemSettingModel SystemSetting { get => _systemSetting; set => SetProperty(ref _systemSetting, value); } + #endregion public SystemSettingPageVM() { @@ -25,7 +28,10 @@ public class SystemSettingPageVM : ObservableClass private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e) { - if (e.PropertyName == nameof(SettingWindowVM.CurrentSetting)) + if ( + e.PropertyName == nameof(SettingWindowVM.CurrentSetting) + && sender.CurrentSetting is not null + ) { SystemSetting = sender.CurrentSetting.SystemSetting; } diff --git a/VPet.Solution/Views/MainWindow.xaml b/VPet.Solution/Views/MainWindow.xaml index f553737..2168a95 100644 --- a/VPet.Solution/Views/MainWindow.xaml +++ b/VPet.Solution/Views/MainWindow.xaml @@ -31,7 +31,8 @@ public partial class CustomizedSettingPage : Page { + public CustomizedSettingPageVM ViewModel => (CustomizedSettingPageVM)DataContext; + public CustomizedSettingPage() { InitializeComponent(); + this.SetViewModel(); } } diff --git a/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml.cs b/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml.cs index 917e74b..add4b88 100644 --- a/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml.cs +++ b/VPet.Solution/Views/SettingEditor/DiagnosticSettingPage.xaml.cs @@ -12,6 +12,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using VPet.Solution.ViewModels.SettingEditor; namespace VPet.Solution.Views.SettingEditor; @@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor; /// public partial class DiagnosticSettingPage : Page { + public DiagnosticSettingPageVM ViewModel => (DiagnosticSettingPageVM)DataContext; + public DiagnosticSettingPage() { InitializeComponent(); + this.SetViewModel(); } } diff --git a/VPet.Solution/Views/SettingEditor/GraphicsSettingPage.xaml b/VPet.Solution/Views/SettingEditor/GraphicsSettingPage.xaml index f58d0de..f249265 100644 --- a/VPet.Solution/Views/SettingEditor/GraphicsSettingPage.xaml +++ b/VPet.Solution/Views/SettingEditor/GraphicsSettingPage.xaml @@ -52,9 +52,8 @@ @@ -153,7 +152,8 @@ ToolTip="{ll:Str '桌宠图形渲染的分辨率,越高图形越清晰\ 但是高分辨率会占用更多内存\ 重启后生效'}" Value="{Binding Value, ElementName=Slider_Resolution}" /> - + + @@ -223,11 +223,12 @@ Value="{Binding GraphicsSetting.StartRecordPoint.Y}" />