This commit is contained in:
Hakoyu
2023-09-26 16:05:39 +08:00
parent 179c62e0df
commit 19203ead6c
19 changed files with 122 additions and 129 deletions

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -16,10 +18,10 @@ public static class Extensions
return source.IndexOf(value, comparisonType) >= 0; return source.IndexOf(value, comparisonType) >= 0;
} }
public static string GetSourceFile(this BitmapImage image) //public static string GetSourceFile(this BitmapImage image)
{ //{
return ((FileStream)image.StreamSource).Name; // return ((FileStream)image.StreamSource).Name;
} //}
public static void CloseStream(this ImageSource source) 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<TKey, TValue>( public static bool TryAdd<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary, this IDictionary<TKey, TValue> dictionary,
TKey key, TKey key,

View File

@ -11,17 +11,15 @@ namespace VPet.ModMaker.Models;
public class I18nHelper public class I18nHelper
{ {
public static I18nHelper Current { get; set; } = new(); public static I18nHelper Current { get; set; } = new();
public ObservableValue<string> MainCulture { get; } = new();
public ObservableValue<string> CultureName { get; } = new(); public ObservableValue<string> CultureName { get; } = new();
public ObservableCollection<string> CultureNames { get; } = new(); public ObservableCollection<string> CultureNames { get; } = new();
public I18nHelper() public I18nHelper()
{ {
CultureNames.CollectionChanged += Langs_CollectionChanged; CultureNames.CollectionChanged += Cultures_CollectionChanged;
} }
private void Langs_CollectionChanged( private void Cultures_CollectionChanged(
object sender, object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e System.Collections.Specialized.NotifyCollectionChangedEventArgs e
) )
@ -29,25 +27,25 @@ public class I18nHelper
// 替换 // 替换
if (e.NewStartingIndex == e.OldStartingIndex) 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; return;
} }
// 删除 // 删除
if (e.OldItems is not null) if (e.OldItems is not null)
{ {
RemoveLang?.Invoke((string)e.OldItems[0]); RemoveCulture?.Invoke((string)e.OldItems[0]);
} }
// 新增 // 新增
if (e.NewItems is not null) if (e.NewItems is not null)
{ {
AddLang?.Invoke((string)e.NewItems[0]); AddCulture?.Invoke((string)e.NewItems[0]);
} }
} }
public event LangEventHandler AddLang; public event CultureEventHandler AddCulture;
public event LangEventHandler RemoveLang; public event CultureEventHandler RemoveCulture;
public event ReplaceLangEventHandler ReplaceLang; public event ReplaceCultureEventHandler ReplaceCulture;
public delegate void LangEventHandler(string lang); public delegate void CultureEventHandler(string culture);
public delegate void ReplaceLangEventHandler(string oldLang, string newLang); public delegate void ReplaceCultureEventHandler(string oldCulture, string newCulture);
} }

View File

@ -16,9 +16,9 @@ public class I18nModel<T>
public I18nModel() public I18nModel()
{ {
I18nHelper.Current.CultureName.ValueChanged += LangChanged; I18nHelper.Current.CultureName.ValueChanged += LangChanged;
I18nHelper.Current.AddLang += AddLang; I18nHelper.Current.AddCulture += AddLang;
I18nHelper.Current.RemoveLang += RemoveLang; I18nHelper.Current.RemoveCulture += RemoveLang;
I18nHelper.Current.ReplaceLang += ReplaceLang; I18nHelper.Current.ReplaceCulture += ReplaceLang;
if (I18nHelper.Current.CultureNames.Count == 0) if (I18nHelper.Current.CultureNames.Count == 0)
return; return;
foreach (var item in I18nHelper.Current.CultureNames) foreach (var item in I18nHelper.Current.CultureNames)

View File

@ -507,13 +507,11 @@ public class AnimeTypeModel
var imageIndex = 0; var imageIndex = 0;
foreach (var image in model.Images) foreach (var image in model.Images)
{ {
File.Copy( image.Image.Value.SaveToPng(
image.Image.Value.GetSourceFile(),
Path.Combine( Path.Combine(
imagesPath, imagesPath,
$"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png" $"{model.Id.Value}_{imageIndex:000}_{image.Duration.Value}.png"
), )
true
); );
imageIndex++; imageIndex++;
} }
@ -537,7 +535,10 @@ public class AnimeModel
var info = Path.GetFileNameWithoutExtension(file).Split(Utils.Separator); var info = Path.GetFileNameWithoutExtension(file).Split(Utils.Separator);
Id.Value = info[0]; Id.Value = info[0];
var duration = info.Last(); 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); Images.Add(imageModel);
} }
} }
@ -548,7 +549,7 @@ public class AnimeModel
model.Id.Value = Id.Value; model.Id.Value = Id.Value;
model.AnimeType.Value = AnimeType.Value; model.AnimeType.Value = AnimeType.Value;
foreach (var image in Images) foreach (var image in Images)
model.Images.Add(image); model.Images.Add(image.Copy());
return model; return model;
} }

