diff --git a/VPet.ModMaker/Converters.xaml b/VPet.ModMaker/Converters.xaml
index 78c7b7d..48c470e 100644
--- a/VPet.ModMaker/Converters.xaml
+++ b/VPet.ModMaker/Converters.xaml
@@ -8,4 +8,5 @@
+
\ No newline at end of file
diff --git a/VPet.ModMaker/Converters/FalseToHiddenConverter.cs b/VPet.ModMaker/Converters/FalseToHiddenConverter.cs
new file mode 100644
index 0000000..40d8c67
--- /dev/null
+++ b/VPet.ModMaker/Converters/FalseToHiddenConverter.cs
@@ -0,0 +1,26 @@
+using Panuon.WPF;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Data;
+
+namespace VPet.ModMaker.Converters;
+
+public class FalseToHiddenConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return (bool.TryParse(value.ToString(), out var result) && result)
+ ? Visibility.Visible
+ : Visibility.Hidden;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value is Visibility visibility && visibility == Visibility.Hidden;
+ }
+}
diff --git a/VPet.ModMaker/Models/ModModel/AnimeModel.cs b/VPet.ModMaker/Models/ModModel/AnimeModel.cs
index fd2e5fd..5746a6d 100644
--- a/VPet.ModMaker/Models/ModModel/AnimeModel.cs
+++ b/VPet.ModMaker/Models/ModModel/AnimeModel.cs
@@ -48,40 +48,137 @@ public class AnimeTypeModel
GraphType.Value = graphType;
if (graphType is GraphInfo.GraphType.Default)
LoadDefault(path);
+ else if (graphType is GraphInfo.GraphType.Touch_Head or GraphInfo.GraphType.Touch_Body)
+ LoadMultiTypeAnime(path);
+ else
+ throw new Exception();
+ }
+
+ public static AnimeTypeModel? Create(GraphInfo.GraphType graphType, string path)
+ {
+ try
+ {
+ var model = new AnimeTypeModel(graphType, path);
+ return model;
+ }
+ catch
+ {
+ return null;
+ }
}
private void LoadDefault(string path)
{
- foreach (var modeDir in Directory.EnumerateDirectories(path))
+ foreach (var dir in Directory.EnumerateDirectories(path))
{
- var mode = Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(modeDir), true);
+ var mode = Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(dir), true);
if (mode is GameSave.ModeType.Happy)
{
- foreach (var imagesDir in Directory.EnumerateDirectories(modeDir))
- {
- HappyAnimes.Add(new(imagesDir));
- }
+ AddAnime(HappyAnimes, dir);
}
else if (mode is GameSave.ModeType.Nomal)
{
- foreach (var imagesDir in Directory.EnumerateDirectories(modeDir))
- {
- NomalAnimes.Add(new(imagesDir));
- }
+ AddAnime(NomalAnimes, dir);
}
else if (mode is GameSave.ModeType.PoorCondition)
{
- foreach (var imagesDir in Directory.EnumerateDirectories(modeDir))
- {
- PoorConditionAnimes.Add(new(imagesDir));
- }
+ AddAnime(PoorConditionAnimes, dir);
}
else if (mode is GameSave.ModeType.Ill)
{
- foreach (var imagesDir in Directory.EnumerateDirectories(modeDir))
+ AddAnime(IllAnimes, dir);
+ }
+ }
+ }
+
+ private void LoadMultiTypeAnime(string path)
+ {
+ foreach (var dir in Directory.EnumerateDirectories(path))
+ {
+ var dirName = Path.GetFileName(dir);
+ var dirInfo = dirName.Split(Utils.Separator, StringSplitOptions.RemoveEmptyEntries);
+ if (dirInfo.Length == 2)
+ {
+ // 判断 A_Happy 类型文件夹
+ var typeName = dirInfo[0];
+ var modeName = dirInfo[1];
+ var type = GetAnimatType(typeName[0]);
+ var mode = Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(modeName), true);
+ if (mode is GameSave.ModeType.Happy)
{
- IllAnimes.Add(new(imagesDir));
+ AddAnime(HappyAnimes, dir, type);
}
+ else if (mode is GameSave.ModeType.Nomal)
+ {
+ AddAnime(NomalAnimes, dir, type);
+ }
+ else if (mode is GameSave.ModeType.PoorCondition)
+ {
+ AddAnime(PoorConditionAnimes, dir, type);
+ }
+ else if (mode is GameSave.ModeType.Ill)
+ {
+ AddAnime(IllAnimes, dir, type);
+ }
+ }
+ else
+ {
+ // 判断 Happy/A 型文件夹
+ var mode = Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(dirName), true);
+ foreach (var typePath in Directory.EnumerateDirectories(dir))
+ {
+ var type = GetAnimatType(Path.GetFileName(typePath)[0]);
+ if (mode is GameSave.ModeType.Happy)
+ {
+ AddAnime(HappyAnimes, dir, type);
+ }
+ else if (mode is GameSave.ModeType.Nomal)
+ {
+ AddAnime(NomalAnimes, dir, type);
+ }
+ else if (mode is GameSave.ModeType.PoorCondition)
+ {
+ AddAnime(PoorConditionAnimes, dir, type);
+ }
+ else if (mode is GameSave.ModeType.Ill)
+ {
+ AddAnime(IllAnimes, dir, type);
+ }
+ }
+ }
+ }
+ }
+
+ private static GraphInfo.AnimatType GetAnimatType(char c)
+ {
+ return c switch
+ {
+ 'A' => GraphInfo.AnimatType.A_Start,
+ 'B' => GraphInfo.AnimatType.B_Loop,
+ 'C' => GraphInfo.AnimatType.C_End,
+ _ => GraphInfo.AnimatType.Single,
+ };
+ }
+
+ public static void AddAnime(
+ ObservableCollection collection,
+ string path,
+ GraphInfo.AnimatType animatType = AnimatType.Single
+ )
+ {
+ if (Directory.EnumerateFiles(path).Any())
+ {
+ var animeModel = new AnimeModel(path);
+ animeModel.AnimeType.Value = animatType;
+ collection.Add(animeModel);
+ }
+ else
+ {
+ foreach (var imagesDir in Directory.EnumerateDirectories(path))
+ {
+ var animeModel = new AnimeModel(imagesDir);
+ animeModel.AnimeType.Value = animatType;
+ collection.Add(animeModel);
}
}
}
@@ -96,7 +193,6 @@ public class AnimeModel
//public ObservableValue ModeType { get; } = new();
public ObservableCollection Images { get; } = new();
- private static readonly char[] _splits = new char[] { '_' };
public AnimeModel() { }
@@ -104,8 +200,7 @@ public class AnimeModel
{
foreach (var file in Directory.EnumerateFiles(imagesPath))
{
- var info = Path.GetFileNameWithoutExtension(file)
- .Split(_splits, StringSplitOptions.RemoveEmptyEntries);
+ var info = Path.GetFileNameWithoutExtension(file).Split(Utils.Separator);
Id.Value = info[0];
var duration = info.Last();
var imageModel = new ImageModel(Utils.LoadImageToStream(file), int.Parse(duration));
diff --git a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
index 35d0cdd..914d5f8 100644
--- a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
+++ b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs
@@ -84,8 +84,8 @@ public class ModInfoModel : I18nModel
true,
out var animeType
);
- if (animeType is GraphInfo.GraphType.Default)
- petModel.Animes.Add(new(animeType, dir));
+ if (AnimeTypeModel.Create(animeType, dir) is AnimeTypeModel model)
+ petModel.Animes.Add(model);
}
}
}
@@ -250,6 +250,88 @@ public class ModInfoModel : I18nModel
var petAnimePath = Path.Combine(petPath, pet.Id.Value);
Directory.CreateDirectory(petAnimePath);
SaveAnime_Default(petAnimePath, pet);
+ SaveAnime_MultiType(petAnimePath, pet);
+ }
+ }
+
+ void SaveAnime_MultiType(string path, PetModel pet)
+ {
+ if (
+ pet.Animes.FirstOrDefault(m => m.GraphType.Value is GraphInfo.GraphType.Touch_Head)
+ is AnimeTypeModel animeType1
+ )
+ {
+ SaveMultiTypeAnime(
+ Path.Combine(path, nameof(GraphInfo.GraphType.Touch_Head)),
+ animeType1
+ );
+ }
+ if (
+ pet.Animes.FirstOrDefault(m => m.GraphType.Value is GraphInfo.GraphType.Touch_Body)
+ is AnimeTypeModel animeType2
+ )
+ {
+ SaveMultiTypeAnime(
+ Path.Combine(path, nameof(GraphInfo.GraphType.Touch_Body)),
+ animeType2
+ );
+ }
+
+ static void SaveMultiTypeAnime(string animePath, AnimeTypeModel model)
+ {
+ Directory.CreateDirectory(animePath);
+ if (model.HappyAnimes.Count > 0)
+ {
+ var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Happy));
+ SaveAnimes(modePath, model.HappyAnimes);
+ }
+ if (model.NomalAnimes.Count > 0)
+ {
+ var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Nomal));
+ SaveAnimes(modePath, model.NomalAnimes);
+ }
+ if (model.PoorConditionAnimes.Count > 0)
+ {
+ var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.PoorCondition));
+ SaveAnimes(modePath, model.PoorConditionAnimes);
+ }
+ if (model.IllAnimes.Count > 0)
+ {
+ var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Ill));
+ SaveAnimes(modePath, model.IllAnimes);
+ }
+ }
+
+ static void SaveAnimes(string animePath, ObservableCollection animes)
+ {
+ Directory.CreateDirectory(animePath);
+ var countA = 0;
+ var countB = 0;
+ var countC = 0;
+ foreach (var anime in animes)
+ {
+ if (anime.AnimeType.Value is GraphInfo.AnimatType.A_Start)
+ {
+ var animatTypePath = Path.Combine(animePath, "A");
+ Directory.CreateDirectory(animatTypePath);
+ SaveImages(Path.Combine(animatTypePath, countA.ToString()), anime);
+ countA++;
+ }
+ else if (anime.AnimeType.Value is GraphInfo.AnimatType.B_Loop)
+ {
+ var animatTypePath = Path.Combine(animePath, "B");
+ Directory.CreateDirectory(animatTypePath);
+ SaveImages(Path.Combine(animatTypePath, countB.ToString()), anime);
+ countB++;
+ }
+ else if (anime.AnimeType.Value is GraphInfo.AnimatType.C_End)
+ {
+ var animatTypePath = Path.Combine(animePath, "C");
+ Directory.CreateDirectory(animatTypePath);
+ SaveImages(Path.Combine(animatTypePath, countC.ToString()), anime);
+ countC++;
+ }
+ }
}
}
@@ -265,53 +347,55 @@ public class ModInfoModel : I18nModel
if (animeType.HappyAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Happy));
- SaveImage(animeType.HappyAnimes, animeType, modePath);
+ SaveAnimes(modePath, animeType.HappyAnimes);
}
if (animeType.NomalAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Nomal));
- SaveImage(animeType.NomalAnimes, animeType, modePath);
+ SaveAnimes(modePath, animeType.NomalAnimes);
}
if (animeType.PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.PoorCondition));
- SaveImage(animeType.PoorConditionAnimes, animeType, modePath);
+ SaveAnimes(modePath, animeType.PoorConditionAnimes);
}
if (animeType.IllAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Ill));
- SaveImage(animeType.IllAnimes, animeType, modePath);
+ SaveAnimes(modePath, animeType.IllAnimes);
}
-
- static void SaveImage(
- ObservableCollection animes,
- AnimeTypeModel animeType,
- string modePath
- )
+ static void SaveAnimes(string animePath, ObservableCollection animes)
{
- Directory.CreateDirectory(modePath);
+ Directory.CreateDirectory(animePath);
var count = 0;
foreach (var anime in animes)
{
- var imagePath = Path.Combine(modePath, count.ToString());
+ var imagePath = Path.Combine(animePath, count.ToString());
Directory.CreateDirectory(imagePath);
- var imageIndex = 0;
- foreach (var image in anime.Images)
- {
- File.Copy(
- image.Image.Value.GetSourceFile(),
- Path.Combine(
- imagePath,
- $"{anime.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png"
- )
- );
- imageIndex++;
- }
+ SaveImages(Path.Combine(imagePath, count.ToString()), anime);
count++;
}
}
}
+ static void SaveImages(string imagesPath, AnimeModel model)
+ {
+ Directory.CreateDirectory(imagesPath);
+ var imageIndex = 0;
+ foreach (var image in model.Images)
+ {
+ File.Copy(
+ image.Image.Value.GetSourceFile(),
+ Path.Combine(
+ imagesPath,
+ $"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png"
+ ),
+ true
+ );
+ imageIndex++;
+ }
+ }
+
void GetMoveInfo(LPS lps, PetModel pet)
{
foreach (var move in pet.Moves)
diff --git a/VPet.ModMaker/Models/Utils.cs b/VPet.ModMaker/Models/Utils.cs
index 2265c93..5dc97ef 100644
--- a/VPet.ModMaker/Models/Utils.cs
+++ b/VPet.ModMaker/Models/Utils.cs
@@ -13,6 +13,7 @@ public static class Utils
{
public const int DecodePixelWidth = 250;
public const int DecodePixelHeight = 250;
+ public static char[] Separator { get; } = new char[] { '_' };
public static BitmapImage LoadImageToStream(string imagePath)
{
diff --git a/VPet.ModMaker/VPet.ModMaker.csproj b/VPet.ModMaker/VPet.ModMaker.csproj
index 9229814..dcdec11 100644
--- a/VPet.ModMaker/VPet.ModMaker.csproj
+++ b/VPet.ModMaker/VPet.ModMaker.csproj
@@ -92,6 +92,7 @@
+
diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
index e244e42..482d2fb 100644
--- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
+++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs
@@ -23,6 +23,8 @@ public class AnimeEditWindowVM
public ObservableValue CurrentAnimeModel { get; } = new();
public GameSave.ModeType CurrentMode { get; set; }
public ObservableValue Loop { get; } = new();
+
+ public ObservableValue HasMultiType { get; } = new(false);
#region Command
public ObservableCommand PlayCommand { get; } = new();
public ObservableCommand StopCommand { get; } = new();
@@ -41,7 +43,6 @@ public class AnimeEditWindowVM
_playerTask = new(Play);
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
- ;
PlayCommand.ExecuteEvent += PlayCommand_ExecuteEvent;
StopCommand.ExecuteEvent += StopCommand_ExecuteEvent;
@@ -49,6 +50,23 @@ public class AnimeEditWindowVM
ClearImageCommand.ExecuteEvent += ClearImageCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteEvent += RemoveAnimeCommand_ExecuteEvent;
RemoveImageCommand.ExecuteEvent += RemoveImageCommand_ExecuteEvent;
+
+ Anime.ValueChanged += Anime_ValueChanged;
+ }
+
+ private void Anime_ValueChanged(AnimeTypeModel oldValue, AnimeTypeModel newValue)
+ {
+ CheckGraphType(newValue);
+ }
+
+ private void CheckGraphType(AnimeTypeModel model)
+ {
+ if (
+ model.GraphType.Value
+ is GraphInfo.GraphType.Touch_Body
+ or GraphInfo.GraphType.Touch_Head
+ )
+ HasMultiType.Value = true;
}
private void CurrentAnimeModel_ValueChanged(AnimeModel oldValue, AnimeModel newValue)
@@ -115,6 +133,31 @@ public class AnimeEditWindowVM
}
}
+ public void AddImages(AnimeModel model, IEnumerable paths)
+ {
+ try
+ {
+ foreach (string path in paths)
+ {
+ if (File.Exists(path))
+ {
+ model.Images.Add(new(Utils.LoadImageToStream(path)));
+ }
+ else if (Directory.Exists(path))
+ {
+ foreach (var file in Directory.EnumerateFiles(path, "*.png"))
+ {
+ model.Images.Add(new(Utils.LoadImageToStream(path)));
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("添加失败 \n{0}".Translate(ex));
+ }
+ }
+
private void StopCommand_ExecuteEvent()
{
if (_playing is false)
diff --git a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
index 2645310..bb7daa9 100644
--- a/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
+++ b/VPet.ModMaker/Views/ModEdit/AnimeEdit/AnimeEditWindow.xaml
@@ -48,6 +48,7 @@
+
@@ -59,6 +60,12 @@
+
i.Id.Value == ViewModel.Work.Value.Id.Value)
- //)
- //{
- // MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
- // return;
- //}
IsCancel = false;
Close();
}
- //private void ListBox_Drop(object sender, DragEventArgs e)
- //{
- // var fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
- //}
-
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (
@@ -125,13 +97,15 @@ public partial class AnimeEditWindow : Window
private void ListBox_Drop(object sender, DragEventArgs e)
{
- if (sender.Equals(_dropSender) is false)
+ if (sender is not ListBox listBox)
+ return;
+ if (e.Data.GetData(DataFormats.FileDrop) is Array array)
+ ViewModel.AddImages((AnimeModel)listBox.DataContext, array.Cast());
+ if (_dropSender is not null && sender.Equals(_dropSender) is false)
{
MessageBox.Show("无法移动不同动画的图片");
return;
}
- if (sender is not ListBox listBox)
- return;
var pos = e.GetPosition(listBox);
var result = VisualTreeHelper.HitTest(listBox, pos);
if (result == null)