diff --git a/VPet.Solution/Models/SaveViewer/SaveModel.cs b/VPet.Solution/Models/SaveViewer/SaveModel.cs new file mode 100644 index 0000000..44c7d9e --- /dev/null +++ b/VPet.Solution/Models/SaveViewer/SaveModel.cs @@ -0,0 +1,188 @@ +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(); + + #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 + + public SaveModel(string filePath, GameSave_v2 save) + { + Name = Path.GetFileNameWithoutExtension(filePath); + FilePath = filePath; + DateSaved = File.GetLastWriteTime(filePath); + LoadSave(save.GameSave); + 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/Utils/ReflectionUtils.cs b/VPet.Solution/Utils/ReflectionUtils.cs index bb87422..76223ae 100644 --- a/VPet.Solution/Utils/ReflectionUtils.cs +++ b/VPet.Solution/Utils/ReflectionUtils.cs @@ -46,6 +46,9 @@ public static class ReflectionUtils { // 尝试获取目标属性信息 targetInfo.PropertyInfos.TryGetValue(property.Name, out var targetReflectionInfo); + // 检测忽视 + if (targetReflectionInfo?.IsIgnore is true) + continue; // 获取源属性名 var sourcePropertyName = targetReflectionInfo is null ? property.Name @@ -82,8 +85,14 @@ public static class ReflectionUtils var objectInfo = new ReflectionObjectInfo(type); foreach (var property in type.GetProperties(_propertyBindingFlags)) { + // 获取是否被忽视 + if (property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute))) + { + objectInfo.PropertyInfos[property.Name] = new(property.Name) { IsIgnore = true }; + continue; + } if ( - property.IsDefined(typeof(ReflectionPropertyAttribute)) is false + property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute)) && property.IsDefined(typeof(ReflectionPropertyConverterAttribute)) is false ) continue; @@ -94,8 +103,8 @@ public static class ReflectionUtils is ReflectionPropertyAttribute propertyInfoAttribute ) { - if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetName) is false) - propertyInfo.TargetName = propertyInfoAttribute.TargetName; + if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetPropertyName) is false) + propertyInfo.TargetName = propertyInfoAttribute.TargetPropertyName; propertyInfo.IsRequired = propertyInfoAttribute.IsRequired; } // 获取属性转换器 @@ -151,8 +160,13 @@ public class ReflectionPropertyInfo /// /// 是必要的 /// - [DefaultValue(true)] - public bool IsRequired { get; set; } = true; + [DefaultValue(false)] + public bool IsRequired { get; set; } = false; + + /// + /// 是忽视的 + /// + public bool IsIgnore { get; set; } = false; /// /// 反射值转换器 @@ -174,7 +188,7 @@ public class ReflectionPropertyAttribute : Attribute /// /// 属性名称 /// - public string TargetName { get; } + public string TargetPropertyName { get; } /// /// 是必要的 @@ -187,9 +201,9 @@ public class ReflectionPropertyAttribute : Attribute IsRequired = isRequired; } - public ReflectionPropertyAttribute(string name, bool isRequired = true) + public ReflectionPropertyAttribute(string targetPropertyName, bool isRequired = true) { - TargetName = name; + TargetPropertyName = targetPropertyName; IsRequired = isRequired; } } @@ -211,6 +225,15 @@ public class ReflectionPropertyConverterAttribute : Attribute } } +/// +/// 反射属性忽视 +/// +[AttributeUsage(AttributeTargets.Property)] +public class ReflectionPropertyIgnoreAttribute : Attribute +{ + public ReflectionPropertyIgnoreAttribute() { } +} + /// /// 反射设置 /// 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..885db67 --- /dev/null +++ b/VPet.Solution/ViewModels/SaveViewer/SaveWindowVM.cs @@ -0,0 +1,111 @@ +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"); + foreach (var file in Directory.EnumerateFiles(saveDirectory)) + { + var save = new GameSave_v2(new LPS(File.ReadAllText(file))); + var saveModel = new SaveModel(file, save); + _saves.Add(saveModel); + } + } +} 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 @@