View File

@ -54,7 +54,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
Likability.Value = model.Likability.Value; Likability.Value = model.Likability.Value;
Price.Value = model.Price.Value; Price.Value = model.Price.Value;
Exp.Value = model.Exp.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) foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy(); I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value]; CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
@ -76,7 +76,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
Price.Value = food.Price; Price.Value = food.Price;
Exp.Value = food.Exp; Exp.Value = food.Exp;
if (File.Exists(food.Image)) if (File.Exists(food.Image))
Image.Value = Utils.LoadImageToStream(food.Image); Image.Value = Utils.LoadImageToMemoryStream(food.Image);
} }
public Food ToFood() public Food ToFood()

View File

@ -21,10 +21,7 @@ public class ImageModel
public ImageModel Copy() public ImageModel Copy()
{ {
var model = new ImageModel( var model = new ImageModel(Image.Value, Duration.Value);
Utils.LoadImageToStream(Image.Value.GetSourceFile()),
Duration.Value
);
return model; return model;
} }

View File

@ -65,7 +65,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
AuthorID = loader.AuthorID; AuthorID = loader.AuthorID;
var imagePath = Path.Combine(loader.ModPath.FullName, "icon.png"); var imagePath = Path.Combine(loader.ModPath.FullName, "icon.png");
if (File.Exists(imagePath)) if (File.Exists(imagePath))
Image.Value = Utils.LoadImageToStream(imagePath); Image.Value = Utils.LoadImageToMemoryStream(imagePath);
foreach (var food in loader.Foods) foreach (var food in loader.Foods)
Foods.Add(new(food)); Foods.Add(new(food));
foreach (var clickText in loader.ClickTexts) foreach (var clickText in loader.ClickTexts)
@ -260,13 +260,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
} }
); );
} }
if (Image.Value is not null) Image.Value?.SaveToPng(Path.Combine(path, "icon.png"));
{
var imagePath = Image.Value.GetSourceFile();
var targetImagePath = Path.Combine(path, Path.GetFileName(imagePath));
if (imagePath != targetImagePath)
File.Copy(imagePath, targetImagePath, true);
}
File.WriteAllText(modInfoFile, lps.ToString()); File.WriteAllText(modInfoFile, lps.ToString());
SavePets(path); SavePets(path);
SaveFoods(path); SaveFoods(path);
@ -548,13 +542,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
Directory.CreateDirectory(foodPath); Directory.CreateDirectory(foodPath);
foreach (var food in Foods) foreach (var food in Foods)
{ {
var foodImagePath = food.Image.Value.GetSourceFile(); food.Image.Value.SaveToPng(Path.Combine(foodPath, food.Id.Value));
var targetImagePath = Path.Combine(
foodPath,
$"{food.Id.Value}{Path.GetExtension(foodImagePath)}"
);
if (foodImagePath != targetImagePath)
File.Copy(foodImagePath, targetImagePath, true);
} }
} }
} }

View File

