食物保存与载入完成

This commit is contained in:
Hakoyu 2023-08-31 03:24:57 +08:00
parent 37b69b92a9
commit 30f272ad25
20 changed files with 195 additions and 66 deletions

4
.editorconfig Normal file
View File

@ -0,0 +1,4 @@
[*.cs]
# RCS1049: Simplify boolean comparison.
dotnet_diagnostic.RCS1049.severity = none

View File

@ -31,6 +31,12 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
LikeMax.Value = clickText.LikeMax.Value;
LikeMin.Value = clickText.LikeMin.Value;
DayTime.Value = clickText.DayTime.Value;
foreach (var item in clickText.I18nDatas)
{
I18nDatas[item.Key] = new();
I18nDatas[item.Key].Text.Value = clickText.I18nDatas[item.Key].Text.Value;
}
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
}
public ClickTextModel(ClickText clickText)

View File

@ -12,9 +12,8 @@ namespace VPet.ModMaker.Models;
public class FoodModel : I18nModel<I18nFoodModel>
{
public string Name { get; set; }
public string Description { get; set; }
public ObservableValue<string> Id { get; } = new();
public ObservableValue<string> Name { get; } = new();
public ObservableValue<string> Description { get; } = new();
public ObservableValue<Food.FoodType> Type { get; } = new();
public ObservableValue<double> Strength { get; } = new();
public ObservableValue<double> StrengthFood { get; } = new();
@ -31,7 +30,8 @@ public class FoodModel : I18nModel<I18nFoodModel>
public FoodModel(FoodModel food)
: this()
{
Id.Value = food.Id.Value;
Name.Value = food.Name.Value;
Description.Value = food.Description.Value;
Type.Value = food.Type.Value;
Strength.Value = food.Strength.Value;
StrengthFood.Value = food.StrengthFood.Value;
@ -42,13 +42,20 @@ public class FoodModel : I18nModel<I18nFoodModel>
Price.Value = food.Price.Value;
Exp.Value = food.Exp.Value;
Image.Value = Utils.LoadImageToStream(food.Image.Value);
foreach (var item in food.I18nDatas)
{
I18nDatas[item.Key] = new();
I18nDatas[item.Key].Name.Value = food.I18nDatas[item.Key].Name.Value;
I18nDatas[item.Key].Description.Value = food.I18nDatas[item.Key].Description.Value;
}
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
}
public FoodModel(Food food)
: this()
{
Name = food.Name;
Description = food.Desc;
Name.Value = food.Name;
Description.Value = food.Desc;
Type.Value = food.Type;
Strength.Value = food.Strength;
StrengthDrink.Value = food.StrengthDrink;
@ -64,9 +71,10 @@ public class FoodModel : I18nModel<I18nFoodModel>
public Food ToFood()
{
// 没有 Name 和 Description
return new Food()
{
Name = Name.Value,
Desc = $"{Name.Value}_{nameof(Description)}",
Type = Type.Value,
Strength = Strength.Value,
StrengthFood = StrengthFood.Value,

View File

@ -11,6 +11,8 @@ namespace VPet.ModMaker.Models;
public class I18nHelper
{
public static I18nHelper Current { get; set; } = new();
public ObservableValue<string> MainCulture { get; } = new();
public ObservableValue<string> CultureName { get; } = new();
public ObservableCollection<string> CultureNames { get; } = new();

View File

@ -25,6 +25,12 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
Mode.Value = lowText.Mode.Value;
Strength.Value = lowText.Strength.Value;
Like.Value = lowText.Like.Value;
foreach (var item in lowText.I18nDatas)
{
I18nDatas[item.Key] = item.Value;
I18nDatas[item.Key].Text.Value = lowText.I18nDatas[item.Key].Text.Value;
}
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
}
public LowTextModel(LowText lowText)
@ -40,7 +46,6 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
public LowText ToLowText()
{
// 没有 Text
return new()
{
Text = Text,

View File

@ -24,7 +24,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
public ObservableValue<string> Author { get; } = new();
public ObservableValue<string> GameVersion { get; } = new();
public ObservableValue<string> ModVersion { get; } = new();
public ObservableValue<BitmapImage> ModImage { get; } = new();
public ObservableValue<BitmapImage> Image { get; } = new();
public ObservableCollection<FoodModel> Foods { get; } = new();
public ObservableCollection<ClickTextModel> ClickTexts { get; } = new();
public ObservableCollection<LowTextModel> LowTexts { get; } = new();
@ -44,7 +44,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
ModVersion.Value = loader.Ver.ToString();
var imagePath = Path.Combine(loader.Path.FullName, "icon.png");
if (File.Exists(imagePath))
ModImage.Value = Utils.LoadImageToStream(imagePath);
Image.Value = Utils.LoadImageToStream(imagePath);
foreach (var food in loader.Foods)
Foods.Add(new(food));
foreach (var clickText in loader.ClickTexts)
@ -86,10 +86,25 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
new Sub("gamever", GameVersion.Value),
new Sub("ver", ModVersion.Value)
},
new Line("intro", Description.Value),
new Line("authorid", "0"),
new Line("itemid", "0"),
new Line("cachedate", DateTime.Now.Date.ToString())
};
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
lps.Add(
new Line("lang", cultureName)
{
new Sub(Name.Value, I18nDatas[cultureName].Name.Value),
new Sub(Description.Value, I18nDatas[cultureName].Description.Value),
}
);
}
var imagePath = Utils.GetImageSourceFile(Image.Value);
var targetImagePath = Path.Combine(path, Path.GetFileName(imagePath));
if (imagePath != targetImagePath)
File.Copy(imagePath, targetImagePath, true);
//lps.FindLine("vupmod").Info = Name.Value;
//lps.FindLine("intro").Info = Description.Value;
//lps.FindSub("gamever").Info = GameVersion.Value;
@ -100,6 +115,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.WriteAllText(modInfoFile, lps.ToString());
SaveFoods(path);
SaveLang(path);
SaveImage(path);
}
public void SaveFoods(string path)
@ -130,8 +146,30 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
var lps = new LPS();
foreach (var food in Foods)
{
lps.Add(new Line(food.Name, food.I18nDatas[cultureName].Name.Value));
lps.Add(new Line(food.Description, food.I18nDatas[cultureName].Description.Value));
lps.Add(new Line(food.Name.Value, food.I18nDatas[cultureName].Name.Value));
lps.Add(
new Line(food.Description.Value, food.I18nDatas[cultureName].Description.Value)
);
}
if (lps.Count > 0)
File.WriteAllText(cultureFile, lps.ToString());
}
}
public void SaveImage(string path)
{
var imagePath = Path.Combine(path, "image");
Directory.CreateDirectory(imagePath);
if (Foods.Count > 0)
{
var foodPath = Path.Combine(imagePath, "food");
Directory.CreateDirectory(foodPath);
foreach (var food in Foods)
{
var foodImagePath = Utils.GetImageSourceFile(food.Image.Value);
var targetImagePath = Path.Combine(foodPath, Path.GetFileName(foodImagePath));
if (foodImagePath != targetImagePath)
File.Copy(foodImagePath, targetImagePath, true);
}
}
}

