AnimeEdit 新增支持 Work

This commit is contained in:
Hakoyu
2023-09-27 18:14:29 +08:00
parent 5831b2d0f7
commit 8746b439e1
13 changed files with 630 additions and 535 deletions

View File

@ -8,6 +8,8 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
namespace VPet.ModMaker.Models;
@ -74,6 +76,11 @@ public static class Extensions
return true;
}
public static bool IsHasNameAnime(this GraphInfo.GraphType graphType)
{
return AnimeTypeModel.HasNameAnimes.Contains(graphType);
}
/// <summary>
/// 流内容对比
/// </summary>

View File

@ -94,20 +94,11 @@ public class ModLoader
var name = lps.First().Info;
var pet = new PetLoader(lps, di);
Pets.Add(pet);
// TODO : 此方法会导致 LoadImageToStream 无法使用
// ! : 此方法会导致 LoadImageToStream 无法使用
//var graphCore = new GraphCore(0);
//foreach (var p in pet.path)
// PetLoader.LoadGraph(graphCore, di, p);
//MultiGraphs.Add(pet.Name, graphCore);
//var p = mw.Pets.FirstOrDefault(x => x.Id == name);
//if (p == null)
// mw.Pets.Add(new PetLoader(lps, di));
//else
//{
// p.path.Add(di.FullName + "\\" + lps.First()["path"].Info);
// p.Config.Set(lps);
//}
}
}
break;

View File