@ -15,21 +15,21 @@ public static class Utils
public const int DecodePixelHeight = 250; public const int DecodePixelHeight = 250;
public static char[] Separator { get; } = new char[] { '_' }; public static char[] Separator { get; } = new char[] { '_' };
public static BitmapImage LoadImageToStream(string imagePath) //public static BitmapImage LoadImageToStream(string imagePath)
{ //{
BitmapImage bitmapImage = new(); // BitmapImage bitmapImage = new();
bitmapImage.BeginInit(); // bitmapImage.BeginInit();
bitmapImage.DecodePixelWidth = DecodePixelWidth; // bitmapImage.DecodePixelWidth = DecodePixelWidth;
try // try
{ // {
bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream; // bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream;
} // }
finally // finally
{ // {
bitmapImage.EndInit(); // bitmapImage.EndInit();
} // }
return bitmapImage; // return bitmapImage;
} //}
public static BitmapImage LoadImageToMemoryStream(string imagePath) public static BitmapImage LoadImageToMemoryStream(string imagePath)
{ {

View File

@ -67,6 +67,7 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />

View File

@ -137,7 +137,7 @@ public class AnimeEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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)) if (File.Exists(path))
{ {
model.Images.Add(new(Utils.LoadImageToStream(path))); model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
} }
else if (Directory.Exists(path)) else if (Directory.Exists(path))
{ {
foreach (var file in Directory.EnumerateFiles(path, "*.png")) foreach (var file in Directory.EnumerateFiles(path, "*.png"))
{ {
model.Images.Add(new(Utils.LoadImageToStream(path))); model.Images.Add(new(Utils.LoadImageToMemoryStream(path)));
} }
} }
} }

View File

@ -48,7 +48,7 @@ public class FoodEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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) if (openFileDialog.ShowDialog() is true)
{ {
Food.Value.Image.Value?.StreamSource?.Close(); Food.Value.Image.Value?.StreamSource?.Close();
Food.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); Food.Value.Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName);
} }
} }
} }

View File

@ -14,6 +14,7 @@ using VPet.ModMaker.Views.ModEdit;
using System.Windows; using System.Windows;
using System.IO; using System.IO;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
namespace VPet.ModMaker.ViewModels.ModEdit; namespace VPet.ModMaker.ViewModels.ModEdit;
@ -77,7 +78,7 @@ public class ModEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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) if (openFileDialog.ShowDialog() is true)
{ {
ModInfo.Value.Image.Value?.StreamSource?.Close(); 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(); var window = new AddCultureWindow();
window.ShowDialog(); window.ShowDialog();
@ -163,19 +164,22 @@ public class ModEditWindowVM
}; };
if (saveFileDialog.ShowDialog() is true) if (saveFileDialog.ShowDialog() is true)
{ {
var pending = PendingBox.Show("保存中".Translate());
try try
{ {
var path = Path.GetDirectoryName(saveFileDialog.FileName); var path = Path.GetDirectoryName(saveFileDialog.FileName);
ModInfo.Value.SaveTo(path); ModInfo.Value.SaveTo(path);
if (string.IsNullOrWhiteSpace(ModInfo.Value.SourcePath.Value)) if (string.IsNullOrWhiteSpace(ModInfo.Value.SourcePath.Value))
ModInfo.Value.SourcePath.Value = path; ModInfo.Value.SourcePath.Value = path;
pending.Close();
MessageBox.Show(ModEditWindow, "保存成功".Translate());
} }
catch (Exception ex) catch (Exception ex)
{ {
pending.Close();
MessageBox.Show($"保存失败 错误信息:\n{0}".Translate(ex)); MessageBox.Show($"保存失败 错误信息:\n{0}".Translate(ex));
return; return;
} }
MessageBox.Show("保存成功".Translate());
} }
} }

View File

@ -52,7 +52,7 @@ public class MoveEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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) if (openFileDialog.ShowDialog() is true)
{ {
Image.Value?.StreamSource?.Close(); Image.Value?.StreamSource?.Close();
Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName);
} }
} }
} }

