diff --git a/VPet.ModMaker/Converters.xaml b/VPet.ModMaker/Converters.xaml index 48c470e..0384cf3 100644 --- a/VPet.ModMaker/Converters.xaml +++ b/VPet.ModMaker/Converters.xaml @@ -9,4 +9,6 @@ + + \ No newline at end of file diff --git a/VPet.ModMaker/Converters/EqualsConverter.cs b/VPet.ModMaker/Converters/EqualsConverter.cs new file mode 100644 index 0000000..ba3939f --- /dev/null +++ b/VPet.ModMaker/Converters/EqualsConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Windows.Data; + +namespace VPet.ModMaker.Converters; + +public class EqualsConverter : IMultiValueConverter +{ + public object Convert( + object[] values, + Type targetType, + object parameter, + System.Globalization.CultureInfo culture + ) + { + if (values.Length != 2) + throw new NotImplementedException("Values length must be 2"); + return values[0].Equals(values[1]); + } + + public object[] ConvertBack( + object value, + Type[] targetTypes, + object parameter, + System.Globalization.CultureInfo culture + ) + { + throw new NotImplementedException(); + } +} diff --git a/VPet.ModMaker/Converters/FalseToCollapsedConverter.cs b/VPet.ModMaker/Converters/FalseToCollapsedConverter.cs new file mode 100644 index 0000000..bc358e1 --- /dev/null +++ b/VPet.ModMaker/Converters/FalseToCollapsedConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace VPet.ModMaker.Converters; + +public class FalseToCollapsedConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool.TryParse(value.ToString(), out var result) && result) + ? Visibility.Visible + : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value is Visibility visibility && visibility == Visibility.Collapsed; + } +} \ No newline at end of file diff --git a/VPet.ModMaker/Converters/NotEqualsConverter.cs b/VPet.ModMaker/Converters/NotEqualsConverter.cs new file mode 100644 index 0000000..d2242aa --- /dev/null +++ b/VPet.ModMaker/Converters/NotEqualsConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Windows.Data; + +namespace VPet.ModMaker.Converters; + +public class NotEqualsConverter : IMultiValueConverter +{ + public object Convert( + object[] values, + Type targetType, + object parameter, + System.Globalization.CultureInfo culture + ) + { + if (values.Length != 2) + throw new NotImplementedException("Values length must be 2"); + return !values[0].Equals(values[1]); + } + + public object[] ConvertBack( + object value, + Type[] targetTypes, + object parameter, + System.Globalization.CultureInfo culture + ) + { + throw new NotImplementedException(); + } +} diff --git a/VPet.ModMaker/Models/ModModel/FoodLocationModel.cs b/VPet.ModMaker/Models/ModModel/FoodLocationModel.cs index c307681..e491f4e 100644 --- a/VPet.ModMaker/Models/ModModel/FoodLocationModel.cs +++ b/VPet.ModMaker/Models/ModModel/FoodLocationModel.cs @@ -18,7 +18,7 @@ public class FoodLocationModel public ObservableValue Duration { get; } = new(100); /// - /// 定位 + /// 范围 /// public ObservableRect Rect { get; } = new(); diff --git a/VPet.ModMaker/VPet.ModMaker.csproj b/VPet.ModMaker/VPet.ModMaker.csproj index 6ead5ed..6d8bfad 100644 --- a/VPet.ModMaker/VPet.ModMaker.csproj +++ b/VPet.ModMaker/VPet.ModMaker.csproj @@ -93,8 +93,11 @@ + + + diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs index b96a6b4..ecfe136 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs @@ -3,6 +3,7 @@ using LinePutScript.Localization.WPF; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -19,13 +20,23 @@ public class AnimePageVM /// /// 显示的动画 /// - public ObservableValue> ShowAnimes { get; } = new(); + public ObservableValue> ShowAnimes { get; } = new(); + + /// + /// 所有动画 + /// + public ObservableCollection AllAnimes { get; } = new(); /// /// 动画 /// public ObservableCollection Animes => CurrentPet.Value.Animes; + /// + /// 食物动画 + /// + public ObservableCollection FoodAnimes => CurrentPet.Value.FoodAnimes; + /// /// 宠物列表 /// @@ -59,7 +70,7 @@ public class AnimePageVM #endregion public AnimePageVM() { - ShowAnimes.Value = Animes; + ShowAnimes.Value = AllAnimes; CurrentPet.ValueChanged += CurrentPet_ValueChanged; Search.ValueChanged += Search_ValueChanged; @@ -68,21 +79,57 @@ public class AnimePageVM RemoveCommand.ExecuteEvent += Remove; } + private void InitializeAllAnimes() + { + AllAnimes.Clear(); + foreach (var item in Animes) + AllAnimes.Add(item); + foreach (var item in FoodAnimes) + AllAnimes.Add(item); + Animes.CollectionChanged += Animes_CollectionChanged; + FoodAnimes.CollectionChanged += Animes_CollectionChanged; + } + + private void Animes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action is NotifyCollectionChangedAction.Add) + AllAnimes.Add(e.NewItems[0]); + else if (e.Action is NotifyCollectionChangedAction.Remove) + AllAnimes.Remove(e.OldItems[0]); + else if (e.Action is NotifyCollectionChangedAction.Replace) + AllAnimes[AllAnimes.IndexOf(e.OldItems[0])] = e.NewItems[0]; + } + private void CurrentPet_ValueChanged(PetModel oldValue, PetModel newValue) { - ShowAnimes.Value = newValue.Animes; + InitializeAllAnimes(); + ShowAnimes.Value = AllAnimes; } private void Search_ValueChanged(string oldValue, string newValue) { if (string.IsNullOrWhiteSpace(newValue)) { - ShowAnimes.Value = Animes; + ShowAnimes.Value = AllAnimes; } else { ShowAnimes.Value = new( - Animes.Where(m => m.Id.Value.Contains(newValue, StringComparison.OrdinalIgnoreCase)) + AllAnimes.Where(m => + { + if (m is AnimeTypeModel animeTypeModel) + return animeTypeModel.Id.Value.Contains( + newValue, + StringComparison.OrdinalIgnoreCase + ); + else if (m is FoodAnimeTypeModel foodAnimeTypeModel) + return foodAnimeTypeModel.Id.Value.Contains( + newValue, + StringComparison.OrdinalIgnoreCase + ); + else + throw new Exception("???"); + }) ); } } @@ -98,6 +145,7 @@ public class AnimePageVM var graphType = selectGraphTypeWindow.GraphType.Value; if (selectGraphTypeWindow.IsCancel) return; + // TODO: FoodAnime var window = new AnimeEditWindow(); var vm = window.ViewModel; vm.CurrentPet = CurrentPet.Value; @@ -115,6 +163,7 @@ public class AnimePageVM /// 动画类型模型 public void Edit(AnimeTypeModel model) { + // TODO: FoodAnime var window = new AnimeEditWindow(); var vm = window.ViewModel; vm.CurrentPet = CurrentPet.Value; @@ -142,14 +191,14 @@ public class AnimePageVM { if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No) return; - if (ShowAnimes.Value.Count == Animes.Count) + if (ShowAnimes.Value.Count == AllAnimes.Count) { - Animes.Remove(model); + AllAnimes.Remove(model); } else { ShowAnimes.Value.Remove(model); - Animes.Remove(model); + AllAnimes.Remove(model); } } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs index 9371f88..0631693 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs @@ -24,6 +24,11 @@ public class FoodAnimeEditWindowVM /// public PetModel CurrentPet { get; set; } + /// + /// 默认食物图片 + /// + public static BitmapImage DefaultFoodImage { get; } = Utils.LoadImageToMemoryStream(""); + /// /// 食物图片 /// @@ -114,6 +119,16 @@ public class FoodAnimeEditWindowVM /// 删除图片命令 /// public ObservableCommand RemoveImageCommand { get; } = new(); + + /// + /// 改变食物图片 + /// + public ObservableCommand ReplaceFoodImageCommand { get; } = new(); + + /// + /// 重置食物图片 + /// + public ObservableCommand ResetFoodImageCommand { get; } = new(); #endregion /// @@ -150,10 +165,31 @@ public class FoodAnimeEditWindowVM ClearImageCommand.ExecuteEvent += ClearImageCommand_ExecuteEvent; RemoveAnimeCommand.ExecuteEvent += RemoveAnimeCommand_ExecuteEvent; RemoveImageCommand.ExecuteEvent += RemoveImageCommand_ExecuteEvent; + ReplaceFoodImageCommand.ExecuteEvent += ReplaceFoodImageCommand_ExecuteEvent; + ResetFoodImageCommand.ExecuteEvent += ResetFoodImageCommand_ExecuteEvent; Anime.ValueChanged += Anime_ValueChanged; } + private void ResetFoodImageCommand_ExecuteEvent() + { + if (FoodImage.Value != DefaultFoodImage) + FoodImage.Value.CloseStream(); + FoodImage.Value = DefaultFoodImage; + } + + private void ReplaceFoodImageCommand_ExecuteEvent() + { + OpenFileDialog openFileDialog = + new() { Title = "选择食物图片".Translate(), Filter = $"图片|*.png".Translate() }; + if (openFileDialog.ShowDialog() is true) + { + if (FoodImage.Value != DefaultFoodImage) + FoodImage.Value.CloseStream(); + FoodImage.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); + } + } + #region LoadAnime private void Anime_ValueChanged(FoodAnimeTypeModel oldValue, FoodAnimeTypeModel newValue) { diff --git a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml index 8d14c0a..110c3fa 100644 --- a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml +++ b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml @@ -21,7 +21,7 @@ - + - + @@ -57,16 +60,8 @@ - - + + @@ -81,16 +76,16 @@ - @@ -103,6 +98,7 @@ @@ -130,7 +126,7 @@ - @@ -140,16 +136,16 @@ - @@ -162,6 +158,7 @@ @@ -189,7 +186,7 @@ - - + + + + + + + + + + + + + + + + + + + + + + @@ -219,8 +290,15 @@ - - + + + + + + + + + {