@ -1,523 +1,11 @@
using HKW.HKWViewModels.SimpleObservable;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using VPet_Simulator.Core;
using static VPet_Simulator.Core.GraphInfo;
namespace VPet.ModMaker.Models.ModModel;
public class AnimeTypeModel
{
public static ObservableCollection<GraphInfo.GraphType> GraphTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.GraphType)).Cast<GraphInfo.GraphType>());
public static ObservableCollection<GraphInfo.AnimatType> AnimatTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.AnimatType)).Cast<GraphInfo.AnimatType>());
public static ObservableCollection<GameSave.ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(GameSave.ModeType)).Cast<GameSave.ModeType>());
public ObservableValue<string> Id { get; } = new();
public ObservableValue<string> Name { get; } = new();
public ObservableValue<GraphInfo.GraphType> GraphType { get; } = new();
public ObservableCollection<AnimeModel> HappyAnimes { get; } = new();
public ObservableCollection<AnimeModel> NomalAnimes { get; } = new();
public ObservableCollection<AnimeModel> PoorConditionAnimes { get; } = new();
public ObservableCollection<AnimeModel> IllAnimes { get; } = new();
public AnimeTypeModel()
{
Name.ValueChanged += (_, _) =>
{
Id.Value = $"{GraphType.Value}_{Name.Value}";
};
}
public AnimeTypeModel(AnimeTypeModel model)
: this()
{
Id.Value = model.Id.Value;
Name.Value = model.Name.Value;
GraphType.Value = model.GraphType.Value;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Copy());
foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Copy());
foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Copy());
}
public static AnimeTypeModel? Create(GraphInfo.GraphType graphType, string path)
{
try
{
var model = new AnimeTypeModel(graphType, path);
return model;
}
catch
{
return null;
}
}
public AnimeTypeModel(GraphInfo.GraphType graphType, string path)
{
Name.Value = Path.GetFileName(path);
if (graphType is GraphInfo.GraphType.Common)
Id.Value = $"{nameof(GraphInfo.GraphType.Common)}_{Name.Value}";
else
Id.Value = graphType.ToString();
GraphType.Value = graphType;
if (
graphType
is GraphInfo.GraphType.Default
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
or GraphInfo.GraphType.Switch_Up
or GraphInfo.GraphType.Switch_Down
or GraphInfo.GraphType.Switch_Thirsty
or GraphInfo.GraphType.Switch_Hunger
or GraphInfo.GraphType.Raised_Dynamic
)
LoadDefault(path);
else if (
graphType
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
or GraphInfo.GraphType.Raised_Static
or GraphInfo.GraphType.StateONE
or GraphInfo.GraphType.StateTWO
or GraphInfo.GraphType.Common
)
LoadMultiType(path);
else
throw new Exception();
}
//private void LoadSingle(string path)
//{
// foreach (var dir in Directory.EnumerateDirectories(path))
// {
// var dirName = Path.GetFileName(dir);
// var dirInfo = dirName.Split(Utils.Separator);
// var mode = Enum.Parse(typeof(GameSave.ModeType), dirInfo[0], true);
// if (dirInfo.Length == 2) { }
// }
//}
private void LoadDefault(string path)
{
foreach (var dir in Directory.EnumerateDirectories(path))
{
var dirName = Path.GetFileName(dir);
if (
dirName.Contains(
nameof(GameSave.ModeType.Happy),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(HappyAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.Nomal),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(NomalAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.PoorCondition),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(PoorConditionAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.Ill),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(IllAnimes, dir);
}
}
if (Directory.EnumerateFiles(path).Any())
{
AddAnime(NomalAnimes, path);
}
}
private void LoadMultiType(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)
{
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 if (Enum.TryParse<GameSave.ModeType>(dirName, true, out var mode))
{
// 判断 Happy/A 型文件夹
foreach (var typePath in Directory.EnumerateDirectories(dir))
{
var type = GetAnimatType(
Path.GetFileName(typePath).Split(Utils.Separator).First()[0]
);
if (mode is GameSave.ModeType.Happy)
{
AddAnime(HappyAnimes, typePath, type);
}
else if (mode is GameSave.ModeType.Nomal)
{
AddAnime(NomalAnimes, typePath, type);
}
else if (mode is GameSave.ModeType.PoorCondition)
{
AddAnime(PoorConditionAnimes, typePath, type);
}
else if (mode is GameSave.ModeType.Ill)
{
AddAnime(IllAnimes, typePath, type);
}
}
}
else
{
var type = GetAnimatType(dirName[0]);
// 判断 A/Happy 文件夹
foreach (var modePath in Directory.EnumerateDirectories(dir))
{
mode = (GameSave.ModeType)
Enum.Parse(
typeof(GameSave.ModeType),
Path.GetFileName(modePath).Split(Utils.Separator).First(),
true
);
if (mode is GameSave.ModeType.Happy)
{
AddAnime(HappyAnimes, modePath, type);
}
else if (mode is GameSave.ModeType.Nomal)
{
AddAnime(NomalAnimes, modePath, type);
}
else if (mode is GameSave.ModeType.PoorCondition)
{
AddAnime(PoorConditionAnimes, modePath, type);
}
else if (mode is GameSave.ModeType.Ill)
{
AddAnime(IllAnimes, modePath, 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,
};
}
private static void AddAnime(
ObservableCollection<AnimeModel> 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);
}
}
}
public void Save(string path)
{
if (
GraphType.Value
is GraphInfo.GraphType.Default
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
)
SaveDefault(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
)
SaveMultiType(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Switch_Up
or GraphInfo.GraphType.Switch_Down
or GraphInfo.GraphType.Switch_Thirsty
or GraphInfo.GraphType.Switch_Hunger
)
SaveSwitch(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Raised_Dynamic
or GraphInfo.GraphType.Raised_Static
)
SaveRaise(path, this);
else if (GraphType.Value is GraphInfo.GraphType.StateONE or GraphInfo.GraphType.StateTWO)
SaveState(path, this);
else if (GraphType.Value is GraphInfo.GraphType.Common)
SaveCommon(path, this);
}
void SaveCommon(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.Name.Value);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
void SaveState(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "State");
Directory.CreateDirectory(animePath);
SaveMultiType(animePath, animeTypeModel);
}
void SaveRaise(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "Raise");
Directory.CreateDirectory(animePath);
if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Dynamic)
SaveDefault(animePath, animeTypeModel);
else if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Static)
SaveMultiType(animePath, animeTypeModel);
}
void SaveSwitch(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "Switch");
Directory.CreateDirectory(animePath);
var switchName = animeTypeModel.GraphType.ToString().Split(Utils.Separator).Last();
SaveWithAnimeType(Path.Combine(animePath, switchName), animeTypeModel);
}
/// <summary>
/// 保存成默认样式
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveDefault(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithAnimeType(animePath, animeTypeModel);
}
/// <summary>
/// 保存成多类型样式
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveMultiType(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
/// <summary>
/// 保存为 ModeType 划分的样式
/// <para><![CDATA[
/// Happy/A/0
/// Happy/A/1
/// Happy/B/0
/// Happy/B/1
/// Nomal/A/0
/// Nomal/A/1
/// ...
/// ]]>
/// </para>
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveWithModeType(string path, AnimeTypeModel animeTypeModel)
{
if (animeTypeModel.HappyAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Happy));
SaveAnimes(modePath, animeTypeModel.HappyAnimes);
}
if (animeTypeModel.NomalAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Nomal));
SaveAnimes(modePath, animeTypeModel.NomalAnimes);
}
if (animeTypeModel.PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.PoorCondition));
SaveAnimes(modePath, animeTypeModel.PoorConditionAnimes);
}
if (animeTypeModel.IllAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Ill));
SaveAnimes(modePath, animeTypeModel.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> 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++;
}
}
}
}
/// <summary>
/// 保存为 AnimeType 划分的样式
/// <para><![CDATA[
/// Happy/0
/// Happy/1
/// Nomal/0
/// Nomal/1
/// ...
/// ]]>
/// </para>
/// </summary>
/// <param name="animePath"></param>
/// <param name="animeType"></param>
static void SaveWithAnimeType(string animePath, AnimeTypeModel animeType)
{
if (animeType.HappyAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Happy));
SaveAnimes(modePath, animeType.HappyAnimes);
}
if (animeType.NomalAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Nomal));
SaveAnimes(modePath, animeType.NomalAnimes);
}
if (animeType.PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.PoorCondition));
SaveAnimes(modePath, animeType.PoorConditionAnimes);
}
if (animeType.IllAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Ill));
SaveAnimes(modePath, animeType.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes)
{
Directory.CreateDirectory(animePath);
var count = 0;
foreach (var anime in animes)
{
SaveImages(Path.Combine(animePath, count.ToString()), anime);
count++;
}
}
}
/// <summary>
/// 保存图片
/// </summary>
/// <param name="imagesPath"></param>
/// <param name="model"></param>
static void SaveImages(string imagesPath, AnimeModel model)
{
Directory.CreateDirectory(imagesPath);
var imageIndex = 0;
foreach (var image in model.Images)
{
image.Image.Value.SaveToPng(
Path.Combine(
imagesPath,
$"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png"
)
);
imageIndex++;
}
}
}
public class AnimeModel
{
public ObservableValue<string> Id { get; } = new();

View File

@ -0,0 +1,521 @@
using HKW.HKWViewModels.SimpleObservable;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using VPet_Simulator.Core;
using static VPet_Simulator.Core.GraphInfo;
namespace VPet.ModMaker.Models.ModModel;
public class AnimeTypeModel
{
public static ObservableCollection<GraphInfo.GraphType> GraphTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.GraphType)).Cast<GraphInfo.GraphType>());
public static ObservableCollection<GraphInfo.AnimatType> AnimatTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.AnimatType)).Cast<GraphInfo.AnimatType>());
public static ObservableCollection<GameSave.ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(GameSave.ModeType)).Cast<GameSave.ModeType>());
public static HashSet<GraphInfo.GraphType> HasNameAnimes { get; } =
new()
{
GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move
};
public ObservableValue<string> Id { get; } = new();
public ObservableValue<string> Name { get; } = new();
public ObservableValue<GraphInfo.GraphType> GraphType { get; } = new();
public ObservableCollection<AnimeModel> HappyAnimes { get; } = new();
public ObservableCollection<AnimeModel> NomalAnimes { get; } = new();
public ObservableCollection<AnimeModel> PoorConditionAnimes { get; } = new();
public ObservableCollection<AnimeModel> IllAnimes { get; } = new();
public AnimeTypeModel()
{
Name.ValueChanged += (_, _) =>
{
Id.Value = $"{GraphType.Value}_{Name.Value}";
};
}
public AnimeTypeModel(AnimeTypeModel model)
: this()
{
Id.Value = model.Id.Value;
Name.Value = model.Name.Value;
GraphType.Value = model.GraphType.Value;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Copy());
foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Copy());
foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Copy());
}
public static AnimeTypeModel? Create(GraphInfo.GraphType graphType, string path)
{
try
{
var model = new AnimeTypeModel(graphType, path);
return model;
}
catch
{
return null;
}
}
public AnimeTypeModel(GraphInfo.GraphType graphType, string path)
{
Name.Value = Path.GetFileName(path);
if (graphType is GraphInfo.GraphType.Common or GraphInfo.GraphType.Work)
Id.Value = $"{graphType}_{Name.Value}";
else
Id.Value = graphType.ToString();
GraphType.Value = graphType;
if (
graphType
is GraphInfo.GraphType.Default
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
or GraphInfo.GraphType.Switch_Up
or GraphInfo.GraphType.Switch_Down
or GraphInfo.GraphType.Switch_Thirsty
or GraphInfo.GraphType.Switch_Hunger
or GraphInfo.GraphType.Raised_Dynamic
)
LoadDefault(path);
else if (
graphType
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
or GraphInfo.GraphType.Raised_Static
or GraphInfo.GraphType.StateONE
or GraphInfo.GraphType.StateTWO
or GraphInfo.GraphType.Common
or GraphInfo.GraphType.Work
)
LoadMultiType(path);
else
throw new Exception();
}
#region Load
private void LoadDefault(string path)
{
foreach (var dir in Directory.EnumerateDirectories(path))
{
var dirName = Path.GetFileName(dir);
if (
dirName.Contains(
nameof(GameSave.ModeType.Happy),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(HappyAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.Nomal),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(NomalAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.PoorCondition),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(PoorConditionAnimes, dir);
}
else if (
dirName.Contains(
nameof(GameSave.ModeType.Ill),
StringComparison.InvariantCultureIgnoreCase
)
)
{
AddAnime(IllAnimes, dir);
}
}
if (Directory.EnumerateFiles(path).Any())
{
AddAnime(NomalAnimes, path);
}
}
private void LoadMultiType(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 == 3)
{
// 判断 A_1_Happy 类型文件夹
var typeName = dirInfo[0];
var modeName = dirInfo[2];
var type = GetAnimatType(typeName[0]);
var mode = (GameSave.ModeType)
Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(modeName), true);
AddAnimeForModeType(dir, mode, type);
}
else if (dirInfo.Length == 2)
{
// 判断 A_Happy 类型文件夹
var typeName = dirInfo[0];
var modeName = dirInfo[1];
var type = GetAnimatType(typeName[0]);
var mode = (GameSave.ModeType)
Enum.Parse(typeof(GameSave.ModeType), Path.GetFileName(modeName), true);
AddAnimeForModeType(dir, mode, type);
}
else if (Enum.TryParse<GameSave.ModeType>(dirName, true, out var mode))
{
// 判断 Happy/A 型文件夹
foreach (var typePath in Directory.EnumerateDirectories(dir))
{
var type = GetAnimatType(
Path.GetFileName(typePath).Split(Utils.Separator).First()[0]
);
AddAnimeForModeType(typePath, mode, type);
}
}
else
{
var type = GetAnimatType(dirName[0]);
// 判断 A/Happy 文件夹
foreach (var modePath in Directory.EnumerateDirectories(dir))
{
mode = (GameSave.ModeType)
Enum.Parse(
typeof(GameSave.ModeType),
Path.GetFileName(modePath).Split(Utils.Separator).First(),
true
);
AddAnimeForModeType(modePath, mode, type);
}
}
}
}
private void AddAnimeForModeType(
string path,
GameSave.ModeType modeType,
GraphInfo.AnimatType animeType
)
{
if (modeType is GameSave.ModeType.Happy)
{
AddAnime(HappyAnimes, path, animeType);
}
else if (modeType is GameSave.ModeType.Nomal)
{
AddAnime(NomalAnimes, path, animeType);
}
else if (modeType is GameSave.ModeType.PoorCondition)
{
AddAnime(PoorConditionAnimes, path, animeType);
}
else if (modeType is GameSave.ModeType.Ill)
{
AddAnime(IllAnimes, path, animeType);
}
}
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,
};
}
private static void AddAnime(
ObservableCollection<AnimeModel> 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);
}
}
}
#endregion
#region Save
public void Save(string path)
{
if (
GraphType.Value
is GraphInfo.GraphType.Default
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
)
SaveDefault(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
)
SaveMultiType(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Switch_Up
or GraphInfo.GraphType.Switch_Down
or GraphInfo.GraphType.Switch_Thirsty
or GraphInfo.GraphType.Switch_Hunger
)
SaveSwitch(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Raised_Dynamic
or GraphInfo.GraphType.Raised_Static
)
SaveRaise(path, this);
else if (GraphType.Value is GraphInfo.GraphType.StateONE or GraphInfo.GraphType.StateTWO)
SaveState(path, this);
else if (GraphType.Value is GraphInfo.GraphType.Common)
SaveCommon(path, this);
else if (GraphType.Value is GraphInfo.GraphType.Work)
SaveHasNameAnime(path, this);
}
void SaveHasNameAnime(string path, AnimeTypeModel animeTypeModel)
{
var animeTypePath = Path.Combine(path, animeTypeModel.GraphType.Value.ToString());
Directory.CreateDirectory(animeTypePath);
var animePath = Path.Combine(animeTypePath, animeTypeModel.Name.Value);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
void SaveCommon(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.Name.Value);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
void SaveState(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "State");
Directory.CreateDirectory(animePath);
SaveMultiType(animePath, animeTypeModel);
}
void SaveRaise(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "Raise");
Directory.CreateDirectory(animePath);
if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Dynamic)
SaveDefault(animePath, animeTypeModel);
else if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Static)
SaveMultiType(animePath, animeTypeModel);
}
void SaveSwitch(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, "Switch");
Directory.CreateDirectory(animePath);
var switchName = animeTypeModel.GraphType.ToString().Split(Utils.Separator).Last();
SaveWithAnimeType(Path.Combine(animePath, switchName), animeTypeModel);
}
/// <summary>
/// 保存成默认样式
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveDefault(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithAnimeType(animePath, animeTypeModel);
}
/// <summary>
/// 保存成多类型样式
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveMultiType(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
/// <summary>
/// 保存为 ModeType 划分的样式
/// <para><![CDATA[
/// Happy/A/0
/// Happy/A/1
/// Happy/B/0
/// Happy/B/1
/// Nomal/A/0
/// Nomal/A/1
/// ...
/// ]]>
/// </para>
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveWithModeType(string path, AnimeTypeModel animeTypeModel)
{
if (animeTypeModel.HappyAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Happy));
SaveAnimes(modePath, animeTypeModel.HappyAnimes);
}
if (animeTypeModel.NomalAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Nomal));
SaveAnimes(modePath, animeTypeModel.NomalAnimes);
}
if (animeTypeModel.PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.PoorCondition));
SaveAnimes(modePath, animeTypeModel.PoorConditionAnimes);
}
if (animeTypeModel.IllAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(GameSave.ModeType.Ill));
SaveAnimes(modePath, animeTypeModel.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> 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++;
}
}
}
}
/// <summary>
/// 保存为 AnimeType 划分的样式
/// <para><![CDATA[
/// Happy/0
/// Happy/1
/// Nomal/0
/// Nomal/1
/// ...
/// ]]>
/// </para>
/// </summary>
/// <param name="animePath"></param>
/// <param name="animeType"></param>
static void SaveWithAnimeType(string animePath, AnimeTypeModel animeType)
{
if (animeType.HappyAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Happy));
SaveAnimes(modePath, animeType.HappyAnimes);
}
if (animeType.NomalAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Nomal));
SaveAnimes(modePath, animeType.NomalAnimes);
}
if (animeType.PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.PoorCondition));
SaveAnimes(modePath, animeType.PoorConditionAnimes);
}
if (animeType.IllAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(GameSave.ModeType.Ill));
SaveAnimes(modePath, animeType.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes)
{
Directory.CreateDirectory(animePath);
var count = 0;
foreach (var anime in animes)
{
SaveImages(Path.Combine(animePath, count.ToString()), anime);
count++;
}
}
}
/// <summary>
/// 保存图片
/// </summary>
/// <param name="imagesPath"></param>
/// <param name="model"></param>
static void SaveImages(string imagesPath, AnimeModel model)
{
Directory.CreateDirectory(imagesPath);
var imageIndex = 0;
foreach (var image in model.Images)
{
image.Image.Value.SaveToPng(
Path.Combine(
imagesPath,
$"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png"
)
);
imageIndex++;
}
}
#endregion
}