View File

@ -52,7 +52,7 @@ public class PetEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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) if (openFileDialog.ShowDialog() is true)
{ {
Image.Value?.StreamSource?.Close(); Image.Value?.StreamSource?.Close();
Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName);
} }
} }
} }

View File

@ -53,7 +53,7 @@ public class WorkEditWindowVM
}; };
if (openFileDialog.ShowDialog() is true) 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) if (openFileDialog.ShowDialog() is true)
{ {
Image.Value?.StreamSource?.Close(); Image.Value?.StreamSource?.Close();
Image.Value = Utils.LoadImageToStream(openFileDialog.FileName); Image.Value = Utils.LoadImageToMemoryStream(openFileDialog.FileName);
} }
} }
} }

View File

@ -146,6 +146,11 @@ public class ModMakerWindowVM
private void ClearHistories() private void ClearHistories()
{ {
if (
MessageBox.Show("确定要清空吗?".Translate(), "", MessageBoxButton.YesNo)
is not MessageBoxResult.Yes
)
return;
ShowHistories.Value.Clear(); ShowHistories.Value.Clear();
Histories.Clear(); Histories.Clear();
File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty); File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty);

View File

@ -284,7 +284,7 @@
<RowDefinition /> <RowDefinition />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Command="{Binding AddCultureCommand}" Content="{ll:Str 添加语言}" /> <Button Command="{Binding AddCultureCommand}" Content="{ll:Str 添加文化}" />
<ListBox <ListBox
x:Name="ListBox_Cultures" x:Name="ListBox_Cultures"
Grid.Row="1" Grid.Row="1"

View File

@ -1,4 +1,5 @@
using Microsoft.Win32; using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using Panuon.WPF; using Panuon.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -16,6 +17,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.ModMaker.Models;
using VPet.ModMaker.ViewModels.ModEdit; using VPet.ModMaker.ViewModels.ModEdit;
using VPet.ModMaker.Views.ModEdit.AnimeEdit; using VPet.ModMaker.Views.ModEdit.AnimeEdit;
using VPet.ModMaker.Views.ModEdit.ClickTextEdit; using VPet.ModMaker.Views.ModEdit.ClickTextEdit;
@ -48,10 +50,23 @@ public partial class ModEditWindow : Window
{ {
InitializeComponent(); InitializeComponent();
DataContext = new ModEditWindowVM(this); DataContext = new ModEditWindowVM(this);
Closed += Window_ModEdit_Closed; Closed += ModEditWindow_Closed;
Loaded += ModEditWindow_Loaded;
} }
private void Window_ModEdit_Closed(object sender, EventArgs e) private void ModEditWindow_Loaded(object sender, RoutedEventArgs e)
{
if (I18nHelper.Current.CultureNames.Count == 0)
{
if (
MessageBox.Show("未添加任何文化,确定要添加文化吗?".Translate(), "", MessageBoxButton.YesNo)
is MessageBoxResult.Yes
)
ViewModel.AddCulture();
}
}
private void ModEditWindow_Closed(object sender, EventArgs e)
{ {
ViewModel.Close(); ViewModel.Close();
try try

View File

@ -108,53 +108,4 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>
<!--<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
<RowDefinition Height="8*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Label
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="{x:Null}"
Content="{ll:Str Mod制作器}"
FontSize="24" />
<Label
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="{x:Null}"
Content="{ll:Str 打开最近制作的MOD}" />
<ListBox
Grid.Row="2"
Grid.RowSpan="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Background="{DynamicResource PrimaryLighter}"
FontSize="20" />
<Button
Grid.Row="4"
Grid.Column="2"
Grid.ColumnSpan="1"
VerticalAlignment="Center"
Content="{ll:Str 创建新MOD}"
Style="{DynamicResource ThemedButtonStyle}" />
<TextBox
Grid.Row="4"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 'MOD名称(英文)'}"
Style="{DynamicResource StandardTextBoxStyle}" />
</Grid>-->
</Window> </Window>