mirror of
https://github.com/LorisYounger/VPet.ModMaker.git
synced 2024-08-30 18:22:21 +00:00
更新
This commit is contained in:
parent
179c62e0df
commit
19203ead6c
@ -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<TKey, TValue>(
|
||||
this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
|
@ -11,17 +11,15 @@ 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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ public class I18nModel<T>
|
||||
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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
|
||||
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<I18nFoodModel>
|
||||
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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
|
||||
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<I18nModInfoModel>
|
||||
}
|
||||
);
|
||||
}
|
||||
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<I18nModInfoModel>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -67,6 +67,7 @@
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -284,7 +284,7 @@
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Button Command="{Binding AddCultureCommand}" Content="{ll:Str 添加语言}" />
|
||||
<Button Command="{Binding AddCultureCommand}" Content="{ll:Str 添加文化}" />
|
||||
<ListBox
|
||||
x:Name="ListBox_Cultures"
|
||||
Grid.Row="1"
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.Win32;
|
||||
using LinePutScript.Localization.WPF;
|
||||
using Microsoft.Win32;
|
||||
using Panuon.WPF;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -16,6 +17,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using VPet.ModMaker.Models;
|
||||
using VPet.ModMaker.ViewModels.ModEdit;
|
||||
using VPet.ModMaker.Views.ModEdit.AnimeEdit;
|
||||
using VPet.ModMaker.Views.ModEdit.ClickTextEdit;
|
||||
@ -48,10 +50,23 @@ public partial class ModEditWindow : Window
|
||||
{
|
||||
InitializeComponent();
|
||||
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();
|
||||
try
|
||||
|
@ -108,53 +108,4 @@
|
||||
</StackPanel>
|
||||
</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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user