View File

@ -98,7 +98,18 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
var dirName = Path.GetFileName(animeDir);
if (Enum.TryParse<GraphInfo.GraphType>(dirName, true, out var animeType))
{
if (AnimeTypeModel.Create(animeType, animeDir) is AnimeTypeModel model)
if (animeType is GraphInfo.GraphType.Work)
{
foreach (var dir in Directory.EnumerateDirectories(animeDir))
{
if (
AnimeTypeModel.Create(GraphInfo.GraphType.Work, dir)
is AnimeTypeModel model1
)
petModel.Animes.Add(model1);
}
}
else if (AnimeTypeModel.Create(animeType, animeDir) is AnimeTypeModel model)
petModel.Animes.Add(model);
}
else if (dirName.Equals("Switch", StringComparison.InvariantCultureIgnoreCase))
@ -161,6 +172,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
}
#region Load
private void LoadI18nData()
{
foreach (var lang in I18nDatas)
@ -220,7 +232,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
}
}
#endregion
#region Save
public void Save()
{
SaveTo(SourcePath.Value);
@ -340,7 +353,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
new Line("pet", pet.Id.Value)
{
new Sub("intor", pet.DescriptionId.Value),
new Sub("ModPath", pet.Id.Value),
new Sub("path", pet.Id.Value),
new Sub("petname", pet.PetNameId.Value)
}
);
@ -546,7 +559,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
}
}
#endregion
public void Close()
{
Image.Value.CloseStream();

View File

@ -101,6 +101,7 @@
<Compile Include="Converters\MarginConverter.cs" />
<Compile Include="Models\EnumFlagsVM.cs" />
<Compile Include="Models\ModModel\AnimeModel.cs" />
<Compile Include="Models\ModModel\AnimeTypeModel.cs" />
<Compile Include="Models\ModModel\ClickTextModel.cs" />
<Compile Include="Models\Expansions.cs" />
<Compile Include="Models\ModModel\FoodModel.cs" />

View File

@ -68,10 +68,16 @@ public class AnimeEditWindowVM
or GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Sleep
or GraphInfo.GraphType.Common
or GraphInfo.GraphType.Work
)
HasMultiType.Value = true;
if (model.GraphType.Value is GraphInfo.GraphType.Idel or GraphInfo.GraphType.Common)
if (
model.GraphType.Value
is GraphInfo.GraphType.Idel
or GraphInfo.GraphType.Common
or GraphInfo.GraphType.Work
)
HasAnimeName.Value = true;
}

