diff --git a/VPet.ModMaker/Models/Expansions.cs b/VPet.ModMaker/Models/Expansions.cs index 2660206..7e67544 100644 --- a/VPet.ModMaker/Models/Expansions.cs +++ b/VPet.ModMaker/Models/Expansions.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; @@ -16,10 +18,10 @@ public static class Extensions return source.IndexOf(value, comparisonType) >= 0; } - public static string GetSourceFile(this BitmapImage image) - { - return ((FileStream)image.StreamSource).Name; - } + //public static string GetSourceFile(this BitmapImage image) + //{ + // return ((FileStream)image.StreamSource).Name; + //} public static void CloseStream(this ImageSource source) { @@ -29,6 +31,37 @@ public static class Extensions } } + public static BitmapImage Copy(this BitmapImage image) + { + BitmapImage newImage = new(); + newImage.BeginInit(); + newImage.DecodePixelWidth = image.DecodePixelWidth; + newImage.DecodePixelHeight = image.DecodePixelHeight; + try + { + using var bitmap = new Bitmap(image.StreamSource); + var ms = new MemoryStream(); + bitmap.Save(ms, ImageFormat.Png); + image.StreamSource.CopyTo(ms); + newImage.StreamSource = ms; + } + finally + { + newImage.EndInit(); + } + return newImage; + } + + public static void SaveToPng(this BitmapSource image, string path) + { + if (path.EndsWith(".png") is false) + path += ".png"; + var encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(image)); + using var fs = new FileStream(path, FileMode.Create); + encoder.Save(fs); + } + public static bool TryAdd( this IDictionary dictionary, TKey key, diff --git a/VPet.ModMaker/Models/I18nHelper.cs b/VPet.ModMaker/Models/I18nHelper.cs index 21f3d5a..71718b7 100644 --- a/VPet.ModMaker/Models/I18nHelper.cs +++ b/VPet.ModMaker/Models/I18nHelper.cs @@ -11,17 +11,15 @@ namespace VPet.ModMaker.Models; public class I18nHelper { public static I18nHelper Current { get; set; } = new(); - - public ObservableValue MainCulture { get; } = new(); public ObservableValue CultureName { get; } = new(); public ObservableCollection CultureNames { get; } = new(); public I18nHelper() { - CultureNames.CollectionChanged += Langs_CollectionChanged; + CultureNames.CollectionChanged += Cultures_CollectionChanged; } - private void Langs_CollectionChanged( + private void Cultures_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) @@ -29,25 +27,25 @@ public class I18nHelper // 替换 if (e.NewStartingIndex == e.OldStartingIndex) { - ReplaceLang?.Invoke((string)e.OldItems[0], (string)e.NewItems[0]); + ReplaceCulture?.Invoke((string)e.OldItems[0], (string)e.NewItems[0]); return; } // 删除 if (e.OldItems is not null) { - RemoveLang?.Invoke((string)e.OldItems[0]); + RemoveCulture?.Invoke((string)e.OldItems[0]); } // 新增 if (e.NewItems is not null) { - AddLang?.Invoke((string)e.NewItems[0]); + AddCulture?.Invoke((string)e.NewItems[0]); } } - public event LangEventHandler AddLang; - public event LangEventHandler RemoveLang; - public event ReplaceLangEventHandler ReplaceLang; + public event CultureEventHandler AddCulture; + public event CultureEventHandler RemoveCulture; + public event ReplaceCultureEventHandler ReplaceCulture; - public delegate void LangEventHandler(string lang); - public delegate void ReplaceLangEventHandler(string oldLang, string newLang); + public delegate void CultureEventHandler(string culture); + public delegate void ReplaceCultureEventHandler(string oldCulture, string newCulture); } diff --git a/VPet.ModMaker/Models/I18nModel.cs b/VPet.ModMaker/Models/I18nModel.cs index 9964387..82f039c 100644 --- a/VPet.ModMaker/Models/I18nModel.cs +++ b/VPet.ModMaker/Models/I18nModel.cs @@ -16,9 +16,9 @@ public class I18nModel public I18nModel() { I18nHelper.Current.CultureName.ValueChanged += LangChanged; - I18nHelper.Current.AddLang += AddLang; - I18nHelper.Current.RemoveLang += RemoveLang; - I18nHelper.Current.ReplaceLang += ReplaceLang; + I18nHelper.Current.AddCulture += AddLang; + I18nHelper.Current.RemoveCulture += RemoveLang; + I18nHelper.Current.ReplaceCulture += ReplaceLang; if (I18nHelper.Current.CultureNames.Count == 0) return; foreach (var item in I18nHelper.Current.CultureNames) diff --git a/VPet.ModMaker/Models/ModModel/AnimeModel.cs b/VPet.ModMaker/Models/ModModel/AnimeModel.cs index 04056d1..c523bbd 100644 --- a/VPet.ModMaker/Models/ModModel/AnimeModel.cs +++ b/VPet.ModMaker/Models/ModModel/AnimeModel.cs @@ -507,13 +507,11 @@ public class AnimeTypeModel var imageIndex = 0; foreach (var image in model.Images) { - File.Copy( - image.Image.Value.GetSourceFile(), + image.Image.Value.SaveToPng( Path.Combine( imagesPath, $"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png" - ), - true + ) ); imageIndex++; } @@ -537,7 +535,10 @@ public class AnimeModel 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)); + var imageModel = new ImageModel( + Utils.LoadImageToMemoryStream(file), + int.Parse(duration) + ); Images.Add(imageModel); } } @@ -548,7 +549,7 @@ public class AnimeModel model.Id.Value = Id.Value; model.AnimeType.Value = AnimeType.Value; foreach (var image in Images) - model.Images.Add(image); + model.Images.Add(image.Copy()); return model; } diff --git a/VPet.ModMaker/Models/ModModel/FoodModel.cs b/VPet.ModMaker/Models/ModModel/FoodModel.cs index 8f884e7..a0e7a27 100644 --- a/VPet.ModMaker/Models/ModModel/FoodModel.cs +++ b/VPet.ModMaker/Models/ModModel/FoodModel.cs @@ -54,7 +54,7 @@ public class FoodModel : I18nModel Likability.Value = model.Likability.Value; Price.Value = model.Price.Value; Exp.Value = model.Exp.Value; - Image.Value = Utils.LoadImageToStream(model.Image.Value.GetSourceFile()); + Image.Value = model.Image.Value; foreach (var item in model.I18nDatas) I18nDatas[item.Key] = item.Value.Copy(); CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value]; @@ -76,7 +76,7 @@ public class FoodModel : I18nModel Price.Value = food.Price; Exp.Value = food.Exp; if (File.Exists(food.Image)) - Image.Value = Utils.LoadImageToStream(food.Image); + Image.Value = Utils.LoadImageToMemoryStream(food.Image); } public Food ToFood() diff --git a/VPet.ModMaker/Models/ModModel/ImageModel.cs b/VPet.ModMaker/Models/ModModel/ImageModel.cs index 8ecbf46..507fba0 100644 --- a/VPet.ModMaker/Models/ModModel/ImageModel.cs +++ b/VPet.ModMaker/Models/ModModel/ImageModel.cs @@ -21,10 +21,7 @@ public class ImageModel public ImageModel Copy() { - var model = new ImageModel( - Utils.LoadImageToStream(Image.Value.GetSourceFile()), - Duration.Value - ); + var model = new ImageModel(Image.Value, Duration.Value); return model; } diff --git a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs index 3cb8b83..6aa533e 100644 --- a/VPet.ModMaker/Models/ModModel/ModInfoModel.cs +++ b/VPet.ModMaker/Models/ModModel/ModInfoModel.cs @@ -65,7 +65,7 @@ public class ModInfoModel : I18nModel AuthorID = loader.AuthorID; var imagePath = Path.Combine(loader.ModPath.FullName, "icon.png"); if (File.Exists(imagePath)) - Image.Value = Utils.LoadImageToStream(imagePath); + Image.Value = Utils.LoadImageToMemoryStream(imagePath); foreach (var food in loader.Foods) Foods.Add(new(food)); foreach (var clickText in loader.ClickTexts) @@ -260,13 +260,7 @@ public class ModInfoModel : I18nModel } ); } - if (Image.Value is not null) - { - var imagePath = Image.Value.GetSourceFile(); - var targetImagePath = Path.Combine(path, Path.GetFileName(imagePath)); - if (imagePath != targetImagePath) - File.Copy(imagePath, targetImagePath, true); - } + Image.Value?.SaveToPng(Path.Combine(path, "icon.png")); File.WriteAllText(modInfoFile, lps.ToString()); SavePets(path); SaveFoods(path); @@ -548,13 +542,7 @@ public class ModInfoModel : I18nModel Directory.CreateDirectory(foodPath); foreach (var food in Foods) { - var foodImagePath = food.Image.Value.GetSourceFile(); - var targetImagePath = Path.Combine( - foodPath, - $"{food.Id.Value}{Path.GetExtension(foodImagePath)}" - ); - if (foodImagePath != targetImagePath) - File.Copy(foodImagePath, targetImagePath, true); + food.Image.Value.SaveToPng(Path.Combine(foodPath, food.Id.Value)); } } } diff --git a/VPet.ModMaker/Models/Utils.cs b/VPet.ModMaker/Models/Utils.cs index 5dc97ef..0edccfc 100644 --- a/VPet.ModMaker/Models/Utils.cs +++ b/VPet.ModMaker/Models/Utils.cs @@ -15,21 +15,21 @@ public static class Utils public const int DecodePixelHeight = 250; public static char[] Separator { get; } = new char[] { '_' }; - public static BitmapImage LoadImageToStream(string imagePath) - { - BitmapImage bitmapImage = new(); - bitmapImage.BeginInit(); - bitmapImage.DecodePixelWidth = DecodePixelWidth; - try - { - bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream; - } - finally - { - bitmapImage.EndInit(); - } - return bitmapImage; - } + //public static BitmapImage LoadImageToStream(string imagePath) + //{ + // BitmapImage bitmapImage = new(); + // bitmapImage.BeginInit(); + // bitmapImage.DecodePixelWidth = DecodePixelWidth; + // try + // { + // bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream; + // } + // finally + // { + // bitmapImage.EndInit(); + // } + // return bitmapImage; + //} public static BitmapImage LoadImageToMemoryStream(string imagePath) { diff --git a/VPet.ModMaker/VPet.ModMaker.csproj b/VPet.ModMaker/VPet.ModMaker.csproj index 348deec..69d15ba 100644 --- a/VPet.ModMaker/VPet.ModMaker.csproj +++ b/VPet.ModMaker/VPet.ModMaker.csproj @@ -67,6 +67,7 @@ + diff --git a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs index 172a5d4..9859c8f 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/AnimeEdit/AnimeEditWindowVM.cs @@ -137,7 +137,7 @@ public class AnimeEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - value.Images.Add(new(Utils.LoadImageToStream(openFileDialog.FileName))); + value.Images.Add(new(Utils.LoadImageToMemoryStream(openFileDialog.FileName))); } } @@ -149,13 +149,13 @@ public class AnimeEditWindowVM { if (File.Exists(path)) { - model.Images.Add(new(Utils.LoadImageToStream(path))); + model.Images.Add(new(Utils.LoadImageToMemoryStream(path))); } else if (Directory.Exists(path)) { foreach (var file in Directory.EnumerateFiles(path, "*.png")) { - model.Images.Add(new(Utils.LoadImageToStream(path))); + model.Images.Add(new(Utils.LoadImageToMemoryStream(path))); } } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/FoodEdit/FoodEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/FoodEdit/FoodEditWindowVM.cs index 71de35a..be8623f 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/FoodEdit/FoodEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/FoodEdit/FoodEditWindowVM.cs @@ -48,7 +48,7 @@ public class FoodEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - Food.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Food.Value.Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } @@ -63,7 +63,7 @@ public class FoodEditWindowVM if (openFileDialog.ShowDialog() is true) { Food.Value.Image.Value?.StreamSource?.Close(); - Food.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Food.Value.Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/ModEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/ModEditWindowVM.cs index faa2afb..b91086d 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/ModEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/ModEditWindowVM.cs @@ -14,6 +14,7 @@ using VPet.ModMaker.Views.ModEdit; using System.Windows; using System.IO; using LinePutScript.Localization.WPF; +using Panuon.WPF.UI; namespace VPet.ModMaker.ViewModels.ModEdit; @@ -77,7 +78,7 @@ public class ModEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - ModInfo.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + ModInfo.Value.Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } @@ -92,11 +93,11 @@ public class ModEditWindowVM if (openFileDialog.ShowDialog() is true) { ModInfo.Value.Image.Value?.StreamSource?.Close(); - ModInfo.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + ModInfo.Value.Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } - private void AddCulture() + public void AddCulture() { var window = new AddCultureWindow(); window.ShowDialog(); @@ -163,19 +164,22 @@ public class ModEditWindowVM }; if (saveFileDialog.ShowDialog() is true) { + var pending = PendingBox.Show("保存中".Translate()); try { var path = Path.GetDirectoryName(saveFileDialog.FileName); ModInfo.Value.SaveTo(path); if (string.IsNullOrWhiteSpace(ModInfo.Value.SourcePath.Value)) ModInfo.Value.SourcePath.Value = path; + pending.Close(); + MessageBox.Show(ModEditWindow, "保存成功".Translate()); } catch (Exception ex) { + pending.Close(); MessageBox.Show($"保存失败 错误信息:\n{0}".Translate(ex)); return; } - MessageBox.Show("保存成功".Translate()); } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs index 038dd5f..a42adeb 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/MoveEdit/MoveEditWindowVM.cs @@ -52,7 +52,7 @@ public class MoveEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } @@ -67,7 +67,7 @@ public class MoveEditWindowVM if (openFileDialog.ShowDialog() is true) { Image.Value?.StreamSource?.Close(); - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs index ed14508..7467ddf 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/PetEdit/PetEditWindowVM.cs @@ -52,7 +52,7 @@ public class PetEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } @@ -67,7 +67,7 @@ public class PetEditWindowVM if (openFileDialog.ShowDialog() is true) { Image.Value?.StreamSource?.Close(); - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } } diff --git a/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs b/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs index 8d4a24b..63d192d 100644 --- a/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModEdit/WorkEdit/WorkEditWindowVM.cs @@ -53,7 +53,7 @@ public class WorkEditWindowVM }; if (openFileDialog.ShowDialog() is true) { - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } @@ -68,7 +68,7 @@ public class WorkEditWindowVM if (openFileDialog.ShowDialog() is true) { Image.Value?.StreamSource?.Close(); - Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); + Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName); } } } diff --git a/VPet.ModMaker/ViewModels/ModMakerWindowVM.cs b/VPet.ModMaker/ViewModels/ModMakerWindowVM.cs index f8d3051..7a8f400 100644 --- a/VPet.ModMaker/ViewModels/ModMakerWindowVM.cs +++ b/VPet.ModMaker/ViewModels/ModMakerWindowVM.cs @@ -146,6 +146,11 @@ public class ModMakerWindowVM private void ClearHistories() { + if ( + MessageBox.Show("确定要清空吗?".Translate(), "", MessageBoxButton.YesNo) + is not MessageBoxResult.Yes + ) + return; ShowHistories.Value.Clear(); Histories.Clear(); File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty); diff --git a/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml b/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml index 6b4db9a..8e3bd9e 100644 --- a/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml +++ b/VPet.ModMaker/Views/ModEdit/ModEditWindow.xaml @@ -284,7 +284,7 @@ -