View File

@ -14,10 +14,15 @@ namespace VPet.ModMaker.Models;
public class ModMaker : MainPlugin
{
public ILine Set;
public override string PluginName => "ModMaker";
public ModMakerWindow Maker;
public ModMaker(IMainWindow mainwin)
: base(mainwin) { }
public ILine Set;
public override void LoadPlugin()
{
@ -36,8 +41,6 @@ public class ModMaker : MainPlugin
modset.Items.Add(menuset);
}
public override string PluginName => "ModMaker";
public ModMakerWindow Maker;
public override void Setting()
{

View File

@ -8,5 +8,7 @@ namespace VPet.ModMaker.Models;
public static class ModMakerInfo
{
// TODO: 可修改的主要文化 ?
public const string MainCulture = "zh-Hans";
public const string BaseDirectory = nameof(ModMaker);
}

View File

@ -11,6 +11,11 @@ namespace VPet.ModMaker;
internal static class Utils
{
public static string GetImageSourceFile(BitmapImage image)
{
return ((FileStream)image.StreamSource).Name;
}
public static BitmapImage LoadImageToStream(string imagePath)
{
BitmapImage bitmapImage = new();
@ -22,7 +27,7 @@ internal static class Utils
public static BitmapImage LoadImageToStream(BitmapImage image)
{
return LoadImageToStream(((FileStream)image.StreamSource).Name);
return LoadImageToStream(GetImageSourceFile(image));
}
public static BitmapImage LoadImageToMemoryStream(string imagePath)
@ -39,7 +44,7 @@ internal static class Utils
public static BitmapImage LoadImageToMemoryStream(BitmapImage image)
{
return LoadImageToMemoryStream(((FileStream)image.StreamSource).Name);
return LoadImageToMemoryStream(GetImageSourceFile(image));
}
public static void ShowDialogX(this Window window, Window owner)

View File

@ -15,8 +15,7 @@ public class ClickTextPageVM
{
#region Value
public ObservableValue<ObservableCollection<ClickTextModel>> ShowClickTexts { get; } = new();
public ObservableCollection<ClickTextModel> ClickTexts { get; } =
new(ModInfoModel.Current.ClickTexts);
public ObservableCollection<ClickTextModel> ClickTexts => ModInfoModel.Current.ClickTexts;
public ObservableValue<string> FilterClickText { get; } = new();
#endregion
#region Command

View File

@ -17,7 +17,7 @@ public class FoodPageVM
{
#region Value
public ObservableValue<ObservableCollection<FoodModel>> ShowFoods { get; } = new();
public ObservableCollection<FoodModel> Foods { get; } = new(ModInfoModel.Current.Foods);
public ObservableCollection<FoodModel> Foods => ModInfoModel.Current.Foods;
public ObservableValue<string> FilterFoodText { get; } = new();
#endregion
#region Command

View File

@ -19,8 +19,7 @@ public class LowTextPageVM
#region Value
public ObservableValue<string> FilterLowText { get; } = new();
public ObservableValue<ObservableCollection<LowTextModel>> ShowLowTexts { get; } = new();
public ObservableCollection<LowTextModel> LowTexts { get; } =
new(ModInfoModel.Current.LowTexts);
public ObservableCollection<LowTextModel> LowTexts => ModInfoModel.Current.LowTexts;
#endregion
#region Command
public ObservableCommand AddLowTextCommand { get; } = new();

View File

@ -55,9 +55,9 @@ public class ModEditWindowVM
foreach (var food in ModInfo.Value.Foods)
{
var foodI18n = food.I18nDatas[i18n.Key];
if (i18n.Value.TryGetValue(food.Name, out var i18nName))
if (i18n.Value.TryGetValue(food.Name.Value, out var i18nName))
foodI18n.Name.Value = i18nName;
if (i18n.Value.TryGetValue(food.Description, out var i18nDescription))
if (i18n.Value.TryGetValue(food.Description.Value, out var i18nDescription))
foodI18n.Description.Value = i18nDescription;
}
foreach (var lowText in ModInfo.Value.LowTexts)
@ -117,7 +117,7 @@ public class ModEditWindowVM
public void Close()
{
ModInfo.Value.ModImage.Value?.StreamSource?.Close();
ModInfo.Value.Image.Value?.StreamSource?.Close();
}
private void AddImage()
@ -126,7 +126,7 @@ public class ModEditWindowVM
new() { Title = "选择图片", Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp" };
if (openFileDialog.ShowDialog() is true)
{
ModInfo.Value.ModImage.Value = Utils.LoadImageToStream(openFileDialog.FileName);
ModInfo.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName);
}
}
@ -136,8 +136,8 @@ public class ModEditWindowVM
new() { Title = "选择图片", Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp" };
if (openFileDialog.ShowDialog() is true)
{
ModInfo.Value.ModImage.Value?.StreamSource?.Close();
ModInfo.Value.ModImage.Value = Utils.LoadImageToStream(openFileDialog.FileName);
ModInfo.Value.Image.Value?.StreamSource?.Close();
ModInfo.Value.Image.Value = Utils.LoadImageToStream(openFileDialog.FileName);
}
}
@ -172,7 +172,21 @@ public class ModEditWindowVM
private void Save()
{
return;
if (string.IsNullOrEmpty(ModInfo.Value.SourcePath.Value))
{
MessageBox.Show("源路径为空, 请使用 保存至");
return;
}
try
{
ModInfo.Value.SaveTo(Path.GetDirectoryName(ModInfo.Value.SourcePath.Value));
}
catch (Exception ex)
{
MessageBox.Show($"保存失败 错误信息:\n{ex}");
return;
}
MessageBox.Show("保存成功");
}
private void SaveTo()
@ -182,12 +196,21 @@ public class ModEditWindowVM
{
Title = "保存 模组信息文件,并在文件夹内保存模组数据",
Filter = $"LPS文件|*.lps;",
DefaultExt = "info.lps"
FileName = "info.lps"
};
if (saveFileDialog.ShowDialog() is true)
{
ModInfo.Value.SaveTo(Path.GetDirectoryName(saveFileDialog.FileName));
try
{
ModInfo.Value.SaveTo(Path.GetDirectoryName(saveFileDialog.FileName));
ModInfo.Value.SourcePath.Value = saveFileDialog.FileName;
}
catch (Exception ex)
{
MessageBox.Show($"保存失败 错误信息:\n{ex}");
return;
}
}
return;
MessageBox.Show("保存成功");
}
}

View File

@ -1,4 +1,5 @@
using HKW.HKWViewModels.SimpleObservable;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -6,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views;
using VPet.ModMaker.Views.ModEdit;
@ -14,17 +16,20 @@ namespace VPet.ModMaker.ViewModels;
public class ModMakerWindowVM
{
#region Value
public ModMakerWindow ModMakerWindow { get; }
public ModEditWindow ModEditWindow { get; private set; }
public ObservableCommand CreateNewModCommand { get; set; } = new();
public ObservableValue<string> ModFilterText { get; } = new();
public ObservableCollection<ModInfoModel> ShowMods { get; set; }
public ObservableCollection<ModInfoModel> Mods { get; } = new();
#endregion
#region Command
public ObservableCommand CreateNewModCommand { get; } = new();
public ObservableCommand LoadModFromFileCommand { get; } = new();
#endregion
public ModMakerWindowVM() { }
public ModMakerWindowVM(ModMakerWindow window)
@ -33,6 +38,7 @@ public class ModMakerWindowVM
ModMakerWindow = window;
ShowMods = Mods;
CreateNewModCommand.ExecuteAction = CreateNewMod;
LoadModFromFileCommand.ExecuteAction = LoadModFromFile;
ModFilterText.ValueChanged += ModFilterText_ValueChanged;
}
@ -46,8 +52,6 @@ public class ModMakerWindowVM
continue;
var modModel = new ModInfoModel(mod);
Mods.Add(modModel);
if (mod.OtherI18nDatas.Count == 0)
continue;
}
}
@ -70,4 +74,34 @@ public class ModMakerWindowVM
ModMakerWindow.Close();
};
}
public void LoadModFromFile()
{
OpenFileDialog openFileDialog =
new()
{
Title = "模组信息文件",
Filter = $"LPS文件|*.lps;",
FileName = "info.lps"
};
if (openFileDialog.ShowDialog() is true)
{
try
{
var path = Path.GetDirectoryName(openFileDialog.FileName);
var mod = new ModLoader(new DirectoryInfo(path));
if (mod.SuccessLoad is false)
{
MessageBox.Show("模组载入失败");
return;
}
ModInfoModel.Current = new ModInfoModel(mod);
CreateNewMod();
}
catch (Exception ex)
{
MessageBox.Show($"模组载入失败:\n{ex}");
}
}
}
}