View File

@ -72,6 +72,7 @@ public class AnimePageVM
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.Anime.Value.GraphType.Value = graphType;
vm.Anime.Value.Name.Value = selectGraphTypeWindow.AnimeName.Value;
window.ShowDialog();
if (window.IsCancel)
return;

View File

@ -3,6 +3,7 @@ using LinePutScript;
using LinePutScript.Converter;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using Panuon.WPF.UI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -189,8 +190,10 @@ public class ModMakerWindowVM
MessageBox.Show("模组载入失败".Translate());
return;
}
var pendingHandler = PendingBox.Show("载入中".Translate());
var modInfo = new ModInfoModel(mod);
EditMod(modInfo);
pendingHandler.Close();
}
catch (Exception ex)
{

View File

@ -91,6 +91,42 @@
<TextBlock Text="{ll:Str 动画类型}" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn
Binding="{Binding HappyAnimes.Count}"
CanUserSort="True"
IsReadOnly="True"
SortMemberPath="Id.Value">
<DataGridTextColumn.Header>
<TextBlock Text="{ll:Str 开心状态动画数量}" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn
Binding="{Binding NomalAnimes.Count}"
CanUserSort="True"
IsReadOnly="True"
SortMemberPath="Id.Value">
<DataGridTextColumn.Header>
<TextBlock Text="{ll:Str 普通状态动画数量}" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn
Binding="{Binding PoorConditionAnimes.Count}"
CanUserSort="True"
IsReadOnly="True"
SortMemberPath="Id.Value">
<DataGridTextColumn.Header>
<TextBlock Text="{ll:Str 不开心状态动画数量}" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn
Binding="{Binding IllAnimes.Count}"
CanUserSort="True"
IsReadOnly="True"
SortMemberPath="Id.Value">
<DataGridTextColumn.Header>
<TextBlock Text="{ll:Str 生病状态动画数量}" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<!--<DataGridTextColumn
Binding="{Binding LocateType.EnumValue.Value}"
CanUserSort="True"

View File

@ -20,7 +20,6 @@
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="当前只支持 Default 动画" />
<Grid
Grid.Row="1"
HorizontalAlignment="Center"
@ -29,11 +28,24 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="{ll:Str 动画类型}" />
<ComboBox
Grid.Column="1"
ItemsSource="{Binding GraphTypes}"
ItemsSource="{Binding GraphTypes.Value}"
SelectedItem="{Binding GraphType.Value}" />
<Label
Grid.Row="1"
Content="{ll:Str 动画名称}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToHiddenConverter}}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Text="{Binding AnimeName.Value, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToHiddenConverter}}" />
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>

