- 宠物动画延迟加载, 大幅提高启动性能
This commit is contained in:
Hakoyu 2024-04-18 21:55:17 +08:00
parent a3c15260b8
commit 7a2fa5c261
5 changed files with 159 additions and 84 deletions

View File

@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using VPet_Simulator.Core;
@ -22,10 +23,9 @@ public class AnimeModel : ObservableObjectX, ICloneable<AnimeModel>
var info = Path.GetFileNameWithoutExtension(file).Split(NativeUtils.Separator);
ID = info[0];
var duration = info.Last();
var imageModel = new ImageModel(
NativeUtils.LoadImageToMemoryStream(file),
int.Parse(duration)
);
if (int.TryParse(duration, out var result) is false)
result = 100;
var imageModel = new ImageModel(file, result);
Images.Add(imageModel);
}
}
@ -63,6 +63,14 @@ public class AnimeModel : ObservableObjectX, ICloneable<AnimeModel>
/// </summary>
public ObservableList<ImageModel> Images { get; } = new();
public void LoadAnime()
{
if (Images.HasValue() is false || Images.First().Image is not null)
return;
foreach (var image in Images)
image.LoadImage();
}
/// <summary>
/// 复制
/// </summary>

View File

@ -180,6 +180,18 @@ public class AnimeTypeModel : ObservableObjectX
}
}
public void LoadTypeAnime()
{
foreach (var anime in HappyAnimes)
anime.LoadAnime();
foreach (var anime in NomalAnimes)
anime.LoadAnime();
foreach (var anime in PoorConditionAnimes)
anime.LoadAnime();
foreach (var anime in IllAnimes)
anime.LoadAnime();
}
public void Close()
{
foreach (var anime in HappyAnimes)
@ -194,6 +206,7 @@ public class AnimeTypeModel : ObservableObjectX
public void Clear()
{
Close();
HappyAnimes.Clear();
NomalAnimes.Clear();
PoorConditionAnimes.Clear();
@ -435,14 +448,14 @@ public class AnimeTypeModel : ObservableObjectX
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
)
SaveDefault(path, this);
SaveDefault(path);
else if (
GraphType
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
)
SaveMultiType(path, this);
SaveMultiType(path);
else if (
GraphType
is GraphInfo.GraphType.Switch_Up
@ -450,55 +463,52 @@ public class AnimeTypeModel : ObservableObjectX
or GraphInfo.GraphType.Switch_Thirsty
or GraphInfo.GraphType.Switch_Hunger
)
SaveSwitch(path, this);
SaveSwitch(path);
else if (
GraphType is GraphInfo.GraphType.Raised_Dynamic or GraphInfo.GraphType.Raised_Static
)
SaveRaised(path, this);
SaveRaised(path);
else if (GraphType is GraphInfo.GraphType.StateONE or GraphInfo.GraphType.StateTWO)
SaveState(path, this);
SaveState(path);
else if (GraphType is GraphInfo.GraphType.Common)
SaveCommon(path, this);
SaveCommon(path);
else if (GraphType.IsHasNameAnime())
SaveHasNameAnime(path, this);
SaveHasNameAnime(path);
}
/// <summary>
/// 保存为带有名称的动画样式
/// </summary>
/// <param name="path">路径</param>
/// <param name="animeTypeModel">动画模型</param>
void SaveHasNameAnime(string path, AnimeTypeModel animeTypeModel)
void SaveHasNameAnime(string path)
{
var animeTypePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
var animeTypePath = Path.Combine(path, GraphType.ToString());
Directory.CreateDirectory(animeTypePath);
var animePath = Path.Combine(animeTypePath, animeTypeModel.Name);
var animePath = Path.Combine(animeTypePath, Name);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
SaveWithModeType(animePath);
}
/// <summary>
/// 保存为通用样式
/// </summary>
/// <param name="path">路径</param>
/// <param name="animeTypeModel">模型</param>
void SaveCommon(string path, AnimeTypeModel animeTypeModel)
void SaveCommon(string path)
{
var animePath = Path.Combine(path, animeTypeModel.Name);
var animePath = Path.Combine(path, Name);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
SaveWithModeType(animePath);
}
/// <summary>
/// 保存为 <see cref="GraphInfo.GraphType.StateONE"/> 或 <see cref="GraphInfo.GraphType.StateTWO"/> 样式
/// </summary>
/// <param name="path">路径</param>
/// <param name="animeTypeModel">模型</param>
void SaveState(string path, AnimeTypeModel animeTypeModel)
void SaveState(string path)
{
var animePath = Path.Combine(path, "State");
Directory.CreateDirectory(animePath);
SaveMultiType(animePath, animeTypeModel);
SaveMultiType(animePath);
}
/// <summary>
@ -506,14 +516,14 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="path">路径</param>
/// <param name="animeTypeModel">模型</param>
void SaveRaised(string path, AnimeTypeModel animeTypeModel)
void SaveRaised(string path)
{
var animePath = Path.Combine(path, "Raise");
Directory.CreateDirectory(animePath);
if (animeTypeModel.GraphType is GraphInfo.GraphType.Raised_Dynamic)
SaveDefault(animePath, animeTypeModel);
else if (animeTypeModel.GraphType is GraphInfo.GraphType.Raised_Static)
SaveMultiType(animePath, animeTypeModel);
if (GraphType is GraphInfo.GraphType.Raised_Dynamic)
SaveDefault(animePath);
else if (GraphType is GraphInfo.GraphType.Raised_Static)
SaveMultiType(animePath);
}
/// <summary>
@ -521,12 +531,12 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="path">路径</param>
/// <param name="animeTypeModel">模型</param>
void SaveSwitch(string path, AnimeTypeModel animeTypeModel)
void SaveSwitch(string path)
{
var animePath = Path.Combine(path, "Switch");
Directory.CreateDirectory(animePath);
var switchName = animeTypeModel.GraphType.ToString().Split(NativeUtils.Separator).Last();
SaveWithAnimeType(Path.Combine(animePath, switchName), animeTypeModel);
var switchName = GraphType.ToString().Split(NativeUtils.Separator).Last();
SaveWithAnimeType(Path.Combine(animePath, switchName));
}
/// <summary>
@ -534,11 +544,11 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveDefault(string path, AnimeTypeModel animeTypeModel)
void SaveDefault(string path)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
var animePath = Path.Combine(path, GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithAnimeType(animePath, animeTypeModel);
SaveWithAnimeType(animePath);
}
/// <summary>
@ -546,11 +556,11 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveMultiType(string path, AnimeTypeModel animeTypeModel)
void SaveMultiType(string path)
{
var animePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
var animePath = Path.Combine(path, GraphType.ToString());
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
SaveWithModeType(animePath);
}
/// <summary>
@ -558,27 +568,27 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="path"></param>
/// <param name="animeTypeModel"></param>
static void SaveWithModeType(string path, AnimeTypeModel animeTypeModel)
void SaveWithModeType(string path)
{
if (animeTypeModel.HappyAnimes.Count > 0)
if (HappyAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(ModeType.Happy));
SaveAnimes(modePath, animeTypeModel.HappyAnimes);
SaveAnimes(modePath, HappyAnimes);
}
if (animeTypeModel.NomalAnimes.Count > 0)
if (NomalAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(ModeType.Nomal));
SaveAnimes(modePath, animeTypeModel.NomalAnimes);
SaveAnimes(modePath, NomalAnimes);
}
if (animeTypeModel.PoorConditionAnimes.Count > 0)
if (PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(ModeType.PoorCondition));
SaveAnimes(modePath, animeTypeModel.PoorConditionAnimes);
SaveAnimes(modePath, PoorConditionAnimes);
}
if (animeTypeModel.IllAnimes.Count > 0)
if (IllAnimes.Count > 0)
{
var modePath = Path.Combine(path, nameof(ModeType.Ill));
SaveAnimes(modePath, animeTypeModel.IllAnimes);
SaveAnimes(modePath, IllAnimes);
}
static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
@ -619,27 +629,27 @@ public class AnimeTypeModel : ObservableObjectX
/// </summary>
/// <param name="animePath"></param>
/// <param name="animeType"></param>
static void SaveWithAnimeType(string animePath, AnimeTypeModel animeType)
void SaveWithAnimeType(string animePath)
{
if (animeType.HappyAnimes.Count > 0)
if (HappyAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(ModeType.Happy));
SaveAnimes(modePath, animeType.HappyAnimes);
SaveAnimes(modePath, HappyAnimes);
}
if (animeType.NomalAnimes.Count > 0)
if (NomalAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(ModeType.Nomal));
SaveAnimes(modePath, animeType.NomalAnimes);
SaveAnimes(modePath, NomalAnimes);
}
if (animeType.PoorConditionAnimes.Count > 0)
if (PoorConditionAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(ModeType.PoorCondition));
SaveAnimes(modePath, animeType.PoorConditionAnimes);
SaveAnimes(modePath, PoorConditionAnimes);
}
if (animeType.IllAnimes.Count > 0)
if (IllAnimes.Count > 0)
{
var modePath = Path.Combine(animePath, nameof(ModeType.Ill));
SaveAnimes(modePath, animeType.IllAnimes);
SaveAnimes(modePath, IllAnimes);
}
static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{
@ -659,9 +669,15 @@ public class AnimeTypeModel : ObservableObjectX
Directory.CreateDirectory(imagesPath);
foreach ((var index, var image) in model.Images.EnumerateIndex())
{
image.Image.SaveToPng(
Path.Combine(imagesPath, $"{model.ID}_{index:000}_{image.Duration}.png")
);
var path = Path.Combine(imagesPath, $"{model.ID}_{index:000}_{image.Duration}.png");
if (image.Image is not null)
{
image.Image.SaveToPng(path);
}
else if (Path.Exists(image.ImageFile))
{
File.Copy(image.ImageFile, path, true);
}
}
}
#endregion

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using LinePutScript;
using VPet_Simulator.Core;
@ -22,7 +23,6 @@ public class FoodAnimeModel : ObservableObjectX, ICloneable<FoodAnimeModel>
{
foreach (var item in line.Where(i => i.Name.StartsWith('a')))
{
//var index = int.Parse(item.Name.Substring(1));
var infos = item.Info.Split(',');
var foodLocationInfo = new FoodAnimeLocationModel();
foodLocationInfo.Duration = int.Parse(infos[0]);
@ -71,6 +71,20 @@ public class FoodAnimeModel : ObservableObjectX, ICloneable<FoodAnimeModel>
/// </summary>
public ObservableList<FoodAnimeLocationModel> FoodLocations { get; } = new();
public void LoadAnime()
{
if (BackImages.FirstOrDefault()?.Image is null)
{
foreach (var image in BackImages)
image.LoadImage();
}
if (FrontImages.FirstOrDefault()?.Image is null)
{
foreach (var image in FrontImages)
image.LoadImage();
}
}
/// <summary>
/// 复制
/// </summary>

View File

@ -43,7 +43,7 @@ public class FoodAnimeTypeModel : ObservableObjectX
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
private string _id = string.Empty;
public string ID
{
@ -54,7 +54,7 @@ public class FoodAnimeTypeModel : ObservableObjectX
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
private string _name = string.Empty;
/// <summary>
/// 名称
@ -91,6 +91,18 @@ public class FoodAnimeTypeModel : ObservableObjectX
/// </summary>
public ObservableList<FoodAnimeModel> IllAnimes { get; } = new();
public void LoadTypeAnime()
{
foreach (var anime in HappyAnimes)
anime.LoadAnime();
foreach (var anime in NomalAnimes)
anime.LoadAnime();
foreach (var anime in PoorConditionAnimes)
anime.LoadAnime();
foreach (var anime in IllAnimes)
anime.LoadAnime();
}
public void Close()
{
foreach (var anime in HappyAnimes)
@ -255,9 +267,9 @@ public class FoodAnimeTypeModel : ObservableObjectX
return new(
Directory
.EnumerateFiles(Path.Combine(path, pngAnimeInfo.Path))
.Select(i => new ImageModel(
NativeUtils.LoadImageToMemoryStream(i),
int.Parse(Path.GetFileNameWithoutExtension(i).Split('_')[2])
.Select(f => new ImageModel(
f,
int.Parse(Path.GetFileNameWithoutExtension(f).Split('_')[2])
))
);
}
@ -329,17 +341,29 @@ public class FoodAnimeTypeModel : ObservableObjectX
var backLayPath = Path.Combine(indexPath, BackLayName);
Directory.CreateDirectory(frontLayPath);
Directory.CreateDirectory(backLayPath);
foreach ((var index, var frontImage) in anime.FrontImages.EnumerateIndex())
foreach ((var index, var image) in anime.FrontImages.EnumerateIndex())
{
frontImage.Image.SaveToPng(
Path.Combine(frontLayPath, $"{anime.ID}_{index:000}_{frontImage.Duration}.png")
);
var path = Path.Combine(frontLayPath, $"{anime.ID}_{index:000}_{image.Duration}.png");
if (image.Image is not null)
{
image.Image.SaveToPng(path);
}
else if (Path.Exists(image.ImageFile))
{
File.Copy(image.ImageFile, path, true);
}
}
foreach ((var index, var backImage) in anime.BackImages.EnumerateIndex())
foreach ((var index, var image) in anime.BackImages.EnumerateIndex())
{
backImage.Image.SaveToPng(
Path.Combine(backLayPath, $"{anime.ID}_{backImage:000}_{backImage.Duration}.png")
);
var path = Path.Combine(backLayPath, $"{anime.ID}_{index:000}_{image.Duration}.png");
if (image.Image is not null)
{
image.Image.SaveToPng(path);
}
else if (Path.Exists(image.ImageFile))
{
File.Copy(image.ImageFile, path, true);
}
}
}
@ -384,16 +408,9 @@ public class FoodAnimeTypeModel : ObservableObjectX
}
}
public class PNGAnimeInfo
public class PNGAnimeInfo(string name, string path, IGameSave.ModeType mode)
{
public string Name { get; }
public string Path { get; }
public ModeType Mode { get; }
public PNGAnimeInfo(string name, string path, ModeType mode)
{
Name = name;
Path = path;
Mode = mode;
}
public string Name { get; } = name;
public string Path { get; } = path;
public ModeType Mode { get; } = mode;
}

View File

@ -15,12 +15,23 @@ namespace VPet.ModMaker.Models.ModModel;
/// </summary>
public class ImageModel : ObservableObjectX, ICloneable<ImageModel>
{
public ImageModel(string imageFile, int duration = 100)
{
ImageFile = imageFile;
Duration = duration;
}
public ImageModel(BitmapImage image, int duration = 100)
{
Image = image;
Duration = duration;
}
/// <summary>
/// 图片路径
/// </summary>
public string ImageFile { get; set; } = string.Empty;
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image = null!;
@ -48,9 +59,18 @@ public class ImageModel : ObservableObjectX, ICloneable<ImageModel>
set => SetProperty(ref _duration, value);
}
#endregion
public void LoadImage()
{
Image = NativeUtils.LoadImageToMemoryStream(ImageFile);
}
public ImageModel Clone()
{
var model = new ImageModel(Image.CloneStream(), Duration);
var model = new ImageModel(
Image?.CloneStream() ?? NativeUtils.LoadImageToMemoryStream(ImageFile),
Duration
);
return model;
}