View File

@ -68,7 +68,7 @@
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="Id"
Text="{Binding Food.Value.Id.Value}" />
Text="{Binding Food.Value.Name.Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Content="食物类型:" />
<ComboBox
x:Name="ComboBox_FoodType"
@ -81,13 +81,13 @@
Grid.Row="2"
Grid.Column="1"
pu:TextBoxHelper.Watermark="食物名称"
Text="{Binding Food.Value.CurrentI18nData.Value.Name.Value}" />
Text="{Binding Food.Value.CurrentI18nData.Value.Name.Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="3" Content="食物描述:" />
<TextBox
Grid.Row="3"
Grid.Column="1"
pu:TextBoxHelper.Watermark="食物描述"
Text="{Binding Food.Value.CurrentI18nData.Value.Description.Value}" />
Text="{Binding Food.Value.CurrentI18nData.Value.Description.Value, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</ScrollViewer>
</Grid>

View File

@ -46,11 +46,11 @@ public partial class FoodEditWindow : Window
private void Button_Yes_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.Food.Value.Id.Value))
{
MessageBox.Show("Id不可为空", "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
//if (string.IsNullOrEmpty(ViewModel.Food.Value.Id.Value))
//{
// MessageBox.Show("Id不可为空", "", MessageBoxButton.OK, MessageBoxImage.Warning);
// return;
//}
if (ViewModel.Food.Value.CurrentI18nData.Value.Name.Value is null)
{
MessageBox.Show("名称不可为空", "", MessageBoxButton.OK, MessageBoxImage.Warning);
@ -61,7 +61,7 @@ public partial class FoodEditWindow : Window
MessageBox.Show("图像不可为空", "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (ModInfoModel.Current.Foods.Any(i => i.Id.Value == ViewModel.Food.Value.Id.Value))
if (ModInfoModel.Current.Foods.Any(i => i.Name == ViewModel.Food.Value.Name))
{
MessageBox.Show("此Id已存在", "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

@ -57,7 +57,7 @@
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Id.Value}"
Binding="{Binding Name.Value}"
CanUserSort="True"
IsReadOnly="True"
SortMemberPath="Name">

View File

@ -57,7 +57,7 @@
x:Name="Image_ModImage"
Width="256"
Height="256"
Source="{Binding ModInfo.Value.ModImage.Value}"
Source="{Binding ModInfo.Value.Image.Value}"
Stretch="Uniform">
<Image.ContextMenu>
<ContextMenu>
@ -78,7 +78,7 @@
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="Button">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding ModInfo.Value.ModImage.Value}" Value="{x:Null}">
<DataTrigger Binding="{Binding ModInfo.Value.Image.Value}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>

View File

@ -51,28 +51,18 @@ public partial class ModEditWindow : Window
private void ClickTexts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ClickTextPage.ViewModel.ClickTexts.CollectionChanged += (s, e) =>
{
TabItem_ClickText.Header =
$"{TabItem_ClickText.Tag} ({ClickTextPage.ViewModel.ClickTexts.Count})";
};
TabItem_ClickText.Header =
$"{TabItem_ClickText.Tag} ({ClickTextPage.ViewModel.ClickTexts.Count})";
}
private void LowTexts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
LowTextPage.ViewModel.LowTexts.CollectionChanged += (s, e) =>
{
TabItem_LowText.Header =
$"{TabItem_LowText.Tag} ({LowTextPage.ViewModel.LowTexts.Count})";
};
TabItem_LowText.Header = $"{TabItem_LowText.Tag} ({LowTextPage.ViewModel.LowTexts.Count})";
}
private void Foods_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
FoodPage.ViewModel.Foods.CollectionChanged += (s, e) =>
{
TabItem_Food.Header = $"{TabItem_Food.Tag} ({FoodPage.ViewModel.Foods.Count})";
};
TabItem_Food.Header = $"{TabItem_Food.Tag} ({FoodPage.ViewModel.Foods.Count})";
}
private void Window_ModEdit_Closed(object sender, EventArgs e)

View File

@ -46,14 +46,21 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Width="64" Source="{Binding ModImage.Value}" />
<Image Width="64" Source="{Binding Image.Value}" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock d:Text="Mod名称" Text="{Binding Id.Value}" />
<TextBlock Grid.Row="1" d:Text="Mod描述" />
<TextBlock
d:Text="Mod名称"
Text="{Binding Name.Value}"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="1"
d:Text="Mod描述"
Text="{Binding Description.Value}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</ControlTemplate>
@ -74,6 +81,10 @@
x:Name="Button_CreateNewMod"
Command="{Binding CreateNewModCommand}"
Content="创建新的模组" />
<Button
x:Name="Button_OpenFromFile"
Command="{Binding LoadModFromFileCommand}"
Content="从文件中载入" />
</StackPanel>
</Grid>
</Grid>