diff --git a/VPet.ModMaker/Converters/CalculatorConverter.cs b/VPet.ModMaker/Converters/CalculatorConverter.cs
index c87c747..188accd 100644
--- a/VPet.ModMaker/Converters/CalculatorConverter.cs
+++ b/VPet.ModMaker/Converters/CalculatorConverter.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
@@ -38,6 +39,8 @@ public class CalculatorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
+ if (values.Any(i => i == DependencyProperty.UnsetValue))
+ return 0;
if (values.Length == 1)
return values[0];
double result = System.Convert.ToDouble(values[0]);
diff --git a/VPet.ModMaker/Converters/RatioMarginConverter.cs b/VPet.ModMaker/Converters/RatioMarginConverter.cs
index db26979..2380d12 100644
--- a/VPet.ModMaker/Converters/RatioMarginConverter.cs
+++ b/VPet.ModMaker/Converters/RatioMarginConverter.cs
@@ -29,6 +29,8 @@ public class RatioMarginConverter : IMultiValueConverter
System.Globalization.CultureInfo culture
)
{
+ if (values.Any(i => i == DependencyProperty.UnsetValue))
+ return new Thickness();
if (values.Length == 0)
{
return new Thickness();
diff --git a/VPet.ModMaker/Models/ModModel/AnimeTypeModel.cs b/VPet.ModMaker/Models/ModModel/AnimeTypeModel.cs
index 3ccbc2e..025d4e9 100644
--- a/VPet.ModMaker/Models/ModModel/AnimeTypeModel.cs
+++ b/VPet.ModMaker/Models/ModModel/AnimeTypeModel.cs
@@ -142,6 +142,26 @@ public class AnimeTypeModel
}
}
+ public void Close()
+ {
+ foreach (var anime in HappyAnimes)
+ anime.Close();
+ foreach (var anime in NomalAnimes)
+ anime.Close();
+ foreach (var anime in PoorConditionAnimes)
+ anime.Close();
+ foreach (var anime in IllAnimes)
+ anime.Close();
+ }
+
+ public void Clear()
+ {
+ HappyAnimes.Clear();
+ NomalAnimes.Clear();
+ PoorConditionAnimes.Clear();
+ IllAnimes.Clear();
+ }
+
public AnimeTypeModel(GraphInfo.GraphType graphType, string path)
{
Name.Value = Path.GetFileName(path);
diff --git a/VPet.ModMaker/Models/ModModel/FoodAnimeModel.cs b/VPet.ModMaker/Models/ModModel/FoodAnimeModel.cs
index 4514fa5..6d6d2b8 100644
--- a/VPet.ModMaker/Models/ModModel/FoodAnimeModel.cs
+++ b/VPet.ModMaker/Models/ModModel/FoodAnimeModel.cs
@@ -57,9 +57,9 @@ public class FoodAnimeModel
double.Parse(infos[3])
);
}
- if (infos.Length > 3)
- foodLocationInfo.Rotate.Value = double.Parse(infos[4]);
if (infos.Length > 4)
+ foodLocationInfo.Rotate.Value = double.Parse(infos[4]);
+ if (infos.Length > 5)
foodLocationInfo.Opacity.Value = double.Parse(infos[5]);
FoodLocations.Add(foodLocationInfo);
}
diff --git a/VPet.ModMaker/Models/ModModel/FoodAnimeTypeModel.cs b/VPet.ModMaker/Models/ModModel/FoodAnimeTypeModel.cs
index 1296a74..c06f2f4 100644
--- a/VPet.ModMaker/Models/ModModel/FoodAnimeTypeModel.cs
+++ b/VPet.ModMaker/Models/ModModel/FoodAnimeTypeModel.cs
@@ -15,6 +15,17 @@ namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeTypeModel
{
+ ///
+ /// 动作类型
+ ///
+ public static GraphInfo.GraphType GraphType => GraphInfo.GraphType.Common;
+
+ ///
+ /// 动画名称
+ ///
+ public static HashSet FoodAnimeNames =
+ new(StringComparer.InvariantCultureIgnoreCase) { "Eat", "Drink", "Gift", };
+
///
/// Id
///
@@ -25,11 +36,6 @@ public class FoodAnimeTypeModel
///
public ObservableValue Name { get; } = new();
- ///
- /// 动作类型
- ///
- public GraphInfo.GraphType GraphType => GraphInfo.GraphType.Common;
-
///
/// 开心动画
///
@@ -53,10 +59,30 @@ public class FoodAnimeTypeModel
public FoodAnimeTypeModel()
{
HappyAnimes.CollectionChanged += Animes_CollectionChanged;
- //Name.ValueChanged += (_, _) =>
- //{
- // Id.Value = $"{GraphType.Value}_{Name.Value}";
- //};
+ Name.ValueChanged += (_, _) =>
+ {
+ Id.Value = $"{GraphType}_{Name.Value}";
+ };
+ }
+
+ public void Close()
+ {
+ foreach (var anime in HappyAnimes)
+ anime.Close();
+ foreach (var anime in NomalAnimes)
+ anime.Close();
+ foreach (var anime in PoorConditionAnimes)
+ anime.Close();
+ foreach (var anime in IllAnimes)
+ anime.Close();
+ }
+
+ public void Clear()
+ {
+ HappyAnimes.Clear();
+ NomalAnimes.Clear();
+ PoorConditionAnimes.Clear();
+ IllAnimes.Clear();
}
private void Animes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -157,16 +183,16 @@ public class FoodAnimeTypeModel
public void ParseInfoFile(string path, string infoPath)
{
- var lps = new LPS(infoPath);
- var foodAnimeInfos = lps.FindAllLineInfo(nameof(FoodAnimation));
+ var lps = new LPS(File.ReadAllText(infoPath));
+ var foodAnimeInfos = lps.FindAllLine(nameof(FoodAnimation));
if (foodAnimeInfos.Any() is false)
throw new Exception("信息文件\n{0}\n未包含食物动画信息".Translate(infoPath));
- var pngAnimeInfos = lps.FindAllLineInfo(nameof(PNGAnimation))
+ var pngAnimeInfos = lps.FindAllLine(nameof(PNGAnimation))
.Select(
i =>
new PNGAnimeInfo(
i.Info,
- i.Find("infoPath").Info,
+ i.Find("path").Info,
(GameSave.ModeType)
Enum.Parse(typeof(GameSave.ModeType), i.Find("mode").Info, true)
)
@@ -246,7 +272,7 @@ public class FoodAnimeTypeModel
i =>
new ImageModel(
Utils.LoadImageToMemoryStream(i),
- int.Parse(Path.GetFileNameWithoutExtension(i).Split('_')[1])
+ int.Parse(Path.GetFileNameWithoutExtension(i).Split('_')[2])
)
)
);
diff --git a/VPet.ModMaker/Models/ModModel/ImageModel.cs b/VPet.ModMaker/Models/ModModel/ImageModel.cs
index 1dd8d64..d44a9de 100644
--- a/VPet.ModMaker/Models/ModModel/ImageModel.cs
+++ b/VPet.ModMaker/Models/ModModel/ImageModel.cs
@@ -31,7 +31,7 @@ public class ImageModel
public ImageModel Copy()
{
- var model = new ImageModel(Image.Value, Duration.Value);
+ var model = new ImageModel(Image.Value.Copy(), Duration.Value);
return model;
}
diff --git a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
index 937b491..79f5644 100644
--- a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
+++ b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
@@ -236,6 +236,11 @@ public class ModInfoModel : I18nModel
)
petModel.Animes.Add(model1);
}
+ else if (FoodAnimeTypeModel.FoodAnimeNames.Contains(dirName))
+ {
+ //if (FoodAnimeTypeModel.Create(animeDir) is FoodAnimeTypeModel model1)
+ // petModel.FoodAnimes.Add(model1);
+ }
}
}
diff --git a/VPet.ModMaker/Models/Utils.cs b/VPet.ModMaker/Models/Utils.cs
index b84cea2..9f671de 100644
--- a/VPet.ModMaker/Models/Utils.cs
+++ b/VPet.ModMaker/Models/Utils.cs
@@ -50,7 +50,6 @@ public static class Utils
{
BitmapImage bitmapImage = new();
bitmapImage.BeginInit();
- bitmapImage.DecodePixelWidth = DecodePixelWidth;
try
{
var ms = new MemoryStream();
@@ -62,6 +61,8 @@ public static class Utils
{
bitmapImage.EndInit();
}
+ if (bitmapImage.PixelWidth > DecodePixelWidth)
+ bitmapImage.DecodePixelWidth = DecodePixelWidth;
return bitmapImage;
}
}
diff --git a/VPet.ModMaker/SimpleObservable/ObservableCommand.cs b/VPet.ModMaker/SimpleObservable/ObservableCommand.cs
index 672de43..0239400 100644
--- a/VPet.ModMaker/SimpleObservable/ObservableCommand.cs
+++ b/VPet.ModMaker/SimpleObservable/ObservableCommand.cs
@@ -13,7 +13,7 @@ namespace HKW.HKWViewModels.SimpleObservable;
/// 可观察命令
///
[DebuggerDisplay(
- "CanExecute = {CanExecuteProperty.EnumValue}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}"
+ "CanExecute = {CanExecuteProperty.Value}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}"
)]
public class ObservableCommand : ICommand
{
@@ -23,16 +23,23 @@ public class ObservableCommand : ICommand
public ObservableValue CanExecuteProperty { get; } = new(true);
///
- /// 等待异步执行完成
+ /// 当前可执行状态
///
- [DebuggerBrowsable(DebuggerBrowsableState.Never)]
- private readonly ObservableValue r_waiting = new(false);
+ public ObservableValue CurrentCanExecute { get; } = new(true);
///
public ObservableCommand()
{
CanExecuteProperty.PropertyChanged += InvokeCanExecuteChanged;
- r_waiting.PropertyChanged += InvokeCanExecuteChanged;
+ CurrentCanExecute.PropertyChanged += InvokeCanExecuteChanged;
+ CurrentCanExecute.ValueChanging += CurrentCanExecute_ValueChanging;
+ }
+
+ private bool CurrentCanExecute_ValueChanging(bool oldValue, bool newValue)
+ {
+ if (newValue is true && CanExecuteProperty.Value is false)
+ return true;
+ return false;
}
private void InvokeCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
@@ -48,9 +55,7 @@ public class ObservableCommand : ICommand
/// 能被执行为 否则为
public bool CanExecute(object? parameter)
{
- if (r_waiting.Value is true)
- return false;
- return CanExecuteProperty.Value;
+ return CurrentCanExecute.Value && CanExecuteProperty.Value;
}
///
@@ -71,12 +76,12 @@ public class ObservableCommand : ICommand
{
if (AsyncExecuteEvent is null)
return;
- r_waiting.Value = true;
+ CurrentCanExecute.Value = false;
foreach (
var asyncEvent in AsyncExecuteEvent.GetInvocationList().Cast()
)
await asyncEvent.Invoke();
- r_waiting.Value = false;
+ CurrentCanExecute.Value = true;
}
#endregion
diff --git a/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs b/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs
index a9e2706..99837b9 100644
--- a/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs
+++ b/VPet.ModMaker/SimpleObservable/ObservableCommandT.cs
@@ -14,7 +14,7 @@ namespace HKW.HKWViewModels.SimpleObservable;
///
/// 参数类型
[DebuggerDisplay(
- "CanExecute = {CanExecuteProperty.EnumValue}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}"
+ "CanExecute = {CanExecuteProperty.Value}, EventCount = {ExecuteEvent.GetInvocationList().Length}, AsyncEventCount = {AsyncExecuteEvent.GetInvocationList().Length}"
)]
public class ObservableCommand : ICommand
where T : notnull
@@ -22,15 +22,24 @@ public class ObservableCommand : ICommand
///
public ObservableValue CanExecuteProperty { get; } = new(true);
- ///
- [DebuggerBrowsable(DebuggerBrowsableState.Never)]
- private readonly ObservableValue r_waiting = new(false);
+ ///
+ /// 当前可执行状态
+ ///
+ public ObservableValue CurrentCanExecute { get; } = new(true);
- ///
+ ///
public ObservableCommand()
{
CanExecuteProperty.PropertyChanged += InvokeCanExecuteChanged;
- r_waiting.PropertyChanged += InvokeCanExecuteChanged;
+ CurrentCanExecute.PropertyChanged += InvokeCanExecuteChanged;
+ CurrentCanExecute.ValueChanging += CurrentCanExecute_ValueChanging;
+ }
+
+ private bool CurrentCanExecute_ValueChanging(bool oldValue, bool newValue)
+ {
+ if (newValue is true && CanExecuteProperty.Value is false)
+ return true;
+ return false;
}
private void InvokeCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
@@ -42,9 +51,7 @@ public class ObservableCommand : ICommand
///
public bool CanExecute(object? parameter)
{
- if (r_waiting.Value is true)
- return false;
- return CanExecuteProperty.Value;
+ return CurrentCanExecute.Value && CanExecuteProperty.Value;
}
///
@@ -60,12 +67,12 @@ public class ObservableCommand : ICommand
{
if (AsyncExecuteEvent is null)
return;
- r_waiting.Value = true;
+ CurrentCanExecute.Value = false;
foreach (
var asyncEvent in AsyncExecuteEvent.GetInvocationList().Cast()
)
await asyncEvent.Invoke(parameter);
- r_waiting.Value = false;
+ CurrentCanExecute.Value = true;
}
#endregion
diff --git a/VPet.ModMaker/SimpleObservable/ObservableValue.cs b/VPet.ModMaker/SimpleObservable/ObservableValue.cs
index 6fb88f7..21f6807 100644
--- a/VPet.ModMaker/SimpleObservable/ObservableValue.cs
+++ b/VPet.ModMaker/SimpleObservable/ObservableValue.cs
@@ -28,9 +28,11 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange
{
if (_value?.Equals(value) is true)
return;
- NotifyPropertyChanging(_value, value);
+ var oldValue = _value;
+ if (NotifyPropertyChanging(oldValue, value))
+ return;
_value = value;
- NotifyPropertyChanged(_value, value);
+ NotifyPropertyChanged(oldValue, value);
}
}
@@ -57,10 +59,15 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange
///
/// 旧值
/// 新值
- private void NotifyPropertyChanging(T oldValue, T newValue)
+ private bool NotifyPropertyChanging(T oldValue, T newValue)
{
PropertyChanging?.Invoke(this, new(nameof(Value)));
- ValueChanging?.Invoke(oldValue, newValue);
+ // 若全部事件取消改变 则取消改变
+ return ValueChanging
+ ?.GetInvocationList()
+ .Cast()
+ .All(e => e.Invoke(oldValue, newValue) is true)
+ is true;
}
///
@@ -98,8 +105,8 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange
/// {
/// v = "B"; // trigger this
/// };
- /// value1.EnumValue = "A"; // execute this
- /// // result: value1.EnumValue == "A" , value2.EnumValue == "B"
+ /// value1.Value = "A"; // execute this
+ /// // result: value1.Value == "A" , value2.Value == "B"
/// ]]>
///
///
@@ -142,12 +149,12 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange
///
/// 值改变前事件
///
- public event ValueChangeEventHandler? ValueChanging;
+ public event ValueChangingEventHandler? ValueChanging;
///
/// 值改变后事件
///
- public event ValueChangeEventHandler? ValueChanged;
+ public event ValueChangedEventHandler? ValueChanged;
///
/// 通知接收器事件
@@ -161,7 +168,15 @@ public class ObservableValue : INotifyPropertyChanging, INotifyPropertyChange
///
/// 旧值
/// 新值
- public delegate void ValueChangeEventHandler(T oldValue, T newValue);
+ /// 取消改变
+ public delegate bool ValueChangingEventHandler(T oldValue, T newValue);
+
+ ///
+ /// 值改变后事件
+ ///
+ /// 旧值
+ /// 新值
+ public delegate void ValueChangedEventHandler(T oldValue, T newValue);
///
/// 通知接收器
diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
index 0905bd3..52491b5 100644
--- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
+++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
@@ -3,12 +3,14 @@ using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Media.Imaging;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
@@ -74,24 +76,34 @@ public class AnimeEditWindowVM
public ObservableCommand StopCommand { get; } = new();
///
- /// 添加图片命令
+ /// 添加动画命令
///
- public ObservableCommand AddImageCommand { get; } = new();
-
- ///
- /// 清除图片命令
- ///
- public ObservableCommand ClearImageCommand { get; } = new();
+ public ObservableCommand AddAnimeCommand { get; } = new();
///
/// 删除动画命令
///
public ObservableCommand RemoveAnimeCommand { get; } = new();
+ ///
+ /// 添加图片命令
+ ///
+ public ObservableCommand AddImageCommand { get; } = new();
+
///
/// 删除图片命令
///
public ObservableCommand RemoveImageCommand { get; } = new();
+
+ ///
+ /// 替换图片命令
+ ///
+ public ObservableCommand ChangeImageCommand { get; } = new();
+
+ ///
+ /// 清除图片命令
+ ///
+ public ObservableCommand ClearImageCommand { get; } = new();
#endregion
///
@@ -110,12 +122,14 @@ public class AnimeEditWindowVM
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
- PlayCommand.ExecuteEvent += PlayCommand_ExecuteEvent;
+ PlayCommand.AsyncExecuteEvent += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteEvent += StopCommand_ExecuteEvent;
- AddImageCommand.ExecuteEvent += AddImageCommand_ExecuteEvent;
- ClearImageCommand.ExecuteEvent += ClearImageCommand_ExecuteEvent;
+ AddAnimeCommand.ExecuteEvent += AddAnimeCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteEvent += RemoveAnimeCommand_ExecuteEvent;
+ AddImageCommand.ExecuteEvent += AddImageCommand_ExecuteEvent;
RemoveImageCommand.ExecuteEvent += RemoveImageCommand_ExecuteEvent;
+ ChangeImageCommand.ExecuteEvent += ChangeImageCommand_ExecuteEvent;
+ ClearImageCommand.ExecuteEvent += ClearImageCommand_ExecuteEvent;
Anime.ValueChanged += Anime_ValueChanged;
}
@@ -135,6 +149,24 @@ public class AnimeEditWindowVM
HasAnimeName.Value = true;
}
#endregion
+
+ #region AnimeCommand
+ ///
+ /// 添加动画
+ ///
+ /// 动画模型
+ private void AddAnimeCommand_ExecuteEvent()
+ {
+ if (CurrentMode is GameSave.ModeType.Happy)
+ Anime.Value.HappyAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.Nomal)
+ Anime.Value.NomalAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.PoorCondition)
+ Anime.Value.PoorConditionAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.Ill)
+ Anime.Value.IllAnimes.Add(new());
+ }
+
///
/// 删除动画
///
@@ -157,6 +189,64 @@ public class AnimeEditWindowVM
value.Close();
}
}
+ #endregion
+
+ #region ImageCommand
+
+ ///
+ /// 添加图片
+ ///
+ /// 动画模型
+ private void AddImageCommand_ExecuteEvent(AnimeModel value)
+ {
+ OpenFileDialog openFileDialog =
+ new()
+ {
+ Title = "选择图片".Translate(),
+ Filter = $"图片|*.png".Translate(),
+ Multiselect = true
+ };
+ if (openFileDialog.ShowDialog() is not true)
+ return;
+ AddImages(value.Images, openFileDialog.FileNames);
+ }
+
+ ///
+ /// 删除图片
+ ///
+ /// 动画模型
+ private void RemoveImageCommand_ExecuteEvent(AnimeModel value)
+ {
+ value.Images.Remove(CurrentImageModel.Value);
+ CurrentImageModel.Value.Close();
+ }
+
+ ///
+ /// 替换图片
+ ///
+ ///
+ ///
+ private void ChangeImageCommand_ExecuteEvent(AnimeModel value)
+ {
+ OpenFileDialog openFileDialog =
+ new() { Title = "选择图片".Translate(), Filter = $"图片|*.png".Translate() };
+ if (openFileDialog.ShowDialog() is not true)
+ return;
+ BitmapImage newImage;
+ try
+ {
+ newImage = Utils.LoadImageToMemoryStream(openFileDialog.FileName);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("替换失败失败 \n{0}".Translate(ex));
+ return;
+ }
+ if (newImage is null)
+ return;
+ CurrentImageModel.Value.Close();
+ CurrentImageModel.Value.Image.Value = newImage;
+ }
///
/// 清空图片
@@ -176,57 +266,36 @@ public class AnimeEditWindowVM
///
/// 添加图片
///
- /// 动画模型
- private void AddImageCommand_ExecuteEvent(AnimeModel value)
- {
- OpenFileDialog openFileDialog =
- new() { Title = "选择图片".Translate(), Filter = $"图片|*.png".Translate() };
- if (openFileDialog.ShowDialog() is true)
- {
- value.Images.Add(new(Utils.LoadImageToMemoryStream(openFileDialog.FileName)));
- }
- }
-
- ///
- /// 添加图片
- ///
- /// 动画模型
+ /// 动画
/// 路径
- public void AddImages(AnimeModel model, IEnumerable paths)
+ public void AddImages(ObservableCollection images, IEnumerable paths)
{
try
{
+ var newImages = new List();
foreach (string path in paths)
{
if (File.Exists(path))
{
- model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
+ newImages.Add(new(Utils.LoadImageToMemoryStream(path)));
}
else if (Directory.Exists(path))
{
foreach (var file in Directory.EnumerateFiles(path, "*.png"))
{
- model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
+ newImages.Add(new(Utils.LoadImageToMemoryStream(path)));
}
}
}
+ foreach (var image in newImages)
+ images.Add(image);
}
catch (Exception ex)
{
MessageBox.Show("添加失败 \n{0}".Translate(ex));
}
}
-
- ///
- /// 删除图片
- ///
- /// 动画模型
- private void RemoveImageCommand_ExecuteEvent(AnimeModel value)
- {
- CurrentImageModel.Value.Close();
- value.Images.Remove(CurrentImageModel.Value);
- }
-
+ #endregion
#region Player
private void CurrentAnimeModel_ValueChanged(AnimeModel oldValue, AnimeModel newValue)
{
@@ -249,19 +318,13 @@ public class AnimeEditWindowVM
{
if (_playing is false)
return;
- Reset();
}
///
/// 开始播放
///
- private void PlayCommand_ExecuteEvent()
+ private async Task PlayCommand_AsyncExecuteEvent()
{
- if (_playing)
- {
- MessageBox.Show("正在播放".Translate());
- return;
- }
if (CurrentAnimeModel.Value is null)
{
MessageBox.Show("未选中动画".Translate());
@@ -269,6 +332,8 @@ public class AnimeEditWindowVM
}
_playing = true;
_playerTask.Start();
+ await Task.WhenAll(_playerTask);
+ Reset();
}
///
diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs
index ecfe136..86cf870 100644
--- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs
+++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimePageVM.cs
@@ -61,12 +61,12 @@ public class AnimePageVM
///
/// 编辑命令
///
- public ObservableCommand EditCommand { get; } = new();
+ public ObservableCommand
/// 动画类型模型
- private void Remove(AnimeTypeModel model)
+ private void Remove(object model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
- if (ShowAnimes.Value.Count == AllAnimes.Count)
+ ShowAnimes.Value.Remove(model);
+ if (model is AnimeTypeModel animeTypeModel)
{
- AllAnimes.Remove(model);
+ Animes.Remove(animeTypeModel);
+ animeTypeModel.Close();
}
- else
+ else if (model is FoodAnimeTypeModel foodAnimeTypeModel)
{
- ShowAnimes.Value.Remove(model);
- AllAnimes.Remove(model);
+ FoodAnimes.Remove(foodAnimeTypeModel);
+ foodAnimeTypeModel.Close();
}
}
}
diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs
index 0631693..21b12ad 100644
--- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs
+++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/FoodAnimeEditWindowVM.cs
@@ -3,11 +3,9 @@ using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
@@ -27,12 +25,15 @@ public class FoodAnimeEditWindowVM
///
/// 默认食物图片
///
- public static BitmapImage DefaultFoodImage { get; } = Utils.LoadImageToMemoryStream("");
+ public static BitmapImage DefaultFoodImage { get; } =
+ Utils.LoadImageToMemoryStream(
+ "C:\\Users\\HKW\\Desktop\\TestPicture\\0000_core\\image\\food.png"
+ );
///
/// 食物图片
///
- public ObservableValue FoodImage { get; } = new();
+ public ObservableValue FoodImage { get; } = new(DefaultFoodImage);
///
/// 比例
@@ -101,25 +102,64 @@ public class FoodAnimeEditWindowVM
public ObservableCommand StopCommand { get; } = new();
///
- /// 添加图片命令
+ /// 添加动画命令
///
- public ObservableCommand AddImageCommand { get; } = new();
-
- ///
- /// 清除图片命令
- ///
- public ObservableCommand ClearImageCommand { get; } = new();
+ public ObservableCommand AddAnimeCommand { get; } = new();
///
/// 删除动画命令
///
- public ObservableCommand RemoveAnimeCommand { get; } = new();
+ public ObservableCommand RemoveAnimeCommand { get; } = new();
+
+ #region FrontImage
+ ///
+ /// 添加顶层图片命令
+ ///
+ public ObservableCommand AddFrontImageCommand { get; } = new();
///
- /// 删除图片命令
+ /// 删除顶层图片命令
///
- public ObservableCommand RemoveImageCommand { get; } = new();
+ public ObservableCommand RemoveFrontImageCommand { get; } = new();
+ ///
+ /// 清除顶层图片命令
+ ///
+ public ObservableCommand ClearFrontImageCommand { get; } = new();
+ #endregion
+
+ #region BackImage
+ ///
+ /// 添加底层图片命令
+ ///
+ public ObservableCommand AddBackImageCommand { get; } = new();
+
+ ///
+ /// 删除底层图片命令
+ ///
+ public ObservableCommand RemoveBackImageCommand { get; } = new();
+
+ ///
+ /// 清除底层图片命令
+ ///
+ public ObservableCommand ClearBackImageCommand { get; } = new();
+ #endregion
+ #region FoodLocation
+ ///
+ /// 添加食物定位命令
+ ///
+ public ObservableCommand AddeFoodLocationCommand { get; } = new();
+
+ ///
+ /// 删除食物定位命令
+ ///
+ public ObservableCommand RemoveFoodLocationCommand { get; } = new();
+
+ ///
+ /// 清除食物定位命令
+ ///
+ public ObservableCommand ClearFoodLocationCommand { get; } = new();
+ #endregion
///
/// 改变食物图片
///
@@ -159,16 +199,25 @@ public class FoodAnimeEditWindowVM
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
- PlayCommand.ExecuteEvent += PlayCommand_ExecuteEvent;
+ PlayCommand.AsyncExecuteEvent += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteEvent += StopCommand_ExecuteEvent;
- AddImageCommand.ExecuteEvent += AddImageCommand_ExecuteEvent;
- ClearImageCommand.ExecuteEvent += ClearImageCommand_ExecuteEvent;
- RemoveAnimeCommand.ExecuteEvent += RemoveAnimeCommand_ExecuteEvent;
- RemoveImageCommand.ExecuteEvent += RemoveImageCommand_ExecuteEvent;
- ReplaceFoodImageCommand.ExecuteEvent += ReplaceFoodImageCommand_ExecuteEvent;
+ ReplaceFoodImageCommand.ExecuteEvent += ChangeFoodImageCommand_ExecuteEvent;
ResetFoodImageCommand.ExecuteEvent += ResetFoodImageCommand_ExecuteEvent;
- Anime.ValueChanged += Anime_ValueChanged;
+ AddAnimeCommand.ExecuteEvent += AddAnimeCommand_ExecuteEvent;
+ RemoveAnimeCommand.ExecuteEvent += RemoveAnimeCommand_ExecuteEvent;
+
+ AddFrontImageCommand.ExecuteEvent += AddFrontImageCommand_ExecuteEvent;
+ RemoveFrontImageCommand.ExecuteEvent += RemoveFrontImageCommand_ExecuteEvent;
+ ClearFrontImageCommand.ExecuteEvent += ClearFrontImageCommand_ExecuteEvent;
+
+ AddBackImageCommand.ExecuteEvent += AddBackImageCommand_ExecuteEvent;
+ RemoveBackImageCommand.ExecuteEvent += RemoveBackImageCommand_ExecuteEvent;
+ ClearBackImageCommand.ExecuteEvent += ClearBackImageCommand_ExecuteEvent;
+
+ AddeFoodLocationCommand.ExecuteEvent += AddeFoodLocationCommand_ExecuteEvent;
+ RemoveFoodLocationCommand.ExecuteEvent += RemoveFoodLocationCommand_ExecuteEvent;
+ ClearFoodLocationCommand.ExecuteEvent += ClearFoodLocationCommand_ExecuteEvent;
}
private void ResetFoodImageCommand_ExecuteEvent()
@@ -178,7 +227,7 @@ public class FoodAnimeEditWindowVM
FoodImage.Value = DefaultFoodImage;
}
- private void ReplaceFoodImageCommand_ExecuteEvent()
+ private void ChangeFoodImageCommand_ExecuteEvent()
{
OpenFileDialog openFileDialog =
new() { Title = "选择食物图片".Translate(), Filter = $"图片|*.png".Translate() };
@@ -190,113 +239,218 @@ public class FoodAnimeEditWindowVM
}
}
- #region LoadAnime
- private void Anime_ValueChanged(FoodAnimeTypeModel oldValue, FoodAnimeTypeModel newValue)
+ //#region LoadAnime
+ //private void Anime_ValueChanged(FoodAnimeTypeModel oldValue, FoodAnimeTypeModel newValue)
+ //{
+ // CheckGraphType(newValue);
+ //}
+
+ //private void CheckGraphType(FoodAnimeTypeModel model)
+ //{
+ // //if (FoodAnimeTypeModel.HasMultiTypeAnimes.Contains(model.GraphType.Value))
+ // // HasMultiType.Value = true;
+
+ // //if (FoodAnimeTypeModel.HasNameAnimes.Contains(model.GraphType.Value))
+ // // HasAnimeName.Value = true;
+ //}
+ //#endregion
+ #region AnimeCommand
+ private void AddAnimeCommand_ExecuteEvent()
{
- CheckGraphType(newValue);
+ if (CurrentMode is GameSave.ModeType.Happy)
+ Anime.Value.HappyAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.Nomal)
+ Anime.Value.NomalAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.PoorCondition)
+ Anime.Value.PoorConditionAnimes.Add(new());
+ else if (CurrentMode is GameSave.ModeType.Ill)
+ Anime.Value.IllAnimes.Add(new());
}
- private void CheckGraphType(FoodAnimeTypeModel model)
- {
- //if (FoodAnimeTypeModel.HasMultiTypeAnimes.Contains(model.GraphType.Value))
- // HasMultiType.Value = true;
-
- //if (FoodAnimeTypeModel.HasNameAnimes.Contains(model.GraphType.Value))
- // HasAnimeName.Value = true;
- }
- #endregion
///
/// 删除动画
///
/// 动画模型
- private void RemoveAnimeCommand_ExecuteEvent(AnimeModel value)
+ private void RemoveAnimeCommand_ExecuteEvent(FoodAnimeModel value)
{
if (
MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
)
{
- //if (CurrentMode is GameSave.ModeType.Happy)
- // Anime.Value.HappyAnimes.Remove(value);
- //else if (CurrentMode is GameSave.ModeType.Nomal)
- // Anime.Value.NomalAnimes.Remove(value);
- //else if (CurrentMode is GameSave.ModeType.PoorCondition)
- // Anime.Value.PoorConditionAnimes.Remove(value);
- //else if (CurrentMode is GameSave.ModeType.Ill)
- // Anime.Value.IllAnimes.Remove(value);
+ if (CurrentMode is GameSave.ModeType.Happy)
+ Anime.Value.HappyAnimes.Remove(value);
+ else if (CurrentMode is GameSave.ModeType.Nomal)
+ Anime.Value.NomalAnimes.Remove(value);
+ else if (CurrentMode is GameSave.ModeType.PoorCondition)
+ Anime.Value.PoorConditionAnimes.Remove(value);
+ else if (CurrentMode is GameSave.ModeType.Ill)
+ Anime.Value.IllAnimes.Remove(value);
value.Close();
}
}
+ #endregion
+ #region ImageCommand
+
+ #region FrontImageCommand
+ ///
+ /// 添加顶层图片
+ ///
+ /// 动画模型
+ private void AddFrontImageCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ OpenFileDialog openFileDialog =
+ new()
+ {
+ Title = "选择图片".Translate(),
+ Filter = $"图片|*.png".Translate(),
+ Multiselect = true
+ };
+ if (openFileDialog.ShowDialog() is true)
+ {
+ AddImages(value.FrontImages, openFileDialog.FileNames);
+ }
+ }
///
- /// 清空图片
+ /// 删除顶层图片
///
/// 动画模型
- private void ClearImageCommand_ExecuteEvent(AnimeModel value)
+ private void RemoveFrontImageCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ value.FrontImages.Remove(CurrentFrontImageModel.Value);
+ CurrentFrontImageModel.Value.Close();
+ }
+
+ ///
+ /// 清空顶层图片
+ ///
+ /// 动画模型
+ private void ClearFrontImageCommand_ExecuteEvent(FoodAnimeModel value)
{
if (
MessageBox.Show("确定清空吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
)
{
- value.Close();
- value.Images.Clear();
+ foreach (var image in value.FrontImages)
+ image.Close();
+ value.FrontImages.Clear();
}
}
+ private void ShowFrontImagesPathInfo(FoodImagesPath imagesPath)
+ {
+ MessageBox.Show(
+ "此顶层动画源位于其它位置\n请去源位置修改此动画\n源位置 模式:{0} 索引:{1}".Translate(
+ imagesPath.Mode,
+ imagesPath.Index
+ )
+ );
+ }
+ #endregion
+
+ #region BackImageCommand
///
- /// 添加图片
+ /// 添加顶层图片
///
/// 动画模型
- private void AddImageCommand_ExecuteEvent(AnimeModel value)
+ private void AddBackImageCommand_ExecuteEvent(FoodAnimeModel value)
{
OpenFileDialog openFileDialog =
- new() { Title = "选择图片".Translate(), Filter = $"图片|*.png".Translate() };
+ new()
+ {
+ Title = "选择图片".Translate(),
+ Filter = $"图片|*.png".Translate(),
+ Multiselect = true
+ };
if (openFileDialog.ShowDialog() is true)
{
- value.Images.Add(new(Utils.LoadImageToMemoryStream(openFileDialog.FileName)));
+ AddImages(value.BackImages, openFileDialog.FileNames);
}
}
+ ///
+ /// 删除顶层图片
+ ///
+ /// 动画模型
+ private void RemoveBackImageCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ value.BackImages.Remove(CurrentBackImageModel.Value);
+ CurrentBackImageModel.Value.Close();
+ }
+
+ ///
+ /// 清空顶层图片
+ ///
+ /// 动画模型
+ private void ClearBackImageCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ if (
+ MessageBox.Show("确定清空吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
+ )
+ {
+ foreach (var image in value.BackImages)
+ image.Close();
+ value.BackImages.Clear();
+ }
+ }
+ #endregion
+
///
/// 添加图片
///
- /// 动画模型
+ /// 动画
/// 路径
- public void AddImages(AnimeModel model, IEnumerable paths)
+ public void AddImages(ObservableCollection images, IEnumerable paths)
{
try
{
+ var newImages = new List();
foreach (string path in paths)
{
if (File.Exists(path))
{
- model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
+ newImages.Add(new(Utils.LoadImageToMemoryStream(path)));
}
else if (Directory.Exists(path))
{
foreach (var file in Directory.EnumerateFiles(path, "*.png"))
{
- model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
+ newImages.Add(new(Utils.LoadImageToMemoryStream(path)));
}
}
}
+ foreach (var image in newImages)
+ images.Add(image);
}
catch (Exception ex)
{
MessageBox.Show("添加失败 \n{0}".Translate(ex));
}
}
-
- ///
- /// 删除图片
- ///
- /// 动画模型
- private void RemoveImageCommand_ExecuteEvent(AnimeModel value)
+ #endregion
+ #region FoodLocationCommand
+ private void AddeFoodLocationCommand_ExecuteEvent(FoodAnimeModel value)
{
- CurrentFrontImageModel.Value.Close();
- value.Images.Remove(CurrentFrontImageModel.Value);
+ value.FoodLocations.Add(new());
}
+ private void RemoveFoodLocationCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ value.FoodLocations.Remove(CurrentFoodLocationModel.Value);
+ CurrentFoodLocationModel.Value = null;
+ }
+
+ private void ClearFoodLocationCommand_ExecuteEvent(FoodAnimeModel value)
+ {
+ if (
+ MessageBox.Show("确定清空吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
+ )
+ {
+ value.FoodLocations.Clear();
+ }
+ }
+ #endregion
#region FrontPlayer
private void CurrentAnimeModel_ValueChanged(FoodAnimeModel oldValue, FoodAnimeModel newValue)
{
@@ -327,19 +481,13 @@ public class FoodAnimeEditWindowVM
{
if (_playing is false)
return;
- Reset();
}
///
/// 开始播放
///
- private void PlayCommand_ExecuteEvent()
+ private async Task PlayCommand_AsyncExecuteEvent()
{
- if (_playing)
- {
- MessageBox.Show("正在播放".Translate());
- return;
- }
if (CurrentAnimeModel.Value is null)
{
MessageBox.Show("未选中动画".Translate());
@@ -349,6 +497,8 @@ public class FoodAnimeEditWindowVM
_frontPlayerTask.Start();
_backPlayerTask.Start();
_foodPlayerTask.Start();
+ await Task.WhenAll(_frontPlayerTask, _backPlayerTask, _foodPlayerTask);
+ Reset();
}
///
diff --git a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
index 110c3fa..7b2c6c5 100644
--- a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
+++ b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
@@ -12,6 +12,7 @@
Width="1000"
Height="600"
d:DataContext="{d:DesignInstance Type=vm:AnimeEditWindowVM}"
+ WindowStartupLocation="CenterScreen"
mc:Ignorable="d">