View File

@ -29,6 +29,7 @@ public partial class SelectGraphTypeWindow : Window
InitializeComponent();
DataContext = this;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
GraphType.ValueChanged += GraphType_ValueChanged;
Closed += (s, e) =>
{
try
@ -39,22 +40,37 @@ public partial class SelectGraphTypeWindow : Window
};
}
private void GraphType_ValueChanged(GraphInfo.GraphType oldValue, GraphInfo.GraphType newValue)
{
if (newValue.IsHasNameAnime())
HasNameAnime.Value = true;
else
HasNameAnime.Value = false;
}
private void CurrentPet_ValueChanged(PetModel oldValue, PetModel newValue)
{
if (CurrentPet.Value.Animes.Count == 0)
{
GraphTypes.Value.Add(GraphInfo.GraphType.Default);
return;
}
GraphTypes.Value = new(
AnimeTypeModel.GraphTypes.Except(CurrentPet.Value.Animes.Select(m => m.GraphType.Value))
);
// 可添加多个项的类型
if (GraphTypes.Value.Contains(GraphInfo.GraphType.Common) is false)
GraphTypes.Value.Add(GraphInfo.GraphType.Common);
if (GraphTypes.Value.Contains(GraphInfo.GraphType.Work) is false)
GraphTypes.Value.Add(GraphInfo.GraphType.Work);
if (GraphTypes.Value.Contains(GraphInfo.GraphType.Move) is false)
GraphTypes.Value.Add(GraphInfo.GraphType.Move);
if (GraphTypes.Value.Contains(GraphInfo.GraphType.Idel) is false)
GraphTypes.Value.Add(GraphInfo.GraphType.Idel);
}
public ObservableValue<PetModel> CurrentPet { get; } = new();
public ObservableValue<GraphInfo.GraphType> GraphType { get; } = new();
public ObservableValue<ObservableCollection<GraphInfo.GraphType>> GraphTypes { get; } =
new(new());
public ObservableValue<string> AnimeName { get; } = new();
public ObservableValue<bool> HasNameAnime { get; } = new();
public bool IsCancel { get; private set; } = true;

View File

@ -216,7 +216,7 @@
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="ModEditWindow.MovePage.ViewModel.CurrentPet.Value.Animes.Count" />
<Binding Path="ModEditWindow.AnimePage.ViewModel.CurrentPet.Value.Animes.Count" />
</MultiBinding>
</TabItem.Header>
<Frame Content="{Binding ModEditWindow.AnimePage}" />