diff --git a/VPet.ModMaker/Models/EnumFlagsVM.cs b/VPet.ModMaker/Models/EnumFlagsVM.cs new file mode 100644 index 0000000..02e6c25 --- /dev/null +++ b/VPet.ModMaker/Models/EnumFlagsVM.cs @@ -0,0 +1,56 @@ +using HKW.HKWViewModels.SimpleObservable; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VPet.ModMaker.Models; + +public class EnumFlagsVM + where T : Enum +{ + public ObservableValue EnumValue { get; } = new(); + + public ObservableCommand AddCommand { get; } = new(); + public ObservableCommand RemoveCommand { get; } = new(); + + public Type EnumType = typeof(T); + public Type UnderlyingType { get; } = Enum.GetUnderlyingType(typeof(T)); + + public EnumFlagsVM() + { + AddCommand.ExecuteEvent += AddCommand_ExecuteEvent; + RemoveCommand.ExecuteEvent += RemoveCommand_ExecuteEvent; + } + + public EnumFlagsVM(T value) + : this() + { + EnumValue.Value = value; + } + + private void AddCommand_ExecuteEvent(T value) + { + if (UnderlyingType == typeof(int)) + { + EnumValue.Value = (T) + Enum.Parse( + EnumType, + (Convert.ToInt32(EnumValue.Value) | Convert.ToInt32(value)).ToString() + ); + } + } + + private void RemoveCommand_ExecuteEvent(T value) + { + if (UnderlyingType == typeof(int)) + { + EnumValue.Value = (T) + Enum.Parse( + EnumType, + (Convert.ToInt32(EnumValue.Value) & ~Convert.ToInt32(value)).ToString() + ); + } + } +} diff --git a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs index ce321aa..8655751 100644 --- a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs +++ b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs @@ -176,10 +176,13 @@ public class ModInfoModel : I18nModel } ); } - var imagePath = Image.Value.GetSourceFile(); - var targetImagePath = Path.Combine(path, Path.GetFileName(imagePath)); - if (imagePath != targetImagePath) - File.Copy(imagePath, targetImagePath, true); + if (Image.Value is not null) + { + var imagePath = Image.Value.GetSourceFile(); + var targetImagePath = Path.Combine(path, Path.GetFileName(imagePath)); + if (imagePath != targetImagePath) + File.Copy(imagePath, targetImagePath, true); + } File.WriteAllText(modInfoFile, lps.ToString()); SavePets(path); SaveFoods(path); @@ -206,10 +209,19 @@ public class ModInfoModel : I18nModel var lps = new LPS(); GetPetInfo(lps, pet); GetWorksInfo(lps, pet); + GetMoveInfo(lps, pet); File.WriteAllText(petFile, lps.ToString()); } } + void GetMoveInfo(LPS lps, PetModel pet) + { + foreach (var move in pet.Moves) + { + lps.Add(LPSConvert.SerializeObjectToLine(move.ToMove(), "move")); + } + } + void GetWorksInfo(LPS lps, PetModel pet) { foreach (var work in pet.Works) diff --git a/VPet.ModMaker/Models/ModModel/MoveModel.cs b/VPet.ModMaker/Models/ModModel/MoveModel.cs index b6dedd4..e0d8237 100644 --- a/VPet.ModMaker/Models/ModModel/MoveModel.cs +++ b/VPet.ModMaker/Models/ModModel/MoveModel.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; using VPet_Simulator.Core; -namespace VPet.ModMaker.Models.ModModel; +namespace VPet.ModMaker.Models; public class MoveModel { @@ -24,28 +24,32 @@ public class MoveModel public ObservableValue Graph { get; } = new(); public ObservableValue Distance { get; } = new(5); public ObservableValue Interval { get; } = new(125); + public ObservableValue LocateLength { get; } = new(); + public ObservableValue SpeedX { get; } = new(); + public ObservableValue SpeedY { get; } = new(); public ObservableValue CheckLeft { get; } = new(100); public ObservableValue CheckRight { get; } = new(100); public ObservableValue CheckTop { get; } = new(100); public ObservableValue CheckBottom { get; } = new(100); - public ObservableValue SpeedX { get; } = new(); - public ObservableValue SpeedY { get; } = new(); - public ObservableValue LocateLength { get; } = new(); public ObservableValue TriggerLeft { get; } = new(100); public ObservableValue TriggerRight { get; } = new(100); public ObservableValue TriggerTop { get; } = new(100); public ObservableValue TriggerBottom { get; } = new(100); - public ObservableValue DirectionType { get; } = new(); + public EnumFlagsVM LocateType { get; } = + new(GraphHelper.Move.DirectionType.None); + public EnumFlagsVM TriggerType { get; } = + new(GraphHelper.Move.DirectionType.None); - public ObservableValue ModeType { get; } = new(); + public EnumFlagsVM ModeType { get; } = + new(GraphHelper.Move.ModeType.Nomal); public MoveModel() { } public MoveModel(MoveModel model) : this() { - //Id.Value = model.Id.Value; + //Id.EnumValue = model.Id.EnumValue; Graph.Value = model.Graph.Value; Distance.Value = model.Distance.Value; Interval.Value = model.Interval.Value; @@ -60,14 +64,15 @@ public class MoveModel TriggerRight.Value = model.TriggerRight.Value; TriggerTop.Value = model.TriggerTop.Value; TriggerBottom.Value = model.TriggerBottom.Value; - DirectionType.Value = model.DirectionType.Value; - ModeType.Value = model.ModeType.Value; + LocateType.EnumValue.Value = model.LocateType.EnumValue.Value; + TriggerType.EnumValue.Value = model.TriggerType.EnumValue.Value; + ModeType.EnumValue.Value = model.ModeType.EnumValue.Value; } public MoveModel(GraphHelper.Move move) : this() { - //Id.Value = move.Id.Value; + //Id.EnumValue = move.Id.EnumValue; Graph.Value = move.Graph; Distance.Value = move.Distance; Interval.Value = move.Interval; @@ -82,8 +87,9 @@ public class MoveModel TriggerRight.Value = move.TriggerRight; TriggerTop.Value = move.TriggerTop; TriggerBottom.Value = move.TriggerBottom; - DirectionType.Value = move.TriggerType; - ModeType.Value = move.Mode; + LocateType.EnumValue.Value = move.LocateType; + TriggerType.EnumValue.Value = move.TriggerType; + ModeType.EnumValue.Value = move.Mode; } public GraphHelper.Move ToMove() @@ -104,8 +110,9 @@ public class MoveModel TriggerRight = TriggerRight.Value, TriggerTop = TriggerTop.Value, TriggerBottom = TriggerBottom.Value, - TriggerType = DirectionType.Value, - Mode = ModeType.Value, + LocateType = LocateType.EnumValue.Value, + TriggerType = TriggerType.EnumValue.Value, + Mode = ModeType.EnumValue.Value, }; } } diff --git a/VPet.ModMaker/Models/ModModel/PetModel.cs b/VPet.ModMaker/Models/ModModel/PetModel.cs index 0131f0a..5e2cbc9 100644 --- a/VPet.ModMaker/Models/ModModel/PetModel.cs +++ b/VPet.ModMaker/Models/ModModel/PetModel.cs @@ -22,6 +22,8 @@ public class PetModel : I18nModel public ObservableCollection Works { get; } = new(); + public ObservableCollection Moves { get; } = new(); + public PetModel() { PetNameId.Value = $"{Id.Value}_{nameof(PetNameId)}"; @@ -106,6 +108,8 @@ public class PetModel : I18nModel foreach (var work in loader.Config.Works) Works.Add(new(work)); + foreach (var move in loader.Config.Moves) + Moves.Add(new(move)); } public void Close() { } diff --git a/VPet.ModMaker/Models/ModModel/SelectTextModel.cs b/VPet.ModMaker/Models/ModModel/SelectTextModel.cs index ac6233f..36f764e 100644 --- a/VPet.ModMaker/Models/ModModel/SelectTextModel.cs +++ b/VPet.ModMaker/Models/ModModel/SelectTextModel.cs @@ -59,9 +59,9 @@ public class SelectTextModel : I18nModel Mode.Value = model.Mode.Value; Tags.Value = model.Tags.Value; ToTags.Value = model.ToTags.Value; - //Working.Value = model.Working.Value; - //WorkingState.Value = model.WorkingState.Value; - //DayTime.Value = model.DayTime.Value; + //Working.EnumValue = model.Working.EnumValue; + //WorkingState.EnumValue = model.WorkingState.EnumValue; + //DayTime.EnumValue = model.DayTime.EnumValue; Like = model.Like.Copy(); Health = model.Health.Copy(); Level = model.Level.Copy(); @@ -84,9 +84,9 @@ public class SelectTextModel : I18nModel Mode.Value = text.Mode; Tags.Value = text.Tags is null ? string.Empty : string.Join(", ", text.Tags); ToTags.Value = text.ToTags is null ? string.Empty : string.Join(", ", text.ToTags); - //Working.Value = text.Working; - //WorkingState.Value = text.State; - //DayTime.Value = text.DaiTime; + //Working.EnumValue = text.Working; + //WorkingState.EnumValue = text.State; + //DayTime.EnumValue = text.DaiTime; Like.SetValue(text.LikeMin, text.LikeMax); Health.SetValue(text.HealthMin, text.HealthMax); Level.SetValue(text.LevelMin, text.LevelMax); @@ -108,9 +108,9 @@ public class SelectTextModel : I18nModel Mode = Mode.Value, Tags = new(Tags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)), ToTags = new(ToTags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)), - //Working = Working.Value, - //State = WorkingState.Value, - //DaiTime = DayTime.Value, + //Working = Working.EnumValue, + //State = WorkingState.EnumValue, + //DaiTime = DayTime.EnumValue, LikeMax = Like.Max.Value, LikeMin = Like.Min.Value, HealthMin = Health.Min.Value, diff --git a/VPet.ModMaker/SimpleObservable/ObservableCommand.cs b/VPet.ModMaker/SimpleObservable/ObservableCommand.cs index 7fdfd20..672de43 100644 --- a/VPet.ModMaker/SimpleObservable/ObservableCommand.cs +++ b/VPet.ModMaker/SimpleObservable/ObservableCommand.cs @@ -13,7 +13,7 @@ namespace HKW.HKWViewModels.SimpleObservable; /// 可观察命令 /// [DebuggerDisplay( - "CanExecute = {CanExecuteProperty.Value}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}" + "CanExecute = {CanExecuteProperty.EnumValue}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}" )] public class ObservableCommand : ICommand { @@ -95,8 +95,8 @@ public class ObservableCommand : ICommand /// { /// canExecute = false; // trigger this /// }; - /// value.Value = "A"; // execute this - /// // result: value.Value == "A" , command.CanExecuteProperty == false + /// value.EnumValue = "A"; // execute this + /// // result: value.EnumValue == "A" , command.CanExecuteProperty == false /// ]]> /// /// diff --git a/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs b/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs index 10dc7fb..a9e2706 100644 --- a/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs +++ b/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs @@ -14,7 +14,7 @@ namespace HKW.HKWViewModels.SimpleObservable; /// /// 参数类型 [DebuggerDisplay( - "CanExecute = {CanExecuteProperty.Value}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}" + "CanExecute = {CanExecuteProperty.EnumValue}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}" )] public class ObservableCommand : ICommand where T : notnull diff --git a/VPet.ModMaker/SimpleObservable/ObservableValue.cs b/VPet.ModMaker/SimpleObservable/ObservableValue.cs index 292172b..0511539 100644 --- a/VPet.ModMaker/SimpleObservable/ObservableValue.cs +++ b/VPet.ModMaker/SimpleObservable/ObservableValue.cs @@ -12,7 +12,7 @@ namespace HKW.HKWViewModels.SimpleObservable; /// 可观察值 /// /// -[DebuggerDisplay("{Value}")] +[DebuggerDisplay("{EnumValue}")] public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChanged { [DebuggerBrowsable(DebuggerBrowsableState.Never)] @@ -93,8 +93,8 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange /// { /// v = "B"; // trigger this /// }; - /// value1.Value = "A"; // execute this - /// // result: value1.Value == "A" , value2.Value == "B" + /// value1.EnumValue = "A"; // execute this + /// // result: value1.EnumValue == "A" , value2.EnumValue == "B" /// ]]> /// /// diff --git a/VPet.ModMaker/VPet.ModMaker.csproj b/VPet.ModMaker/VPet.ModMaker.csproj index 5bc53ea..5111afb 100644 --- a/VPet.ModMaker/VPet.ModMaker.csproj +++ b/VPet.ModMaker/VPet.ModMaker.csproj @@ -97,6 +97,7 @@ + @@ -120,6 +121,8 @@ + + @@ -169,6 +172,12 @@ ModEditWindow.xaml + + MoveEditWindow.xaml + + + MovePage.xaml + PetEditWindow.xaml @@ -250,6 +259,14 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs new file mode 100644 index 0000000..038dd5f --- /dev/null +++ b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs @@ -0,0 +1,73 @@ +using HKW.HKWViewModels.SimpleObservable; +using LinePutScript.Localization.WPF; +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using VPet.ModMaker.Models; + +namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit; + +public class MoveEditWindowVM +{ + #region Value + public PetModel CurrentPet { get; set; } + public MoveModel OldMove { get; set; } + public ObservableValue Move { get; } = new(new()); + #endregion + public ObservableValue BorderLength { get; } = new(250); + public ObservableValue LengthRatio { get; } = new(250.0 / 500.0); + public ObservableValue Image { get; } = new(); + #region Command + public ObservableCommand AddImageCommand { get; } = new(); + public ObservableCommand ChangeImageCommand { get; } = new(); + #endregion + public MoveEditWindowVM() + { + AddImageCommand.ExecuteEvent += AddImage; + ChangeImageCommand.ExecuteEvent += ChangeImage; + Image.ValueChanged += Image_ValueChanged; + } + + private void Image_ValueChanged(BitmapImage oldValue, BitmapImage newValue) + { + //LengthRatio.EnumValue = BorderLength.EnumValue / value.PixelWidth; + } + + public void Close() + { + Image.Value?.StreamSource?.Close(); + } + + private void AddImage() + { + OpenFileDialog openFileDialog = + new() + { + Title = "选择图片".Translate(), + Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate() + }; + if (openFileDialog.ShowDialog() is true) + { + Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + } + } + + private void ChangeImage() + { + OpenFileDialog openFileDialog = + new() + { + Title = "选择图片".Translate(), + Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate() + }; + if (openFileDialog.ShowDialog() is true) + { + Image.Value?.StreamSource?.Close(); + Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + } + } +} diff --git a/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MovePageVM.cs b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MovePageVM.cs new file mode 100644 index 0000000..8c8c909 --- /dev/null +++ b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MovePageVM.cs @@ -0,0 +1,108 @@ +using HKW.HKWViewModels.SimpleObservable; +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 System.Windows; +using VPet.ModMaker.Models; +using VPet.ModMaker.Views.ModEdit.MoveEdit; + +namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit; + +public class MovePageVM +{ + #region Value + public ObservableValue> ShowMoves { get; } = new(); + public ObservableCollection Moves => CurrentPet.Value.Moves; + + public ObservableCollection Pets => ModInfoModel.Current.Pets; + public ObservableValue CurrentPet { get; } = new(new()); + public ObservableValue Filter { get; } = new(); + #endregion + #region Command + public ObservableCommand AddCommand { get; } = new(); + public ObservableCommand EditCommand { get; } = new(); + public ObservableCommand RemoveCommand { get; } = new(); + #endregion + public MovePageVM() + { + ShowMoves.Value = Moves; + CurrentPet.ValueChanged += CurrentPet_ValueChanged; + Filter.ValueChanged += Filter_ValueChanged; + + AddCommand.ExecuteEvent += Add; + EditCommand.ExecuteEvent += Edit; + RemoveCommand.ExecuteEvent += Remove; + } + + private void CurrentPet_ValueChanged(PetModel oldValue, PetModel newValue) + { + ShowMoves.Value = newValue.Moves; + } + + private void Filter_ValueChanged(string oldValue, string newValue) + { + //if (string.IsNullOrWhiteSpace(newValue)) + //{ + // ShowMoves.EnumValue = Moves; + //} + //else + //{ + // ShowMoves.EnumValue = new( + // Moves.Where(m => m.Id.EnumValue.Contains(newValue, StringComparison.OrdinalIgnoreCase)) + // ); + //} + } + + public void Close() { } + + private void Add() + { + var window = new MoveEditWindow(); + var vm = window.ViewModel; + vm.CurrentPet = CurrentPet.Value; + window.ShowDialog(); + if (window.IsCancel) + return; + Moves.Add(vm.Move.Value); + } + + public void Edit(MoveModel model) + { + var window = new MoveEditWindow(); + var vm = window.ViewModel; + vm.CurrentPet = CurrentPet.Value; + vm.OldMove = model; + var newMove = vm.Move.Value = new(model); + window.ShowDialog(); + if (window.IsCancel) + return; + if (ShowMoves.Value.Count == Moves.Count) + { + Moves[Moves.IndexOf(model)] = newMove; + } + else + { + Moves[Moves.IndexOf(model)] = newMove; + ShowMoves.Value[ShowMoves.Value.IndexOf(model)] = newMove; + } + } + + private void Remove(MoveModel food) + { + if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No) + return; + if (ShowMoves.Value.Count == Moves.Count) + { + Moves.Remove(food); + } + else + { + ShowMoves.Value.Remove(food); + Moves.Remove(food); + } + } +} diff --git a/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs index b0a0089..6a0d616 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs @@ -33,7 +33,7 @@ public class PetEditWindowVM private void Image_ValueChanged(BitmapImage oldValue, BitmapImage newValue) { - //LengthRatio.Value = BorderLength.Value / value.PixelWidth; + //LengthRatio.EnumValue = BorderLength.EnumValue / value.PixelWidth; } public void Close() diff --git a/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs index 137105a..e4cae5c 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs @@ -34,7 +34,7 @@ public class WorkEditWindowVM private void Image_ValueChanged(BitmapImage oldValue, BitmapImage newValue) { - //LengthRatio.Value = BorderLength.Value / value.PixelWidth; + //LengthRatio.EnumValue = BorderLength.EnumValue / value.PixelWidth; } public void Close() diff --git a/VPet.ModMaker/Views/ModEdit/FoodEdit/FoodEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/FoodEdit/FoodEditWindow.xaml index e8d23cb..d66c1b3 100644 --- a/VPet.ModMaker/Views/ModEdit/FoodEdit/FoodEditWindow.xaml +++ b/VPet.ModMaker/Views/ModEdit/FoodEdit/FoodEditWindow.xaml @@ -97,6 +97,7 @@ Grid.Row="4" Grid.Column="1" pu:TextBoxHelper.Watermark="{ll:Str 食物描述}" + Style="{StaticResource TextBox_Wrap}" Text="{Binding Food.Value.CurrentI18nData.Value.Description.Value, UpdateSourceTrigger=PropertyChanged}" /> diff --git a/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml index 686f235..bbe62c0 100644 --- a/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml +++ b/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml @@ -98,14 +98,14 @@ + -