- 完全重构
- 添加版本升级提示(109->11000)
This commit is contained in:
Hakoyu 2024-03-29 23:46:32 +08:00
parent 75951b92d6
commit 0fe086bd8b
67 changed files with 1808 additions and 1453 deletions

View File

@ -12,6 +12,9 @@
<c:EqualsMultiConverter x:Key="EqualsConverter" />
<c:EqualsMultiConverter x:Key="NotEqualsConverter" IsInverted="True" />
<c:NullToBoolConverter x:Key="NullToFalseConverter" />
<c:AllBoolToVisibilityMultiConverter x:Key="AllTrueToCollapsedConverter" />
<c:AllBoolToVisibilityMultiConverter
x:Key="AllTrueToCollapsedConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<c:BoolInverteConverter x:Key="BoolInverter" />
</ResourceDictionary>

View File

@ -32,5 +32,5 @@ public class I18nData : ObservableObjectX<I18nData>
/// <summary>
/// 基于 <see cref="I18nHelper.Current.CultureNames"/> 的索引的数据列表
/// </summary>
public ObservableCollection<ObservableValue<string>> Datas { get; } = new();
public ObservableList<ObservableValue<string>> Datas { get; } = new();
}

View File

@ -12,23 +12,23 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// 模组制作历史
/// </summary>
public class ModMakeHistory
public class ModMakeHistory : IEquatable<ModMakeHistory>
{
/// <summary>
/// 图片
/// </summary>
public BitmapImage Image { get; set; }
public BitmapImage? Image { get; set; }
/// <summary>
/// Id
/// </summary>
[Line(ignoreCase: true)]
public string Id { get; set; }
public string ID { get; set; } = string.Empty;
/// <summary>
/// 路径
/// </summary>
private string _path;
private string _path = string.Empty;
/// <summary>
/// 资源路径
@ -56,4 +56,20 @@ public class ModMakeHistory
/// </summary>
[Line(ignoreCase: true)]
public DateTime LastTime { get; set; } = DateTime.Now;
public bool Equals(ModMakeHistory? other)
{
return SourcePath.Equals(other?.SourcePath);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return Equals(obj as ModMakeHistory);
}
public override int GetHashCode()
{
return SourcePath.GetHashCode();
}
}

View File

@ -17,7 +17,7 @@ public class ModMaker : MainPlugin
//public ILine Set;
public override string PluginName => "ModMaker";
public ModMakerWindow Maker;
public ModMakerWindow Maker = null!;
public ModMaker(IMainWindow mainwin)
: base(mainwin) { }
@ -61,8 +61,8 @@ public class ModMaker : MainPlugin
}
}
private void Maker_Closed(object sender, EventArgs e)
private void Maker_Closed(object? sender, EventArgs e)
{
Maker = null;
Maker = null!;
}
}

View File

@ -10,16 +10,34 @@ namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 动画模型
/// </summary>
public class AnimeModel : ObservableObjectX<AnimeModel>
public class AnimeModel : ObservableObjectX<AnimeModel>, ICloneable<AnimeModel>
{
#region Id
public AnimeModel() { }
public AnimeModel(string imagesPath)
: this()
{
foreach (var file in Directory.EnumerateFiles(imagesPath))
{
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)
);
Images.Add(imageModel);
}
}
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public string Id
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
@ -43,40 +61,24 @@ public class AnimeModel : ObservableObjectX<AnimeModel>
/// <summary>
/// 图像列表
/// </summary>
public ObservableCollection<ImageModel> Images { get; } = new();
public AnimeModel() { }
public AnimeModel(string imagesPath)
: this()
{
foreach (var file in Directory.EnumerateFiles(imagesPath))
{
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)
);
Images.Add(imageModel);
}
}
public ObservableList<ImageModel> Images { get; } = new();
/// <summary>
/// 复制
/// </summary>
/// <returns></returns>
public AnimeModel Copy()
public AnimeModel Clone()
{
var model = new AnimeModel();
model.Id = Id;
model.ID = ID;
model.AnimeType = AnimeType;
foreach (var image in Images)
model.Images.Add(image.Copy());
model.Images.Add(image.Clone());
return model;
}
object ICloneable.Clone() => Clone();
/// <summary>
/// 关闭所有图像流
/// </summary>

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -16,64 +18,94 @@ namespace VPet.ModMaker.Models.ModModel;
public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
{
public AnimeTypeModel()
{
PropertyChanged += AnimeTypeModel_PropertyChanged;
}
private void AnimeTypeModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Name))
{
ID = $"{GraphType}_{Name}";
}
}
public AnimeTypeModel(AnimeTypeModel model)
: this()
{
ID = model.ID;
Name = model.Name;
GraphType = model.GraphType;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Clone());
foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Clone());
foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Clone());
foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Clone());
}
/// <summary>
/// 动作类型
/// </summary>
public static ObservableCollection<GraphInfo.GraphType> GraphTypes { get; } =
new(Enum.GetValues<GraphInfo.GraphType>());
public static FrozenSet<GraphInfo.GraphType> GraphTypes { get; } =
Enum.GetValues<GraphInfo.GraphType>().ToFrozenSet();
/// <summary>
/// 动画类型
/// </summary>
public static ObservableCollection<GraphInfo.AnimatType> AnimatTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.AnimatType)).Cast<GraphInfo.AnimatType>());
public static FrozenSet<GraphInfo.AnimatType> AnimatTypes { get; } =
Enum.GetValues<GraphInfo.AnimatType>().ToFrozenSet();
/// <summary>
/// 模式类型
/// </summary>
public static ObservableCollection<ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(ModeType)).Cast<ModeType>());
public static FrozenSet<ModeType> ModeTypes { get; } = Enum.GetValues<ModeType>().ToFrozenSet();
/// <summary>
/// 含有名称的动作列表
/// </summary>
public static HashSet<GraphInfo.GraphType> HasNameAnimes { get; } =
new()
{
GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say
};
public static FrozenSet<GraphInfo.GraphType> HasNameAnimes { get; } =
FrozenSet.ToFrozenSet(
[
GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say
]
);
/// <summary>
/// 含有不同动画类型的动作列表
/// </summary>
public static HashSet<GraphInfo.GraphType> HasMultiTypeAnimes { get; } =
new()
{
GraphInfo.GraphType.Touch_Head,
GraphInfo.GraphType.Touch_Body,
GraphInfo.GraphType.Sleep,
GraphInfo.GraphType.Raised_Static,
GraphInfo.GraphType.StateONE,
GraphInfo.GraphType.StateTWO,
GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say
};
public static FrozenSet<GraphInfo.GraphType> HasMultiTypeAnimes { get; } =
FrozenSet.ToFrozenSet(
[
GraphInfo.GraphType.Touch_Head,
GraphInfo.GraphType.Touch_Body,
GraphInfo.GraphType.Sleep,
GraphInfo.GraphType.Raised_Static,
GraphInfo.GraphType.StateONE,
GraphInfo.GraphType.StateTWO,
GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say
]
);
#region Id
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public string Id
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
@ -82,7 +114,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
private string _name = string.Empty;
/// <summary>
/// 名称
@ -96,61 +128,37 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
#region GraphType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GraphInfo.GraphType _GraphType;
private GraphInfo.GraphType _graphType;
/// <summary>
/// 动作类型
/// </summary>
public GraphInfo.GraphType GraphType
{
get => _GraphType;
set => SetProperty(ref _GraphType, value);
get => _graphType;
set => SetProperty(ref _graphType, value);
}
#endregion
/// <summary>
/// 开心动画
/// </summary>
public ObservableCollection<AnimeModel> HappyAnimes { get; } = new();
public ObservableList<AnimeModel> HappyAnimes { get; } = new();
/// <summary>
/// 普通动画 (默认)
/// </summary>
public ObservableCollection<AnimeModel> NomalAnimes { get; } = new();
public ObservableList<AnimeModel> NomalAnimes { get; } = new();
/// <summary>
/// 低状态动画
/// </summary>
public ObservableCollection<AnimeModel> PoorConditionAnimes { get; } = new();
public ObservableList<AnimeModel> PoorConditionAnimes { get; } = new();
/// <summary>
/// 生病动画
/// </summary>
public ObservableCollection<AnimeModel> IllAnimes { get; } = new();
public AnimeTypeModel()
{ //TODO
//Name.ValueChanged += (_, _) =>
//{
// Id.Value = $"{GraphType.Value}_{Name.Value}";
//};
}
public AnimeTypeModel(AnimeTypeModel model)
: this()
{
Id = model.Id;
Name = model.Name;
GraphType = model.GraphType;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Copy());
foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Copy());
foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Copy());
}
public ObservableList<AnimeModel> IllAnimes { get; } = new();
/// <summary>
/// 创建动画类型模型
@ -196,9 +204,9 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
Name = Path.GetFileName(path);
// 为带有名字的类型设置Id
if (graphType.IsHasNameAnime())
Id = $"{graphType}_{Name}";
ID = $"{graphType}_{Name}";
else
Id = graphType.ToString();
ID = graphType.ToString();
GraphType = graphType;
if (
graphType
@ -389,7 +397,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
/// <param name="path">路径</param>
/// <param name="animatType">动画类型</param>
private static void AddAnime(
ObservableCollection<AnimeModel> collection,
ObservableList<AnimeModel> collection,
string path,
GraphInfo.AnimatType animatType = AnimatType.Single
)
@ -572,7 +580,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
SaveAnimes(modePath, animeTypeModel.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes)
static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{
Directory.CreateDirectory(animePath);
var countA = 0;
@ -632,7 +640,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
var modePath = Path.Combine(animePath, nameof(ModeType.Ill));
SaveAnimes(modePath, animeType.IllAnimes);
}
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes)
static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{
Directory.CreateDirectory(animePath);
foreach (var anime in animes.EnumerateIndex())
@ -651,7 +659,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
foreach (var image in model.Images.EnumerateIndex())
{
image.Value.Image.SaveToPng(
Path.Combine(imagesPath, $"{model.Id}_{image.Index:000}_{image.Value.Duration}.png")
Path.Combine(imagesPath, $"{model.ID}_{image.Index:000}_{image.Value.Duration}.png")
);
}
}

View File

@ -11,8 +11,12 @@ namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 食物图像位置模型
/// </summary>
public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel>
public class FoodAnimeLocationModel
: ObservableObjectX<FoodAnimeLocationModel>,
ICloneable<FoodAnimeLocationModel>
{
public FoodAnimeLocationModel() { }
#region Duration
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _duration;
@ -30,7 +34,7 @@ public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel>
/// <summary>
/// 范围
/// </summary>
public ObservableRectangleLocation<double> Rect { get; set; } = new();
public ObservableRectangleLocation<double> RectangleLocation { get; set; } = new();
/// <summary>
/// 旋转角度
@ -59,27 +63,27 @@ public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel>
set => SetProperty(ref _opacity, value);
}
#endregion
public FoodAnimeLocationModel()
public FoodAnimeLocationModel Clone()
{
Rect.PropertyChangedX += (s, e) =>
var model = new FoodAnimeLocationModel
{
Rect.Height = (int)e.NewValue;
Duration = Duration,
RectangleLocation = new(
RectangleLocation.X,
RectangleLocation.Y,
RectangleLocation.Width,
RectangleLocation.Width
),
Rotate = Rotate,
Opacity = Opacity
};
}
public FoodAnimeLocationModel Copy()
{
var model = new FoodAnimeLocationModel();
model.Duration = Duration;
model.Rect = new(Rect.X, Rect.Y, Rect.Width, Rect.Height);
model.Rotate = Rotate;
model.Opacity = Opacity;
return model;
}
object ICloneable.Clone() => Clone();
public override string ToString()
{
return $"{Duration}, {Rect.X}, {Rect.Y}, {Rect.Width}, {Rotate}, {Opacity}";
return $"{Duration}, {RectangleLocation.X}, {RectangleLocation.Y}, {RectangleLocation.Width}, {Rotate}, {Opacity}";
}
}

View File

@ -13,42 +13,14 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>
public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>, ICloneable<FoodAnimeModel>
{
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _Id;
public string Id
{
get => _Id;
set => SetProperty(ref _Id, value);
}
#endregion
public ObservableValue<ModeType> Mode { get; }
/// <summary>
/// 后图像列表
/// </summary>
public ObservableCollection<ImageModel> BackImages { get; set; } = new();
/// <summary>
/// 前图像列表
/// </summary>
public ObservableCollection<ImageModel> FrontImages { get; set; } = new();
/// <summary>
/// 食物定位列表
/// </summary>
public ObservableCollection<FoodAnimeLocationModel> FoodLocations { get; } = new();
public FoodAnimeModel() { }
public FoodAnimeModel(ILine line)
: this()
{
foreach (var item in line.Where(i => i.Name.StartsWith("a")))
foreach (var item in line.Where(i => i.Name.StartsWith('a')))
{
//var index = int.Parse(item.Name.Substring(1));
var infos = item.Info.Split(',');
@ -56,7 +28,7 @@ public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>
foodLocationInfo.Duration = int.Parse(infos[0]);
if (infos.Length > 1)
{
foodLocationInfo.Rect = new(
foodLocationInfo.RectangleLocation = new(
double.Parse(infos[1]),
double.Parse(infos[2]),
double.Parse(infos[3]),
@ -71,23 +43,53 @@ public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>
}
}
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
public ObservableValue<ModeType> Mode { get; }
/// <summary>
/// 后图像列表
/// </summary>
public ObservableList<ImageModel> BackImages { get; set; } = new();
/// <summary>
/// 前图像列表
/// </summary>
public ObservableList<ImageModel> FrontImages { get; set; } = new();
/// <summary>
/// 食物定位列表
/// </summary>
public ObservableList<FoodAnimeLocationModel> FoodLocations { get; } = new();
/// <summary>
/// 复制
/// </summary>
/// <returns></returns>
public FoodAnimeModel Copy()
public FoodAnimeModel Clone()
{
var model = new FoodAnimeModel();
model.Id = Id;
model.ID = ID;
foreach (var image in FrontImages)
model.FrontImages.Add(image.Copy());
model.FrontImages.Add(image.Clone());
foreach (var image in BackImages)
model.BackImages.Add(image.Copy());
model.BackImages.Add(image.Clone());
foreach (var foodLocation in FoodLocations)
model.FoodLocations.Add(foodLocation.Copy());
model.FoodLocations.Add(foodLocation.Clone());
return model;
}
object ICloneable.Clone() => Clone();
/// <summary>
/// 关闭所有图像流
/// </summary>

View File

@ -17,6 +17,8 @@ namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
{
public FoodAnimeTypeModel() { }
/// <summary>
/// 动作类型
/// </summary>
@ -38,11 +40,11 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
/// </summary>
public const string BackLayName = "back_lay";
#region Id
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
public string Id
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
@ -59,37 +61,34 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
set
{
if (SetProperty(ref _name, value) is false)
return;
ID = $"{GraphType}_{Name}";
}
}
#endregion
/// <summary>
/// 开心动画
/// </summary>
public ObservableCollection<FoodAnimeModel> HappyAnimes { get; } = new();
public ObservableList<FoodAnimeModel> HappyAnimes { get; } = new();
/// <summary>
/// 普通动画 (默认)
/// </summary>
public ObservableCollection<FoodAnimeModel> NomalAnimes { get; } = new();
public ObservableList<FoodAnimeModel> NomalAnimes { get; } = new();
/// <summary>
/// 低状态动画
/// </summary>
public ObservableCollection<FoodAnimeModel> PoorConditionAnimes { get; } = new();
public ObservableList<FoodAnimeModel> PoorConditionAnimes { get; } = new();
/// <summary>
/// 生病动画
/// </summary>
public ObservableCollection<FoodAnimeModel> IllAnimes { get; } = new();
public FoodAnimeTypeModel()
{ //TODO
//Name.ValueChanged += (_, _) =>
//{
// Id.Value = $"{GraphType}_{Name.Value}";
//};
}
public ObservableList<FoodAnimeModel> IllAnimes { get; } = new();
public void Close()
{
@ -131,16 +130,16 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public FoodAnimeTypeModel(FoodAnimeTypeModel model)
: this()
{
Id = model.Id;
ID = model.ID;
Name = model.Name;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
HappyAnimes.Add(anime.Clone());
foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Copy());
NomalAnimes.Add(anime.Clone());
foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Copy());
PoorConditionAnimes.Add(anime.Clone());
foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Copy());
IllAnimes.Add(anime.Clone());
}
/// <summary>
@ -217,7 +216,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public void AddModeAnime(
string path,
ModeType mode,
ObservableCollection<FoodAnimeModel> foodAnimes,
ObservableList<FoodAnimeModel> foodAnimes,
ILine line,
List<PNGAnimeInfo> pngAnimeInfos
)
@ -250,7 +249,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
}
foodAnimes.Add(anime);
static ObservableCollection<ImageModel> GetImages(string path, PNGAnimeInfo pngAnimeInfo)
static ObservableList<ImageModel> GetImages(string path, PNGAnimeInfo pngAnimeInfo)
{
return new(
Directory
@ -299,7 +298,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
/// <param name="mode">模式</param>
private void SaveAnimeInfo(
string animePath,
ObservableCollection<FoodAnimeModel> animes,
ObservableList<FoodAnimeModel> animes,
ModeType mode
)
{
@ -334,7 +333,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
frontImage.Value.Image.SaveToPng(
Path.Combine(
frontLayPath,
$"{anime.Id}_{frontImage.Index:000}_{frontImage.Value.Duration}.png"
$"{anime.ID}_{frontImage.Index:000}_{frontImage.Value.Duration}.png"
)
);
}
@ -343,7 +342,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
backImage.Value.Image.SaveToPng(
Path.Combine(
backLayPath,
$"{anime.Id}_{backImage.Index:000}_{backImage.Value.Duration}.png"
$"{anime.ID}_{backImage.Index:000}_{backImage.Value.Duration}.png"
)
);
}

View File

@ -25,25 +25,6 @@ public class FoodModel : I18nModel<I18nFoodModel>
{
public FoodModel()
{
//DescriptionId = $"{Id}_{nameof(DescriptionId)}";
//TODO
//Id.ValueChanged += (s, e) =>
//{
// DescriptionId.Value = $"{e.NewValue}_{nameof(DescriptionId)}";
//};
//ReferencePrice.AddNotifySender(
// Strength,
// StrengthFood,
// StrengthDrink,
// Feeling,
// Health,
// Likability,
// Exp
//);
//ReferencePrice.SenderPropertyChanged += (s, _) =>
//{
// s.Value = Math.Floor(SetValueToFood(_food).RealPrice);
//};
PropertyChangedX += FoodModel_PropertyChangedX;
}
@ -64,11 +45,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
PropertyChangedXEventArgs e
)
{
if (e.PropertyName == nameof(ID))
{
DescriptionID = $"{e.NewValue}_{nameof(DescriptionID)}";
}
else if (_notifyReferencePrice.Contains(e.PropertyName))
if (e.PropertyName is not null && _notifyReferencePrice.Contains(e.PropertyName))
{
this.Adapt(_food);
ReferencePrice = Math.Floor(_food.RealPrice);
@ -96,7 +73,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
/// <summary>
/// 食物类型
/// </summary>
public static ObservableCollection<Food.FoodType> FoodTypes { get; } =
public static ObservableList<Food.FoodType> FoodTypes { get; } =
new(Enum.GetValues(typeof(Food.FoodType)).Cast<Food.FoodType>());
#region ID

View File

@ -13,11 +13,17 @@ namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 图像模型
/// </summary>
public class ImageModel : ObservableObjectX<ImageModel>
public class ImageModel : ObservableObjectX<ImageModel>, ICloneable<ImageModel>
{
public ImageModel(BitmapImage image, int duration = 100)
{
Image = image;
Duration = duration;
}
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
private BitmapImage _image = null!;
/// <summary>
/// 图像
@ -42,19 +48,14 @@ public class ImageModel : ObservableObjectX<ImageModel>
set => SetProperty(ref _duration, value);
}
#endregion
public ImageModel(BitmapImage image, int duration = 100)
{
Image = image;
Duration = duration;
}
public ImageModel Copy()
public ImageModel Clone()
{
var model = new ImageModel(Image.CloneStream(), Duration);
return model;
}
object ICloneable.Clone() => Clone();
public void Close()
{
Image?.CloseStream();

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -26,6 +27,29 @@ namespace VPet.ModMaker.Models;
/// </summary>
public class ModInfoModel : I18nModel<I18nModInfoModel>
{
public ModInfoModel()
{
PropertyChanged += ModInfoModel_PropertyChanged;
Pets.CollectionChanged += Pets_CollectionChanged;
}
private void ModInfoModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ID))
{
DescriptionID = $"{ID}_{nameof(DescriptionID)}";
}
else if (e.PropertyName == nameof(ShowMainPet))
{
Pets_CollectionChanged(null, null!);
}
}
/// <summary>
/// 当前
/// </summary>
public static ModInfoModel Current { get; set; } = new();
#region AutoSetFoodPrice
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _autoSetFoodPrice;
@ -65,33 +89,28 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public ulong ItemID { get; }
/// <summary>
/// 当前
/// </summary>
public static ModInfoModel Current { get; set; } = new();
#region Id
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public string Id
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region DescriptionId
#region DescriptionID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId = string.Empty;
/// <summary>
/// 描述Id
/// </summary>
public string DescriptionId
public string DescriptionID
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
@ -145,9 +164,9 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
private BitmapImage? _image;
public BitmapImage Image
public BitmapImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
@ -174,27 +193,27 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <summary>
/// 食物
/// </summary>
public ObservableCollection<FoodModel> Foods { get; } = new();
public ObservableList<FoodModel> Foods { get; } = new();
/// <summary>
/// 点击文本
/// </summary>
public ObservableCollection<ClickTextModel> ClickTexts { get; } = new();
public ObservableList<ClickTextModel> ClickTexts { get; } = new();
/// <summary>
/// 低状态文本
/// </summary>
public ObservableCollection<LowTextModel> LowTexts { get; } = new();
public ObservableList<LowTextModel> LowTexts { get; } = new();
/// <summary>
/// 选择文本
/// </summary>
public ObservableCollection<SelectTextModel> SelectTexts { get; } = new();
public ObservableList<SelectTextModel> SelectTexts { get; } = new();
/// <summary>
/// 宠物
/// </summary>
public ObservableCollection<PetModel> Pets { get; } = new();
public ObservableList<PetModel> Pets { get; } = new();
/// <summary>
/// 宠物实际数量
@ -220,27 +239,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public static Dictionary<string, Dictionary<string, string>> SaveI18nDatas { get; } = new();
#endregion
public ModInfoModel()
{
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
//TODO
//Id.ValueChanged += (o, n) =>
//{
// DescriptionId.Value = $"{n}_{nameof(DescriptionId)}";
//};
//Pets.CollectionChanged += Pets_CollectionChanged;
//ShowMainPet.ValueChanged += ShowMainPet_ValueChanged;
}
private void ShowMainPet_ValueChanged(
ObservableValue<bool> sender,
ValueChangedEventArgs<bool> e
)
{
Pets_CollectionChanged(null, null);
}
private void Pets_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void Pets_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (ShowMainPet)
PetDisplayedCount = Pets.Count;
@ -252,8 +252,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
: this()
{
SourcePath = loader.ModPath.FullName;
Id = loader.Name;
DescriptionId = loader.Intro;
ID = loader.Name;
DescriptionID = loader.Intro;
Author = loader.Author;
GameVersion = loader.GameVer;
ModVersion = loader.Ver;
@ -280,22 +280,25 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
// 若宠物的值为默认值并且本体同名宠物不为默认值, 则把本体宠物的值作为模组宠物的默认值
if (
petModel.TouchHeadRect == PetModel.Default.TouchHeadRect
&& petModel.TouchHeadRect != mainPet.TouchHeadRect
petModel.TouchHeadRectangleLocation
== PetModel.Current.TouchHeadRectangleLocation
&& petModel.TouchHeadRectangleLocation != mainPet.TouchHeadRectangleLocation
)
petModel.TouchHeadRect = mainPet.TouchHeadRect;
petModel.TouchHeadRectangleLocation = mainPet.TouchHeadRectangleLocation;
if (
petModel.TouchBodyRect == PetModel.Default.TouchBodyRect
&& petModel.TouchBodyRect != mainPet.TouchBodyRect
petModel.TouchBodyRectangleLocation
== PetModel.Current.TouchBodyRectangleLocation
&& petModel.TouchBodyRectangleLocation != mainPet.TouchBodyRectangleLocation
)
petModel.TouchBodyRect = mainPet.TouchBodyRect;
petModel.TouchBodyRectangleLocation = mainPet.TouchBodyRectangleLocation;
if (
petModel.TouchRaisedRect == PetModel.Default.TouchRaisedRect
&& petModel.TouchRaisedRect != mainPet.TouchRaisedRect
petModel.TouchRaisedRectangleLocation
== PetModel.Current.TouchRaisedRectangleLocation
&& petModel.TouchRaisedRectangleLocation != mainPet.TouchRaisedRectangleLocation
)
petModel.TouchRaisedRect = mainPet.TouchRaisedRect;
petModel.TouchRaisedRectangleLocation = mainPet.TouchRaisedRectangleLocation;
if (
petModel.RaisePoint == PetModel.Default.RaisePoint
petModel.RaisePoint == PetModel.Current.RaisePoint
&& petModel.RaisePoint != mainPet.RaisePoint
)
petModel.RaisePoint = mainPet.RaisePoint;
@ -328,7 +331,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
public void RefreshId()
{
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
DescriptionID = $"{ID}_{nameof(DescriptionID)}";
}
#region Load
@ -500,15 +503,15 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
continue;
if (i18nData.TryGetValue(pet.ID, out var name))
data.Name = name;
if (i18nData.TryGetValue(pet.PetNameId, out var petName))
if (i18nData.TryGetValue(pet.PetNameID, out var petName))
data.PetName = petName;
if (i18nData.TryGetValue(pet.DescriptionId, out var description))
if (i18nData.TryGetValue(pet.DescriptionID, out var description))
data.Description = description;
foreach (var work in pet.Works)
{
if (work.I18nDatas.TryGetValue(key, out var workData) is false)
continue;
if (i18nData.TryGetValue(work.Id, out var workName))
if (i18nData.TryGetValue(work.ID, out var workName))
workData.Name = workName;
}
}
@ -521,7 +524,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
foreach (var selectText in SelectTexts)
selectText.RefreshID();
foreach (var pet in Pets)
pet.RefreshId();
pet.RefreshID();
}
#endregion
#region Save
@ -567,13 +570,13 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
var lps = new LPS()
{
new Line("vupmod", Id)
new Line("vupmod", ID)
{
new Sub("author", Author),
new Sub("gamever", GameVersion),
new Sub("ver", ModVersion)
},
new Line("intro", DescriptionId),
new Line("intro", DescriptionID),
new Line("authorid", AuthorID.ToString()),
new Line("itemid", ItemID.ToString()),
new Line("cachedate", DateTime.Now.Date.ToString("s"))
@ -583,8 +586,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(
new Line("lang", cultureName)
{
new Sub(Id, I18nDatas[cultureName].Name),
new Sub(DescriptionId, I18nDatas[cultureName].Description),
new Sub(ID, I18nDatas[cultureName].Name),
new Sub(DescriptionID, I18nDatas[cultureName].Description),
}
);
}
@ -768,7 +771,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
Directory.CreateDirectory(foodPath);
foreach (var food in Foods)
{
food.Image.SaveToPng(Path.Combine(foodPath, food.ID));
food.Image?.SaveToPng(Path.Combine(foodPath, food.ID));
}
}
}
@ -778,12 +781,12 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public void Close()
{
Image.CloseStream();
Image?.CloseStream();
foreach (var food in Foods)
food.Close();
foreach (var pet in Pets)
pet.Close();
Current = null;
Current = null!;
}
public void SaveTranslationMod(string path, IEnumerable<string> cultures)

View File

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Extensions;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.ViewModels.ModEdit;
using VPet.ModMaker.Views;
using VPet.ModMaker.Views.ModEdit;
namespace VPet.ModMaker.Models;
/// <summary>
/// 模组升级助手
/// </summary>
public static class ModUpdataHelper
{
public static int LastVersion => UpdataAction.Last().Key;
/// <summary>
/// 能否升级模组
/// </summary>
/// <param name="mod">模组</param>
/// <param name="version">版本</param>
/// <returns>可以升级为 <see langword="true"/> 不可以为 <see langword="false"/></returns>
public static bool CanUpdata(ModInfoModel mod)
{
if (mod.ModVersion >= LastVersion)
return false;
return true;
}
/// <summary>
/// 升级模组
/// </summary>
/// <param name="mod">模组</param>
/// <param name="version">版本</param>
/// <returns>可以升级为 <see langword="true"/> 不可以为 <see langword="false"/></returns>
public static bool Updata(ModInfoModel mod)
{
if (CanUpdata(mod) is false)
return false;
foreach (var action in UpdataAction)
{
if (mod.ModVersion >= action.Key)
continue;
try
{
// 更新模组
action.Value(mod);
// 更新支持的游戏版本
mod.GameVersion = action.Key;
}
catch (Exception ex)
{
MessageBox.Show(
ModEditWindow.Current,
"模组更新失败\n当前版本: {0}\n目标版本: {1}\n{2}".Translate(mod.ModVersion, action.Key, ex)
);
return false;
}
}
return true;
}
public static SortedDictionary<int, Action<ModInfoModel>> UpdataAction { get; } =
new()
{
[11000] = (ModInfoModel m) =>
{
// 修改宠物默认ID
foreach (var pet in m.Pets)
{
if (pet.ID == "默认虚拟桌宠")
pet.ID = "vup";
foreach (var work in pet.Works)
{
// 修复工作溢出
work.FixOverLoad();
}
}
},
};
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@ -15,20 +16,65 @@ namespace VPet.ModMaker.Models;
/// </summary>
public class MoveModel : ObservableObjectX<MoveModel>
{
public MoveModel() { }
public MoveModel(MoveModel model)
: this()
{
//Id.EnumValue = model.Id.EnumValue;
Graph = model.Graph;
Distance = model.Distance;
Interval = model.Interval;
CheckLeft = model.CheckLeft;
CheckRight = model.CheckRight;
CheckTop = model.CheckTop;
CheckBottom = model.CheckBottom;
SpeedX = model.SpeedX;
SpeedY = model.SpeedY;
LocateLength = model.LocateLength;
TriggerLeft = model.TriggerLeft;
TriggerRight = model.TriggerRight;
TriggerTop = model.TriggerTop;
TriggerBottom = model.TriggerBottom;
LocateType.Value = model.LocateType.Value;
TriggerType.Value = model.TriggerType.Value;
ModeType.Value = model.ModeType.Value;
}
public MoveModel(GraphHelper.Move move)
: this()
{
//Id.EnumValue = move.Id.EnumValue;
Graph = move.Graph;
Distance = move.Distance;
Interval = move.Interval;
CheckLeft = move.CheckLeft;
CheckRight = move.CheckRight;
CheckTop = move.CheckTop;
CheckBottom = move.CheckBottom;
SpeedX = move.SpeedX;
SpeedY = move.SpeedY;
LocateLength = move.LocateLength;
TriggerLeft = move.TriggerLeft;
TriggerRight = move.TriggerRight;
TriggerTop = move.TriggerTop;
TriggerBottom = move.TriggerBottom;
LocateType.Value = move.LocateType;
TriggerType.Value = move.TriggerType;
ModeType.Value = move.Mode;
}
/// <summary>
/// 移动类型
/// </summary>
public static ObservableCollection<GraphHelper.Move.DirectionType> DirectionTypes { get; } =
new(
Enum.GetValues(typeof(GraphHelper.Move.DirectionType))
.Cast<GraphHelper.Move.DirectionType>()
);
public static FrozenSet<GraphHelper.Move.DirectionType> DirectionTypes { get; } =
Enum.GetValues<GraphHelper.Move.DirectionType>().ToFrozenSet();
/// <summary>
/// 模式类型
/// </summary>
public static ObservableCollection<GraphHelper.Move.ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(GraphHelper.Move.ModeType)).Cast<GraphHelper.Move.ModeType>());
public static FrozenSet<GraphHelper.Move.ModeType> ModeTypes { get; } =
Enum.GetValues<GraphHelper.Move.ModeType>().ToFrozenSet();
//#region Id
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -38,7 +84,7 @@ public class MoveModel : ObservableObjectX<MoveModel>
//#endregion
#region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph;
private string _graph = string.Empty;
/// <summary>
/// 指定动画
@ -255,54 +301,6 @@ public class MoveModel : ObservableObjectX<MoveModel>
| GraphHelper.Move.ModeType.Ill
);
public MoveModel() { }
public MoveModel(MoveModel model)
: this()
{
//Id.EnumValue = model.Id.EnumValue;
Graph = model.Graph;
Distance = model.Distance;
Interval = model.Interval;
CheckLeft = model.CheckLeft;
CheckRight = model.CheckRight;
CheckTop = model.CheckTop;
CheckBottom = model.CheckBottom;
SpeedX = model.SpeedX;
SpeedY = model.SpeedY;
LocateLength = model.LocateLength;
TriggerLeft = model.TriggerLeft;
TriggerRight = model.TriggerRight;
TriggerTop = model.TriggerTop;
TriggerBottom = model.TriggerBottom;
LocateType.Value = model.LocateType.Value;
TriggerType.Value = model.TriggerType.Value;
ModeType.Value = model.ModeType.Value;
}
public MoveModel(GraphHelper.Move move)
: this()
{
//Id.EnumValue = move.Id.EnumValue;
Graph = move.Graph;
Distance = move.Distance;
Interval = move.Interval;
CheckLeft = move.CheckLeft;
CheckRight = move.CheckRight;
CheckTop = move.CheckTop;
CheckBottom = move.CheckBottom;
SpeedX = move.SpeedX;
SpeedY = move.SpeedY;
LocateLength = move.LocateLength;
TriggerLeft = move.TriggerLeft;
TriggerRight = move.TriggerRight;
TriggerTop = move.TriggerTop;
TriggerBottom = move.TriggerBottom;
LocateType.Value = move.LocateType;
TriggerType.Value = move.TriggerType;
ModeType.Value = move.Mode;
}
public GraphHelper.Move ToMove()
{
return new()

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -13,6 +14,7 @@ using HKW.HKWUtils.Observable;
using LinePutScript;
using LinePutScript.Converter;
using LinePutScript.Localization.WPF;
using Mapster;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
@ -23,189 +25,38 @@ namespace VPet.ModMaker.Models;
/// </summary>
public class PetModel : I18nModel<I18nPetInfoModel>
{
public static PetModel Default { get; } = new();
#region FromMain
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _fromMain;
/// <summary>
/// 来自本体
/// </summary>
public bool FromMain
{
get => _fromMain;
set => SetProperty(ref _fromMain, value);
}
#endregion
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
/// <summary>
/// Id
/// </summary>
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region PetNameId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _petNameId;
/// <summary>
/// 名称Id
/// </summary>
public string PetNameId
{
get => _petNameId;
set => SetProperty(ref _petNameId, value);
}
#endregion
#region DescriptionId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId;
/// <summary>
/// 描述Id
/// </summary>
public string DescriptionId
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
}
#endregion
#region TouchHeadRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchHeadRect = new(159, 16, 189, 178);
/// <summary>
/// 头部点击区域
/// </summary>
public ObservableRectangleLocation<double> TouchHeadRect
{
get => _touchHeadRect;
set => SetProperty(ref _touchHeadRect, value);
}
#endregion
#region TouchBodyRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchBodyRect = new(166, 206, 163, 136);
/// <summary>
/// 身体区域
/// </summary>
public ObservableRectangleLocation<double> TouchBodyRect
{
get => _touchBodyRect;
set => SetProperty(ref _touchBodyRect, value);
}
#endregion
/// <summary>
/// 提起区域
/// </summary>
#region TouchRaisedRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStateRect _touchRaisedRect =
new(
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 200, 500, 300)
);
public ObservableMultiStateRect TouchRaisedRect
{
get => _touchRaisedRect;
set => SetProperty(ref _touchRaisedRect, value);
}
#endregion
#region RaisePoint
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStatePoint _raisePoint =
new(new(290, 128), new(290, 128), new(290, 128), new(225, 115));
/// <summary>
/// 提起定位
/// </summary>
public ObservableMultiStatePoint RaisePoint
{
get => _raisePoint;
set => SetProperty(ref _raisePoint, value);
}
#endregion
/// <summary>
/// 工作
/// </summary>
public ObservableCollection<WorkModel> Works { get; } = new();
/// <summary>
/// 移动
/// </summary>
public ObservableCollection<MoveModel> Moves { get; } = new();
/// <summary>
/// 动画
/// </summary>
public ObservableCollection<AnimeTypeModel> Animes { get; } = new();
/// <summary>
///食物动画
/// </summary>
public ObservableCollection<FoodAnimeTypeModel> FoodAnimes { get; } = new();
#region AnimeCount
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _AnimeCount;
public int AnimeCount
{
get => _AnimeCount;
set => SetProperty(ref _AnimeCount, value);
}
#endregion
public PetModel()
{
PetNameId = $"{ID}_{nameof(PetNameId)}";
DescriptionId = $"{ID}_{nameof(DescriptionId)}";
//TODO
//ID.ValueChanged += (s, e) =>
//{
// PetNameId = $"{e.NewValue}_{nameof(PetNameId)}";
// DescriptionId = $"{e.NewValue}_{nameof(DescriptionId)}";
//};
//AnimeCount.AddNotifySender(Animes);
//AnimeCount.AddNotifySender(FoodAnimes);
//AnimeCount.SenderPropertyChanged += (s, _) =>
//{
// s.Value = Animes.Count + FoodAnimes.Count;
//};
PropertyChanged += PetModel_PropertyChanged;
Animes.PropertyChanged += Animes_PropertyChanged;
FoodAnimes.PropertyChanged += FoodAnimes_PropertyChanged;
}
private void PetModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ID))
{
PetNameID = $"{ID}_{nameof(PetNameID)}";
DescriptionID = $"{ID}_{nameof(DescriptionID)}";
}
}
public PetModel(PetModel model)
: this()
{
ID = model.ID;
PetNameId = model.PetNameId;
TouchHeadRect = model.TouchHeadRect.Clone();
TouchBodyRect = model.TouchBodyRect.Clone();
TouchRaisedRect = model.TouchRaisedRect.Copy();
RaisePoint = model.RaisePoint.Copy();
PetNameID = model.PetNameID;
DescriptionID = model.DescriptionID;
Tags = model.Tags;
TouchHeadRectangleLocation = model.TouchHeadRectangleLocation.Clone();
TouchBodyRectangleLocation = model.TouchBodyRectangleLocation.Clone();
TouchRaisedRectangleLocation = model.TouchRaisedRectangleLocation.Clone();
RaisePoint = model.RaisePoint.Clone();
foreach (var work in model.Works)
Works.Add(work);
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
@ -213,42 +64,43 @@ public class PetModel : I18nModel<I18nPetInfoModel>
: this()
{
ID = loader.Name;
PetNameId = loader.PetName;
DescriptionId = loader.Intor;
PetNameID = loader.PetName;
DescriptionID = loader.Intor;
Tags = loader.Config.Data["tag"].Info;
TouchHeadRect = new(
TouchHeadRectangleLocation = new(
loader.Config.TouchHeadLocate.X,
loader.Config.TouchHeadLocate.Y,
loader.Config.TouchHeadSize.Width,
loader.Config.TouchHeadSize.Height
);
TouchBodyRect = new(
TouchBodyRectangleLocation = new(
loader.Config.TouchBodyLocate.X,
loader.Config.TouchBodyLocate.Y,
loader.Config.TouchBodySize.Width,
loader.Config.TouchBodySize.Height
);
TouchRaisedRect.Happy = new(
TouchRaisedRectangleLocation.Happy = new(
loader.Config.TouchRaisedLocate[0].X,
loader.Config.TouchRaisedLocate[0].Y,
loader.Config.TouchRaisedSize[0].Width,
loader.Config.TouchRaisedSize[0].Height
);
TouchRaisedRect.Nomal = new(
TouchRaisedRectangleLocation.Nomal = new(
loader.Config.TouchRaisedLocate[1].X,
loader.Config.TouchRaisedLocate[1].Y,
loader.Config.TouchRaisedSize[1].Width,
loader.Config.TouchRaisedSize[1].Height
);
TouchRaisedRect.PoorCondition = new(
TouchRaisedRectangleLocation.PoorCondition = new(
loader.Config.TouchRaisedLocate[2].X,
loader.Config.TouchRaisedLocate[2].Y,
loader.Config.TouchRaisedSize[2].Width,
loader.Config.TouchRaisedSize[2].Height
);
TouchRaisedRect.Ill = new(
TouchRaisedRectangleLocation.Ill = new(
loader.Config.TouchRaisedLocate[3].X,
loader.Config.TouchRaisedLocate[3].Y,
loader.Config.TouchRaisedSize[3].Width,
@ -272,10 +124,191 @@ public class PetModel : I18nModel<I18nPetInfoModel>
Moves.Add(new(move));
}
public void RefreshId()
public static PetModel Current { get; } = new();
#region FromMain
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _fromMain;
/// <summary>
/// 来自本体
/// </summary>
public bool FromMain
{
PetNameId = $"{ID}_{nameof(PetNameId)}";
DescriptionId = $"{ID}_{nameof(DescriptionId)}";
get => _fromMain;
set => SetProperty(ref _fromMain, value);
}
#endregion
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public string ID
{
get => _id;
set
{
SetProperty(ref _id, value);
RefreshID();
}
}
#endregion
#region PetNameId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _petNameID = string.Empty;
/// <summary>
/// 名称Id
/// </summary>
public string PetNameID
{
get => _petNameID;
set => SetProperty(ref _petNameID, value);
}
#endregion
#region DescriptionId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionID = string.Empty;
/// <summary>
/// 描述Id
/// </summary>
public string DescriptionID
{
get => _descriptionID;
set => SetProperty(ref _descriptionID, value);
}
#endregion
#region Tags
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _tags = string.Empty;
/// <summary>
/// 标签
/// </summary>
public string Tags
{
get => _tags;
set => SetProperty(ref _tags, value);
}
#endregion
#region TouchHeadRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchHeadRectangleLocation =
new(159, 16, 189, 178);
/// <summary>
/// 头部点击区域
/// </summary>
public ObservableRectangleLocation<double> TouchHeadRectangleLocation
{
get => _touchHeadRectangleLocation;
set => SetProperty(ref _touchHeadRectangleLocation, value);
}
#endregion
#region TouchBodyRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchBodyRectangleLocation =
new(166, 206, 163, 136);
/// <summary>
/// 身体区域
/// </summary>
public ObservableRectangleLocation<double> TouchBodyRectangleLocation
{
get => _touchBodyRectangleLocation;
set => SetProperty(ref _touchBodyRectangleLocation, value);
}
#endregion
/// <summary>
/// 提起区域
/// </summary>
#region TouchRaisedRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStateRectangleLocation _touchRaisedRectangleLocation =
new(
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 200, 500, 300)
);
public ObservableMultiStateRectangleLocation TouchRaisedRectangleLocation
{
get => _touchRaisedRectangleLocation;
set => SetProperty(ref _touchRaisedRectangleLocation, value);
}
#endregion
#region RaisePoint
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStatePoint _raisePoint =
new(new(290, 128), new(290, 128), new(290, 128), new(225, 115));
/// <summary>
/// 提起定位
/// </summary>
public ObservableMultiStatePoint RaisePoint
{
get => _raisePoint;
set => SetProperty(ref _raisePoint, value);
}
#endregion
/// <summary>
/// 工作
/// </summary>
public ObservableList<WorkModel> Works { get; } = new();
/// <summary>
/// 移动
/// </summary>
public ObservableList<MoveModel> Moves { get; } = new();
/// <summary>
/// 动画
/// </summary>
public ObservableList<AnimeTypeModel> Animes { get; } = new();
/// <summary>
///食物动画
/// </summary>
public ObservableList<FoodAnimeTypeModel> FoodAnimes { get; } = new();
#region AnimeCount
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _animeCount;
public int AnimeCount
{
get => _animeCount;
set => SetProperty(ref _animeCount, value);
}
#endregion
private void FoodAnimes_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
AnimeCount = Animes.Count + FoodAnimes.Count;
}
private void Animes_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
AnimeCount = Animes.Count + FoodAnimes.Count;
}
public void RefreshID()
{
PetNameID = $"{ID}_{nameof(PetNameID)}";
DescriptionID = $"{ID}_{nameof(DescriptionID)}";
}
public void Close()
@ -316,10 +349,10 @@ public class PetModel : I18nModel<I18nPetInfoModel>
ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(PetNameId, I18nDatas[cultureName].PetName);
.TryAdd(PetNameID, I18nDatas[cultureName].PetName);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(DescriptionId, I18nDatas[cultureName].Description);
.TryAdd(DescriptionID, I18nDatas[cultureName].Description);
}
var petFile = Path.Combine(path, $"{ID}.lps");
if (File.Exists(petFile) is false)
@ -351,7 +384,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// 保存移动信息
/// </summary>
/// <param name="lps"></param>
/// <param name="pet"></param>
void SaveMoveInfo(LPS lps)
{
foreach (var move in Moves)
@ -364,7 +396,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// 保存工作信息
/// </summary>
/// <param name="lps"></param>
/// <param name="pet"></param>
void SaveWorksInfo(LPS lps)
{
foreach (var work in Works)
@ -374,7 +405,7 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(work.Id, work.I18nDatas[cultureName].Name);
.TryAdd(work.ID, work.I18nDatas[cultureName].Name);
}
}
}
@ -405,16 +436,22 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
SavePetBasicInfo(lps);
// 如果值不为默认并且不与本体值相同, 则保存
if (TouchHeadRect != Default.TouchHeadRect && TouchHeadRect != mainPet.TouchHeadRect)
if (
TouchHeadRectangleLocation != Current.TouchHeadRectangleLocation
&& TouchHeadRectangleLocation != mainPet.TouchHeadRectangleLocation
)
SavePetTouchHeadInfo(lps);
if (TouchBodyRect != Default.TouchBodyRect && TouchBodyRect != mainPet.TouchBodyRect)
if (
TouchBodyRectangleLocation != Current.TouchBodyRectangleLocation
&& TouchBodyRectangleLocation != mainPet.TouchBodyRectangleLocation
)
SavePetTouchBodyInfo(lps);
if (
TouchRaisedRect != Default.TouchRaisedRect
&& TouchRaisedRect != mainPet.TouchRaisedRect
TouchRaisedRectangleLocation != Current.TouchRaisedRectangleLocation
&& TouchRaisedRectangleLocation != mainPet.TouchRaisedRectangleLocation
)
SavePetTouchRaisedInfo(lps);
if (RaisePoint != Default.RaisePoint && RaisePoint != mainPet.RaisePoint)
if (RaisePoint != Current.RaisePoint && RaisePoint != mainPet.RaisePoint)
SavePetRaisePointInfo(lps);
}
@ -423,11 +460,12 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("pet", ID)
{
new Sub("intor", DescriptionId),
new Sub("intor", DescriptionID),
new Sub("path", ID),
new Sub("petname", PetNameId)
new Sub("petname", PetNameID)
}
);
lps.Add(new Line("tag", Tags));
}
private void SavePetTouchHeadInfo(LPS lps)
@ -435,10 +473,10 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("touchhead")
{
new Sub("px", TouchHeadRect.X),
new Sub("py", TouchHeadRect.Y),
new Sub("sw", TouchHeadRect.Width),
new Sub("sh", TouchHeadRect.Height),
new Sub("px", TouchHeadRectangleLocation.X),
new Sub("py", TouchHeadRectangleLocation.Y),
new Sub("sw", TouchHeadRectangleLocation.Width),
new Sub("sh", TouchHeadRectangleLocation.Height),
}
);
}
@ -448,10 +486,10 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("touchbody")
{
new Sub("px", TouchBodyRect.X),
new Sub("py", TouchBodyRect.Y),
new Sub("sw", TouchBodyRect.Width),
new Sub("sh", TouchBodyRect.Height),
new Sub("px", TouchBodyRectangleLocation.X),
new Sub("py", TouchBodyRectangleLocation.Y),
new Sub("sw", TouchBodyRectangleLocation.Width),
new Sub("sh", TouchBodyRectangleLocation.Height),
}
);
}
@ -461,25 +499,25 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("touchraised")
{
new Sub("happy_px", TouchRaisedRect.Happy.X),
new Sub("happy_py", TouchRaisedRect.Happy.Y),
new Sub("happy_sw", TouchRaisedRect.Happy.Width),
new Sub("happy_sh", TouchRaisedRect.Happy.Height),
new Sub("happy_px", TouchRaisedRectangleLocation.Happy.X),
new Sub("happy_py", TouchRaisedRectangleLocation.Happy.Y),
new Sub("happy_sw", TouchRaisedRectangleLocation.Happy.Width),
new Sub("happy_sh", TouchRaisedRectangleLocation.Happy.Height),
//
new Sub("nomal_px", TouchRaisedRect.Nomal.X),
new Sub("nomal_py", TouchRaisedRect.Nomal.Y),
new Sub("nomal_sw", TouchRaisedRect.Nomal.Width),
new Sub("nomal_sh", TouchRaisedRect.Nomal.Height),
new Sub("nomal_px", TouchRaisedRectangleLocation.Nomal.X),
new Sub("nomal_py", TouchRaisedRectangleLocation.Nomal.Y),
new Sub("nomal_sw", TouchRaisedRectangleLocation.Nomal.Width),
new Sub("nomal_sh", TouchRaisedRectangleLocation.Nomal.Height),
//
new Sub("poorcondition_px", TouchRaisedRect.PoorCondition.X),
new Sub("poorcondition_py", TouchRaisedRect.PoorCondition.Y),
new Sub("poorcondition_sw", TouchRaisedRect.PoorCondition.Width),
new Sub("poorcondition_sh", TouchRaisedRect.PoorCondition.Height),
new Sub("poorcondition_px", TouchRaisedRectangleLocation.PoorCondition.X),
new Sub("poorcondition_py", TouchRaisedRectangleLocation.PoorCondition.Y),
new Sub("poorcondition_sw", TouchRaisedRectangleLocation.PoorCondition.Width),
new Sub("poorcondition_sh", TouchRaisedRectangleLocation.PoorCondition.Height),
//
new Sub("ill_px", TouchRaisedRect.Ill.X),
new Sub("ill_py", TouchRaisedRect.Ill.Y),
new Sub("ill_sw", TouchRaisedRect.Ill.Width),
new Sub("ill_sh", TouchRaisedRect.Ill.Height),
new Sub("ill_px", TouchRaisedRectangleLocation.Ill.X),
new Sub("ill_py", TouchRaisedRectangleLocation.Ill.Y),
new Sub("ill_sw", TouchRaisedRectangleLocation.Ill.Width),
new Sub("ill_sh", TouchRaisedRectangleLocation.Ill.Height),
}
);
}
@ -507,7 +545,7 @@ public class PetModel : I18nModel<I18nPetInfoModel>
#endregion
}
public class I18nPetInfoModel : ObservableObjectX<I18nPetInfoModel>
public class I18nPetInfoModel : ObservableObjectX<I18nPetInfoModel>, ICloneable<I18nPetInfoModel>
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -540,7 +578,7 @@ public class I18nPetInfoModel : ObservableObjectX<I18nPetInfoModel>
}
#endregion
public I18nPetInfoModel Copy()
public I18nPetInfoModel Clone()
{
var result = new I18nPetInfoModel();
result.Name = Name;
@ -548,15 +586,18 @@ public class I18nPetInfoModel : ObservableObjectX<I18nPetInfoModel>
result.Description = Description;
return result;
}
object ICloneable.Clone() => Clone();
}
public class ObservableMultiStateRect
: ObservableObjectX<ObservableMultiStateRect>,
IEquatable<ObservableMultiStateRect>
public class ObservableMultiStateRectangleLocation
: ObservableObjectX<ObservableMultiStateRectangleLocation>,
IEquatable<ObservableMultiStateRectangleLocation>,
ICloneable<ObservableMultiStateRectangleLocation>
{
#region Happy
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _happy;
private ObservableRectangleLocation<double> _happy = null!;
public ObservableRectangleLocation<double> Happy
{
get => _happy;
@ -565,9 +606,9 @@ public class ObservableMultiStateRect
#endregion
#region Nomal
private ObservableRectangleLocation<double> _nomal;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _nomal = null!;
public ObservableRectangleLocation<double> Nomal
{
get => _nomal;
@ -577,7 +618,7 @@ public class ObservableMultiStateRect
#region PoorCondition
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _poorCondition;
private ObservableRectangleLocation<double> _poorCondition = null!;
public ObservableRectangleLocation<double> PoorCondition
{
get => _poorCondition;
@ -587,7 +628,7 @@ public class ObservableMultiStateRect
#region Ill
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _ill;
private ObservableRectangleLocation<double> _ill = null!;
public ObservableRectangleLocation<double> Ill
{
get => _ill;
@ -595,7 +636,7 @@ public class ObservableMultiStateRect
}
#endregion
public ObservableMultiStateRect()
public ObservableMultiStateRectangleLocation()
{
Happy = new();
Nomal = new();
@ -603,7 +644,7 @@ public class ObservableMultiStateRect
Ill = new();
}
public ObservableMultiStateRect(
public ObservableMultiStateRectangleLocation(
ObservableRectangleLocation<double> happy,
ObservableRectangleLocation<double> nomal,
ObservableRectangleLocation<double> poorCondition,
@ -616,7 +657,7 @@ public class ObservableMultiStateRect
Ill = ill;
}
public ObservableMultiStateRect Copy()
public ObservableMultiStateRectangleLocation Clone()
{
return new()
{
@ -627,6 +668,8 @@ public class ObservableMultiStateRect
};
}
object ICloneable.Clone() => Clone();
#region Other
/// <inheritdoc/>
@ -638,36 +681,32 @@ public class ObservableMultiStateRect
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableMultiStateRect temp
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
Happy,
temp.Happy
)
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
Nomal,
temp.Nomal
)
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
PoorCondition,
temp.PoorCondition
)
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(Ill, temp.Ill);
return Equals(obj as ObservableMultiStateRectangleLocation);
}
/// <inheritdoc/>
public bool Equals(ObservableMultiStateRect? other)
public bool Equals(ObservableMultiStateRectangleLocation? other)
{
return Equals(obj: other);
return Happy.Equals(other?.Happy)
&& Nomal.Equals(other?.Nomal)
&& PoorCondition.Equals(other?.PoorCondition)
&& Ill.Equals(other?.Ill);
}
/// <inheritdoc/>
public static bool operator ==(ObservableMultiStateRect a, ObservableMultiStateRect b)
public static bool operator ==(
ObservableMultiStateRectangleLocation a,
ObservableMultiStateRectangleLocation b
)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableMultiStateRect a, ObservableMultiStateRect b)
public static bool operator !=(
ObservableMultiStateRectangleLocation a,
ObservableMultiStateRectangleLocation b
)
{
return Equals(a, b) is not true;
}
@ -677,11 +716,12 @@ public class ObservableMultiStateRect
public class ObservableMultiStatePoint
: ObservableObjectX<ObservableMultiStatePoint>,
IEquatable<ObservableMultiStatePoint>
IEquatable<ObservableMultiStatePoint>,
ICloneable<ObservableMultiStatePoint>
{
#region Happy
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _happy;
private ObservablePoint<double> _happy = null!;
public ObservablePoint<double> Happy
{
get => _happy;
@ -691,7 +731,7 @@ public class ObservableMultiStatePoint
#region Nomal
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _nomal;
private ObservablePoint<double> _nomal = null!;
public ObservablePoint<double> Nomal
{
get => _nomal;
@ -701,7 +741,7 @@ public class ObservableMultiStatePoint
#region PoorCondition
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _poorCondition;
private ObservablePoint<double> _poorCondition = null!;
public ObservablePoint<double> PoorCondition
{
get => _poorCondition;
@ -711,7 +751,7 @@ public class ObservableMultiStatePoint
#region Ill
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _ill;
private ObservablePoint<double> _ill = null!;
public ObservablePoint<double> Ill
{
get => _ill;
@ -739,7 +779,7 @@ public class ObservableMultiStatePoint
Ill = ill;
}
public ObservableMultiStatePoint Copy()
public ObservableMultiStatePoint Clone()
{
return new()
{
@ -750,6 +790,8 @@ public class ObservableMultiStatePoint
};
}
object ICloneable.Clone() => Clone();
#region Other
/// <inheritdoc/>
@ -761,20 +803,16 @@ public class ObservableMultiStatePoint
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableMultiStatePoint temp
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Happy, temp.Happy)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Nomal, temp.Nomal)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(
PoorCondition,
temp.PoorCondition
)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Ill, temp.Ill);
return Equals(obj as ObservableMultiStatePoint);
}
/// <inheritdoc/>
public bool Equals(ObservableMultiStatePoint? other)
{
return Equals(obj: other);
return Happy.Equals(other?.Happy)
&& Nomal.Equals(other?.Nomal)
&& PoorCondition.Equals(other?.PoorCondition)
&& Ill.Equals(other?.Ill);
}
/// <inheritdoc/>

View File

@ -119,7 +119,6 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
/// <summary>
/// 选择Id
/// </summary>
public string ChooseID
{
get => _chooseId;

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
@ -8,6 +10,8 @@ using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using HKW.HKWUtils.Observable;
using Mapster;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.Models;
@ -16,23 +20,105 @@ namespace VPet.ModMaker.Models;
/// </summary>
public class WorkModel : I18nModel<I18nWorkModel>
{
public WorkModel()
{
PropertyChanged += WorkModel_PropertyChanged;
}
private static readonly FrozenSet<string> _notifyIsOverLoad = FrozenSet.ToFrozenSet(
[
nameof(WorkType),
nameof(MoneyBase),
nameof(StrengthFood),
nameof(StrengthDrink),
nameof(Feeling),
nameof(Feeling),
nameof(LevelLimit),
nameof(FinishBonus)
]
);
private void WorkModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is not null && _notifyIsOverLoad.Contains(e.PropertyName))
{
IsOverLoad = VPet_Simulator.Windows.Interface.ExtensionFunction.IsOverLoad(ToWork());
}
}
public WorkModel(WorkModel model)
: this()
{
WorkType = model.WorkType;
ID = model.ID;
Graph = model.Graph;
//MoneyLevel = model.MoneyLevel;
MoneyBase = model.MoneyBase;
StrengthFood = model.StrengthFood;
StrengthDrink = model.StrengthDrink;
Feeling = model.Feeling;
LevelLimit = model.LevelLimit;
Time = model.Time;
FinishBonus = model.FinishBonus;
BorderBrush = model.BorderBrush;
Background = model.Background;
ButtonBackground = model.ButtonBackground;
ButtonForeground = model.ButtonForeground;
Foreground = model.Foreground;
Left = model.Left;
Top = model.Top;
Width = model.Width;
//Image = model.Image?.CloneStream();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public WorkModel(VPet_Simulator.Core.GraphHelper.Work work)
: this()
{
WorkType = work.Type;
ID = work.Name;
Graph = work.Graph;
//MoneyLevel = work.MoneyLevel;
MoneyBase = work.MoneyBase;
StrengthFood = work.StrengthFood;
StrengthDrink = work.StrengthDrink;
Feeling = work.Feeling;
LevelLimit = work.LevelLimit;
Time = work.Time;
FinishBonus = work.FinishBonus;
BorderBrush = new((Color)ColorConverter.ConvertFromString("#FF" + work.BorderBrush));
Background = new((Color)ColorConverter.ConvertFromString("#FF" + work.Background));
Foreground = new((Color)ColorConverter.ConvertFromString("#FF" + work.Foreground));
ButtonBackground = new(
(Color)ColorConverter.ConvertFromString("#AA" + work.ButtonBackground)
);
ButtonForeground = new(
(Color)ColorConverter.ConvertFromString("#FF" + work.ButtonForeground)
);
Left = work.Left;
Top = work.Top;
Width = work.Width;
}
/// <summary>
/// 工作类型
/// </summary>
public static ObservableCollection<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkTypes { get; } =
new(
Enum.GetValues(typeof(VPet_Simulator.Core.GraphHelper.Work.WorkType))
.Cast<VPet_Simulator.Core.GraphHelper.Work.WorkType>()
);
public static FrozenSet<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkTypes { get; } =
Enum.GetValues<VPet_Simulator.Core.GraphHelper.Work.WorkType>().ToFrozenSet();
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public string Id
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
@ -41,12 +127,11 @@ public class WorkModel : I18nModel<I18nWorkModel>
#region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph;
private string _graph = string.Empty;
/// <summary>
/// 指定动画
/// </summary>
public string Graph
{
get => _graph;
@ -180,19 +265,19 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
//#region Image
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
//private BitmapImage? _image;
/// <summary>
/// 图片
/// </summary>
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
///// <summary>
///// 图片
///// </summary>
//public BitmapImage? Image
//{
// get => _image;
// set => SetProperty(ref _image, value);
//}
//#endregion
#region WorkType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -224,13 +309,13 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#endregion
/// <summary>
/// 背景色
/// </summary>
#region Background
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _background = new((Color)ColorConverter.ConvertFromString("#FF81D4FA"));
/// <summary>
/// 背景色
/// </summary>
public SolidColorBrush Background
{
get => _background;
@ -238,13 +323,13 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#endregion
/// <summary>
/// 前景色
/// </summary>
#region Foreground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _foreground = new((Color)ColorConverter.ConvertFromString("#FF0286C6"));
/// <summary>
/// 前景色
/// </summary>
public SolidColorBrush Foreground
{
get => _foreground;
@ -252,14 +337,14 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#endregion
/// <summary>
/// 按钮背景色
/// </summary>
#region ButtonBackground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _buttonBackground =
new((Color)ColorConverter.ConvertFromString("#AA0286C6"));
/// <summary>
/// 按钮背景色
/// </summary>
public SolidColorBrush ButtonBackground
{
get => _buttonBackground;
@ -267,135 +352,67 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#endregion
#region ButtonForeground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _buttonForeground =
new((Color)ColorConverter.ConvertFromString("#FFFFFFFF"));
/// <summary>
/// 按钮前景色
/// </summary>
#region ButtonForeground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _buttonForeground;
public SolidColorBrush ButtonForeground
{
get => _buttonForeground;
set => SetProperty(ref _buttonForeground, value);
}
#endregion
#region Left
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _left;
/// <summary>
/// X位置
/// </summary>
#region Left
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Left;
public double Left
{
get => _Left;
set => SetProperty(ref _Left, value);
get => _left;
set => SetProperty(ref _left, value);
}
#endregion
#region Top
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _top;
/// <summary>
/// Y位置
/// </summary>
#region Top
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Top;
public double Top
{
get => _Top;
set => SetProperty(ref _Top, value);
get => _top;
set => SetProperty(ref _top, value);
}
#endregion
#region Width
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _width;
/// <summary>
/// 宽度
/// </summary>
#region Width
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Width;
public double Width
{
get => _Width;
set => SetProperty(ref _Width, value);
get => _width;
set => SetProperty(ref _width, value);
}
#endregion
public WorkModel()
{ //TODO
//IsOverLoad.AddNotifySender(
// WorkType,
// MoneyBase,
// //MoneyLevel,
// StrengthFood,
// StrengthDrink,
// Feeling,
// LevelLimit,
// FinishBonus
//);
//IsOverLoad.SenderPropertyChanged += (s, _) =>
//{
// s.Value = VPet_Simulator.Windows.Interface.ExtensionFunction.IsOverLoad(ToWork());
//};
}
public WorkModel(WorkModel model)
: this()
public void FixOverLoad()
{
WorkType = model.WorkType;
Id = model.Id;
Graph = model.Graph;
//MoneyLevel = model.MoneyLevel;
MoneyBase = model.MoneyBase;
StrengthFood = model.StrengthFood;
StrengthDrink = model.StrengthDrink;
Feeling = model.Feeling;
LevelLimit = model.LevelLimit;
Time = model.Time;
FinishBonus = model.FinishBonus;
BorderBrush = model.BorderBrush;
Background = model.Background;
ButtonBackground = model.ButtonBackground;
ButtonForeground = model.ButtonForeground;
Foreground = model.Foreground;
Left = model.Left;
Top = model.Top;
Width = model.Width;
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public WorkModel(VPet_Simulator.Core.GraphHelper.Work work)
: this()
{
WorkType = work.Type;
Id = work.Name;
Graph = work.Graph;
//MoneyLevel = work.MoneyLevel;
MoneyBase = work.MoneyBase;
StrengthFood = work.StrengthFood;
StrengthDrink = work.StrengthDrink;
Feeling = work.Feeling;
LevelLimit = work.LevelLimit;
Time = work.Time;
FinishBonus = work.FinishBonus;
BorderBrush = new((Color)ColorConverter.ConvertFromString("#FF" + work.BorderBrush));
Background = new((Color)ColorConverter.ConvertFromString("#FF" + work.Background));
Foreground = new((Color)ColorConverter.ConvertFromString("#FF" + work.Foreground));
ButtonBackground = new(
(Color)ColorConverter.ConvertFromString("#AA" + work.ButtonBackground)
);
ButtonForeground = new(
(Color)ColorConverter.ConvertFromString("#FF" + work.ButtonForeground)
);
Left = work.Left;
Top = work.Top;
Width = work.Width;
var work = ToWork();
work.FixOverLoad();
work.Adapt(this);
}
public VPet_Simulator.Core.GraphHelper.Work ToWork()
@ -403,7 +420,7 @@ public class WorkModel : I18nModel<I18nWorkModel>
return new()
{
Type = WorkType,
Name = Id,
Name = ID,
Graph = Graph,
//MoneyLevel = MoneyLevel,
MoneyBase = MoneyBase,
@ -428,15 +445,15 @@ public class WorkModel : I18nModel<I18nWorkModel>
public void Close()
{
Image.CloseStream();
//Image?.CloseStream();
}
}
public class I18nWorkModel : ObservableObjectX<I18nWorkModel>
public class I18nWorkModel : ObservableObjectX<I18nWorkModel>, ICloneable<I18nWorkModel>
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
private string _name = string.Empty;
public string Name
{
@ -445,10 +462,12 @@ public class I18nWorkModel : ObservableObjectX<I18nWorkModel>
}
#endregion
public I18nWorkModel Copy()
public I18nWorkModel Clone()
{
var result = new I18nWorkModel();
result.Name = Name;
return result;
}
object ICloneable.Clone() => Clone();
}

View File

@ -285,6 +285,24 @@ public static class NativeExtensions
catch { }
};
}
public static void SetDataContext(
this Window window,
object viewModel,
Action? closedAction = null
)
{
window.DataContext = viewModel;
window.Closed += (s, e) =>
{
try
{
closedAction?.Invoke();
window.DataContext = null;
}
catch { }
};
}
}
/// <summary>

View File

@ -27,7 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="HKW.Utils" Version="1.2.4" />
<PackageReference Include="HKW.Utils" Version="1.2.5" />
<PackageReference Include="HKW.WPF" Version="1.0.3" />
<PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -21,24 +22,70 @@ namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
{
public AnimeEditWindowVM()
{
_playerTask = new(Play);
PropertyChangedX += AnimeEditWindowVM_PropertyChangedX;
PlayCommand.ExecuteAsyncCommand += PlayCommand_ExecuteAsyncCommand;
StopCommand.ExecuteCommand += StopCommand_ExecuteCommand;
AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteCommand;
RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteCommand;
AddImageCommand.ExecuteCommand += AddImageCommand_ExecuteCommand;
RemoveImageCommand.ExecuteCommand += RemoveImageCommand_ExecuteCommand;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
ClearImageCommand.ExecuteCommand += ClearImageCommand_ExecuteCommand;
}
private void AnimeEditWindowVM_PropertyChangedX(
AnimeEditWindowVM sender,
PropertyChangedXEventArgs e
)
{
if (e.PropertyName == nameof(CurrentAnimeModel))
{
var newModel = e.NewValue as AnimeModel;
var oldModel = e.OldValue as AnimeModel;
StopCommand_ExecuteCommand();
if (oldModel is not null)
oldModel.Images.CollectionChanged -= Images_CollectionChanged;
if (newModel is not null)
newModel.Images.CollectionChanged += Images_CollectionChanged;
}
}
/// <summary>
/// 当前宠物
/// </summary>
public PetModel CurrentPet { get; set; }
public PetModel CurrentPet { get; set; } = null!;
/// <summary>
/// 旧动画
/// </summary>
public AnimeTypeModel OldAnime { get; set; }
public AnimeTypeModel? OldAnime { get; set; }
#region Anime
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private AnimeTypeModel _anime = new();
/// <summary>
/// 动画
/// </summary>
public ObservableValue<AnimeTypeModel> Anime { get; } = new(new());
public AnimeTypeModel Anime
{
get => _anime;
set
{
if (SetProperty(ref _anime, value) is false)
return;
CheckGraphType(Anime);
}
}
#endregion
#region CurrentImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ImageModel _currentImageModel;
private ImageModel _currentImageModel = null!;
/// <summary>
/// 当前图像模型
@ -52,7 +99,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
#region CurrentAnimeModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private AnimeModel _currentAnimeModel;
private AnimeModel _currentAnimeModel = null!;
/// <summary>
/// 当前动画模型
@ -164,32 +211,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// </summary>
private Task _playerTask;
public AnimeEditWindowVM()
{
_playerTask = new(Play);
//TODO
//CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteEvent;
AddImageCommand.ExecuteCommand += AddImageCommand_ExecuteEvent;
RemoveImageCommand.ExecuteCommand += RemoveImageCommand_ExecuteEvent;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteEvent;
ClearImageCommand.ExecuteCommand += ClearImageCommand_ExecuteEvent;
Anime.ValueChanged += Anime_ValueChanged;
}
#region LoadAnime
private void Anime_ValueChanged(
ObservableValue<AnimeTypeModel> sender,
ValueChangedEventArgs<AnimeTypeModel> e
)
{
CheckGraphType(e.NewValue);
}
private void CheckGraphType(AnimeTypeModel model)
{
@ -206,16 +228,16 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// 添加动画
/// </summary>
/// <param name="value">动画模型</param>
private void AddAnimeCommand_ExecuteEvent()
private void AddAnimeCommand_ExecuteCommand()
{
if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Add(new());
Anime.HappyAnimes.Add(new());
else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Add(new());
Anime.NomalAnimes.Add(new());
else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Add(new());
Anime.PoorConditionAnimes.Add(new());
else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Add(new());
Anime.IllAnimes.Add(new());
}
/// <summary>
@ -223,20 +245,20 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// </summary>
/// <param name="value">动画模型</param>
private void RemoveAnimeCommand_ExecuteEvent(AnimeModel value)
private void RemoveAnimeCommand_ExecuteCommand(AnimeModel value)
{
if (
MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
)
{
if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Remove(value);
Anime.HappyAnimes.Remove(value);
else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Remove(value);
Anime.NomalAnimes.Remove(value);
else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Remove(value);
Anime.PoorConditionAnimes.Remove(value);
else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Remove(value);
Anime.IllAnimes.Remove(value);
value.Close();
}
}
@ -248,7 +270,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// 添加图片
/// </summary>
/// <param name="value">动画模型</param>
private void AddImageCommand_ExecuteEvent(AnimeModel value)
private void AddImageCommand_ExecuteCommand(AnimeModel value)
{
OpenFileDialog openFileDialog =
new()
@ -266,7 +288,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// 删除图片
/// </summary>
/// <param name="value">动画模型</param>
private void RemoveImageCommand_ExecuteEvent(AnimeModel value)
private void RemoveImageCommand_ExecuteCommand(AnimeModel value)
{
CurrentImageModel.Close();
value.Images.Remove(CurrentImageModel);
@ -277,7 +299,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// </summary>
/// <param name="value"></param>
/// <exception cref="NotImplementedException"></exception>
private void ChangeImageCommand_ExecuteEvent(AnimeModel value)
private void ChangeImageCommand_ExecuteCommand(AnimeModel value)
{
OpenFileDialog openFileDialog =
new() { Title = "选择图片".Translate(), Filter = $"图片|*.png".Translate() };
@ -303,7 +325,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// 清空图片
/// </summary>
/// <param name="value">动画模型</param>
private void ClearImageCommand_ExecuteEvent(AnimeModel value)
private void ClearImageCommand_ExecuteCommand(AnimeModel value)
{
if (
MessageBox.Show("确定清空吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.Yes
@ -319,7 +341,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// </summary>
/// <param name="images">动画</param>
/// <param name="paths">路径</param>
public void AddImages(ObservableCollection<ImageModel> images, IEnumerable<string> paths)
public void AddImages(ObservableList<ImageModel> images, IEnumerable<string> paths)
{
try
{
@ -348,27 +370,16 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
}
#endregion
#region Player
private void CurrentAnimeModel_ValueChanged(
ObservableValue<AnimeModel> sender,
ValueChangedEventArgs<AnimeModel> e
)
{
StopCommand_ExecuteEvent();
if (e.OldValue is not null)
e.OldValue.Images.CollectionChanged -= Images_CollectionChanged;
if (e.NewValue is not null)
e.NewValue.Images.CollectionChanged += Images_CollectionChanged;
}
private void Images_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void Images_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
StopCommand_ExecuteEvent();
StopCommand_ExecuteCommand();
}
/// <summary>
/// 停止播放
/// </summary>
private void StopCommand_ExecuteEvent()
private void StopCommand_ExecuteCommand()
{
_playing = false;
}
@ -376,7 +387,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
/// <summary>
/// 开始播放
/// </summary>
private async Task PlayCommand_AsyncExecuteEvent()
private async Task PlayCommand_ExecuteAsyncCommand()
{
if (CurrentAnimeModel is null)
{
@ -385,7 +396,7 @@ public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
}
_playing = true;
_playerTask.Start();
await Task.WhenAll(_playerTask);
await _playerTask;
Reset();
}

View File

@ -18,51 +18,94 @@ namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class AnimePageVM : ObservableObjectX<AnimePageVM>
{
public AnimePageVM()
{
AllAnimes = new()
{
Filter = (f) =>
{
if (f is AnimeTypeModel animeModel)
{
return animeModel.ID.Contains(Search, StringComparison.OrdinalIgnoreCase);
}
else if (f is FoodAnimeTypeModel foodAnimeModel)
{
return foodAnimeModel.ID.Contains(Search, StringComparison.OrdinalIgnoreCase);
}
else
throw new Exception("???");
},
FilteredList = new()
};
PropertyChangedX += AnimePageVM_PropertyChangedX;
AddCommand.ExecuteCommand += AddCommand_ExecuteCommand;
EditCommand.ExecuteCommand += EditCommand_ExecuteCommand;
RemoveCommand.ExecuteCommand += RemoveCommand_ExecuteCommand;
}
private void AnimePageVM_PropertyChangedX(AnimePageVM sender, PropertyChangedXEventArgs e)
{
if (e.PropertyName == nameof(CurrentPet))
{
InitializeAllAnimes();
}
else if (e.PropertyName == nameof(Search))
{
AllAnimes.Refresh();
}
}
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
#region Property
/// <summary>
/// 显示的动画
/// 所有动画
/// </summary>
#region ShowAnimes
#region AllAnimes
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<object> _showAnimes;
private ObservableFilterList<object, ObservableList<object>> _allAnimes = null!;
public ObservableCollection<object> ShowAnimes
public ObservableFilterList<object, ObservableList<object>> AllAnimes
{
get => _showAnimes;
set => SetProperty(ref _showAnimes, value);
get => _allAnimes;
set => SetProperty(ref _allAnimes, value);
}
#endregion
/// <summary>
/// 所有动画
/// </summary>
public ObservableCollection<object> AllAnimes { get; } = new();
/// <summary>
/// 动画
/// </summary>
public ObservableCollection<AnimeTypeModel> Animes => CurrentPet.Value.Animes;
public ObservableList<AnimeTypeModel> Animes => CurrentPet.Animes;
/// <summary>
/// 食物动画
/// </summary>
public ObservableCollection<FoodAnimeTypeModel> FoodAnimes => CurrentPet.Value.FoodAnimes;
public ObservableList<FoodAnimeTypeModel> FoodAnimes => CurrentPet.FoodAnimes;
/// <summary>
/// 宠物列表
/// </summary>
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public static ObservableList<PetModel> Pets => ModInfoModel.Current.Pets;
#region CurrentPEt
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _currentPet = null!;
/// <summary>
/// 当前宠物
/// </summary>
public ObservableValue<PetModel> CurrentPet { get; } = new(new());
public PetModel CurrentPet
{
get => _currentPet;
set => SetProperty(ref _currentPet, value);
}
#endregion
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
private string _search = string.Empty;
/// <summary>
/// 搜索
@ -90,18 +133,6 @@ public class AnimePageVM : ObservableObjectX<AnimePageVM>
/// </summary>
public ObservableCommand<object> RemoveCommand { get; } = new();
#endregion
public AnimePageVM()
{
ShowAnimes = AllAnimes;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
}
private void InitializeAllAnimes()
{
AllAnimes.Clear();
@ -109,70 +140,32 @@ public class AnimePageVM : ObservableObjectX<AnimePageVM>
AllAnimes.Add(item);
foreach (var item in FoodAnimes)
AllAnimes.Add(item);
Animes.CollectionChanged -= Animes_CollectionChanged;
Animes.CollectionChanged += Animes_CollectionChanged;
FoodAnimes.CollectionChanged -= Animes_CollectionChanged;
FoodAnimes.CollectionChanged += Animes_CollectionChanged;
}
private void Animes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void Animes_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action is NotifyCollectionChangedAction.Add)
AllAnimes.Add(e.NewItems[0]);
AllAnimes.Add(e.NewItems![0]!);
else if (e.Action is NotifyCollectionChangedAction.Remove)
AllAnimes.Remove(e.OldItems[0]);
AllAnimes.Remove(e.OldItems![0]!);
else if (e.Action is NotifyCollectionChangedAction.Replace)
AllAnimes[AllAnimes.IndexOf(e.OldItems[0])] = e.NewItems[0];
}
private void CurrentPet_ValueChanged(
ObservableValue<PetModel> sender,
ValueChangedEventArgs<PetModel> e
)
{
InitializeAllAnimes();
ShowAnimes = AllAnimes;
}
private void Search_ValueChanged(
ObservableValue<string> sender,
ValueChangedEventArgs<string> e
)
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowAnimes = AllAnimes;
}
else
{
ShowAnimes = new(
AllAnimes.Where(m =>
{
if (m is AnimeTypeModel animeTypeModel)
return animeTypeModel.Id.Contains(
e.NewValue,
StringComparison.OrdinalIgnoreCase
);
else if (m is FoodAnimeTypeModel foodAnimeTypeModel)
return foodAnimeTypeModel.Id.Contains(
e.NewValue,
StringComparison.OrdinalIgnoreCase
);
else
throw new Exception("???");
})
);
}
AllAnimes[AllAnimes.IndexOf(e.OldItems![0]!)] = e.NewItems![0]!;
}
/// <summary>
/// 添加动画
/// </summary>
private void Add()
private void AddCommand_ExecuteCommand()
{
var selectGraphTypeWindow = new SelectGraphTypeWindow();
selectGraphTypeWindow.CurrentPet.Value = CurrentPet.Value;
selectGraphTypeWindow.ViewModel.CurrentPet = CurrentPet;
selectGraphTypeWindow.ShowDialog();
var graphType = selectGraphTypeWindow.GraphType.Value;
var animeName = selectGraphTypeWindow.AnimeName.Value;
var graphType = selectGraphTypeWindow.ViewModel.GraphType;
var animeName = selectGraphTypeWindow.ViewModel.AnimeName;
if (selectGraphTypeWindow.IsCancel)
return;
if (
@ -182,24 +175,24 @@ public class AnimePageVM : ObservableObjectX<AnimePageVM>
{
var window = new FoodAnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.Anime.Value.Name = animeName;
vm.CurrentPet = CurrentPet;
vm.Anime.Name = animeName;
window.ShowDialog();
if (window.IsCancel)
return;
FoodAnimes.Add(vm.Anime.Value);
FoodAnimes.Add(vm.Anime);
}
else
{
var window = new AnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.Anime.Value.GraphType = graphType;
vm.Anime.Value.Name = animeName;
vm.CurrentPet = CurrentPet;
vm.Anime.GraphType = graphType;
vm.Anime.Name = animeName;
window.ShowDialog();
if (window.IsCancel)
return;
Animes.Add(vm.Anime.Value);
Animes.Add(vm.Anime);
}
}
@ -207,38 +200,34 @@ public class AnimePageVM : ObservableObjectX<AnimePageVM>
/// 编辑动画
/// </summary>
/// <param name="model">动画类型模型</param>
public void Edit(object model)
public void EditCommand_ExecuteCommand(object model)
{
var pendingHandler = PendingBox.Show("载入中".Translate());
if (model is AnimeTypeModel animeTypeModel)
{
var window = new AnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
vm.OldAnime = animeTypeModel;
var newAnime = vm.Anime.Value = new(animeTypeModel);
var newAnime = vm.Anime = new(animeTypeModel);
pendingHandler.Close();
window.ShowDialog();
if (window.IsCancel)
return;
Animes[Animes.IndexOf(animeTypeModel)] = newAnime;
if (ShowAnimes.Count != Animes.Count)
ShowAnimes[ShowAnimes.IndexOf(animeTypeModel)] = newAnime;
}
else if (model is FoodAnimeTypeModel foodAnimeTypeModel)
{
var window = new FoodAnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
vm.OldAnime = foodAnimeTypeModel;
var newAnime = vm.Anime.Value = new(foodAnimeTypeModel);
var newAnime = vm.Anime = new(foodAnimeTypeModel);
pendingHandler.Close();
window.ShowDialog();
if (window.IsCancel)
return;
FoodAnimes[FoodAnimes.IndexOf(foodAnimeTypeModel)] = newAnime;
if (ShowAnimes.Count != FoodAnimes.Count)
ShowAnimes[ShowAnimes.IndexOf(foodAnimeTypeModel)] = newAnime;
}
}
@ -246,11 +235,11 @@ public class AnimePageVM : ObservableObjectX<AnimePageVM>
/// 删除动画
/// </summary>
/// <param name="model">动画类型模型</param>
private void Remove(object model)
private void RemoveCommand_ExecuteCommand(object model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
ShowAnimes.Remove(model);
AllAnimes.Remove(model);
if (model is AnimeTypeModel animeTypeModel)
{
Animes.Remove(animeTypeModel);

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
@ -20,6 +21,62 @@ namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
{
public FoodAnimeEditWindowVM()
{
_frontPlayerTask = new(FrontPlay);
_backPlayerTask = new(BackPlay);
_foodPlayerTask = new(FoodPlay);
PropertyChangedX += FoodAnimeEditWindowVM_PropertyChangedX;
;
PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
ReplaceFoodImageCommand.ExecuteCommand += ChangeFoodImageCommand_ExecuteEvent;
ResetFoodImageCommand.ExecuteCommand += ResetFoodImageCommand_ExecuteEvent;
AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteEvent;
AddFrontImageCommand.ExecuteCommand += AddFrontImageCommand_ExecuteEvent;
RemoveFrontImageCommand.ExecuteCommand += RemoveFrontImageCommand_ExecuteEvent;
ClearFrontImageCommand.ExecuteCommand += ClearFrontImageCommand_ExecuteEvent;
ChangeFrontImageCommand.ExecuteCommand += ChangeFrontImageCommand_ExecuteEvent;
AddBackImageCommand.ExecuteCommand += AddBackImageCommand_ExecuteEvent;
RemoveBackImageCommand.ExecuteCommand += RemoveBackImageCommand_ExecuteEvent;
ClearBackImageCommand.ExecuteCommand += ClearBackImageCommand_ExecuteEvent;
ChangeBackImageCommand.ExecuteCommand += ChangeBackImageCommand_ExecuteEvent;
AddFoodLocationCommand.ExecuteCommand += AddeFoodLocationCommand_ExecuteEvent;
RemoveFoodLocationCommand.ExecuteCommand += RemoveFoodLocationCommand_ExecuteEvent;
ClearFoodLocationCommand.ExecuteCommand += ClearFoodLocationCommand_ExecuteEvent;
}
private void FoodAnimeEditWindowVM_PropertyChangedX(
FoodAnimeEditWindowVM sender,
PropertyChangedXEventArgs e
)
{
if (e.PropertyName == nameof(CurrentAnimeModel))
{
var newModel = e.NewValue as FoodAnimeModel;
var oldModel = e.OldValue as FoodAnimeModel;
StopCommand_ExecuteEvent();
if (oldModel is not null)
{
oldModel.FrontImages.CollectionChanged -= Images_CollectionChanged;
oldModel.BackImages.CollectionChanged -= Images_CollectionChanged;
oldModel.FoodLocations.CollectionChanged -= Images_CollectionChanged;
}
if (newModel is not null)
{
newModel.FrontImages.CollectionChanged += Images_CollectionChanged;
newModel.BackImages.CollectionChanged += Images_CollectionChanged;
newModel.FoodLocations.CollectionChanged += Images_CollectionChanged;
}
}
}
/// <summary>
/// 当前宠物
/// </summary>
@ -67,7 +124,16 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// <summary>
/// 动画
/// </summary>
public ObservableValue<FoodAnimeTypeModel> Anime { get; } = new(new());
#region Anime
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private FoodAnimeTypeModel _anime = new();
public FoodAnimeTypeModel Anime
{
get => _anime;
set => SetProperty(ref _anime, value);
}
#endregion
#region CurrentFrontImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -284,37 +350,6 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// </summary>
private Task _foodPlayerTask;
public FoodAnimeEditWindowVM()
{
_frontPlayerTask = new(FrontPlay);
_backPlayerTask = new(BackPlay);
_foodPlayerTask = new(FoodPlay);
//TODO
//CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
ReplaceFoodImageCommand.ExecuteCommand += ChangeFoodImageCommand_ExecuteEvent;
ResetFoodImageCommand.ExecuteCommand += ResetFoodImageCommand_ExecuteEvent;
AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteEvent;
AddFrontImageCommand.ExecuteCommand += AddFrontImageCommand_ExecuteEvent;
RemoveFrontImageCommand.ExecuteCommand += RemoveFrontImageCommand_ExecuteEvent;
ClearFrontImageCommand.ExecuteCommand += ClearFrontImageCommand_ExecuteEvent;
ChangeFrontImageCommand.ExecuteCommand += ChangeFrontImageCommand_ExecuteEvent;
AddBackImageCommand.ExecuteCommand += AddBackImageCommand_ExecuteEvent;
RemoveBackImageCommand.ExecuteCommand += RemoveBackImageCommand_ExecuteEvent;
ClearBackImageCommand.ExecuteCommand += ClearBackImageCommand_ExecuteEvent;
ChangeBackImageCommand.ExecuteCommand += ChangeBackImageCommand_ExecuteEvent;
AddFoodLocationCommand.ExecuteCommand += AddeFoodLocationCommand_ExecuteEvent;
RemoveFoodLocationCommand.ExecuteCommand += RemoveFoodLocationCommand_ExecuteEvent;
ClearFoodLocationCommand.ExecuteCommand += ClearFoodLocationCommand_ExecuteEvent;
}
private void ResetFoodImageCommand_ExecuteEvent()
{
if (FoodImage != DefaultFoodImage)
@ -353,13 +388,13 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
private void AddAnimeCommand_ExecuteEvent()
{
if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Add(new());
Anime.HappyAnimes.Add(new());
else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Add(new());
Anime.NomalAnimes.Add(new());
else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Add(new());
Anime.PoorConditionAnimes.Add(new());
else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Add(new());
Anime.IllAnimes.Add(new());
}
/// <summary>
@ -374,13 +409,13 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
)
{
if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Remove(value);
Anime.HappyAnimes.Remove(value);
else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Remove(value);
Anime.NomalAnimes.Remove(value);
else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Remove(value);
Anime.PoorConditionAnimes.Remove(value);
else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Remove(value);
Anime.IllAnimes.Remove(value);
value.Close();
}
}
@ -540,7 +575,7 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// </summary>
/// <param name="images">动画</param>
/// <param name="paths">路径</param>
public void AddImages(ObservableCollection<ImageModel> images, IEnumerable<string> paths)
public void AddImages(ObservableList<ImageModel> images, IEnumerable<string> paths)
{
try
{
@ -591,27 +626,8 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
}
#endregion
#region FrontPlayer
private void CurrentAnimeModel_ValueChanged(
ObservableValue<FoodAnimeModel> sender,
ValueChangedEventArgs<FoodAnimeModel> e
)
{
StopCommand_ExecuteEvent();
if (e.OldValue is not null)
{
e.OldValue.FrontImages.CollectionChanged -= Images_CollectionChanged;
e.OldValue.BackImages.CollectionChanged -= Images_CollectionChanged;
e.OldValue.FoodLocations.CollectionChanged -= Images_CollectionChanged;
}
if (e.NewValue is not null)
{
e.NewValue.FrontImages.CollectionChanged += Images_CollectionChanged;
e.NewValue.BackImages.CollectionChanged += Images_CollectionChanged;
e.NewValue.FoodLocations.CollectionChanged += Images_CollectionChanged;
}
}
private void Images_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void Images_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
StopCommand_ExecuteEvent();
}

View File

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Extensions;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class SelectGraphTypeWindowVM : ObservableObjectX<SelectGraphTypeWindowVM>
{
public SelectGraphTypeWindowVM()
{
PropertyChanged += SelectGraphTypeWindowVM_PropertyChanged;
}
private void SelectGraphTypeWindowVM_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(CurrentPet))
{
GraphTypes = new(
AnimeTypeModel.GraphTypes.Except(CurrentPet.Animes.Select(m => m.GraphType))
);
// 可添加多个项的类型
GraphTypes.AddRange(AnimeTypeModel.HasNameAnimes);
}
else if (e.PropertyName == nameof(GraphType))
{
if (GraphType.IsHasNameAnime())
HasNameAnime = true;
else
HasNameAnime = false;
}
}
#region CurrentPet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _currentPet = null!;
/// <summary>
/// 当前宠物
/// </summary>
public PetModel CurrentPet
{
get => _currentPet;
set => SetProperty(ref _currentPet, value);
}
#endregion
#region GraphType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GraphInfo.GraphType _graphType;
/// <summary>
/// 动画类型
/// </summary>
public GraphInfo.GraphType GraphType
{
get => _graphType;
set => SetProperty(ref _graphType, value);
}
#endregion
#region GraphTypes
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableSet<GraphInfo.GraphType> _graphTypes = new();
/// <summary>
/// 动画类型列表
/// </summary>
public ObservableSet<GraphInfo.GraphType> GraphTypes
{
get => _graphTypes;
set => SetProperty(ref _graphTypes, value);
}
#endregion
#region AnimeName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _animeName = string.Empty;
/// <summary>
/// 动画名称
/// </summary>
public string AnimeName
{
get => _animeName;
set => SetProperty(ref _animeName, value);
}
#endregion
#region HasNameAnime
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _hasNameAnime = true;
/// <summary>
/// 具有动画名称
/// </summary>
public bool HasNameAnime
{
get => _hasNameAnime;
set => SetProperty(ref _hasNameAnime, value);
}
#endregion
}

View File

@ -35,16 +35,16 @@ public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
// /// <summary>
// /// 全部I18n数据
// /// </summary>
// public ObservableCollection<I18nData> I18nDatas { get; } = new();
// public ObservableList<I18nData> I18nDatas { get; } = new();
// /// <summary>
// /// 显示的I18n数据
// /// </summary>
// #region ShowI18nDatas
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private ObservableCollection<I18nData> _showI18nDatas;
// private ObservableList<I18nData> _showI18nDatas;
// public ObservableCollection<I18nData> ShowI18nDatas
// public ObservableList<I18nData> ShowI18nDatas
// {
// get => _showI18nDatas;
// set => SetProperty(ref _showI18nDatas, value);
@ -54,7 +54,7 @@ public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
// /// <summary>
// /// 搜索目标列表
// /// </summary>
// public ObservableCollection<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) };
// public ObservableList<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) };
// /// <summary>
// /// 搜索目标
@ -117,7 +117,7 @@ public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
// /// </summary>
// /// <param name="sender"></param>
// /// <param name="e"></param>
// private void CultureNames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
// private void CultureNames_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {

View File

@ -26,7 +26,8 @@ public class ModEditWindowVM : ObservableObjectX<ModEditWindowVM>
{
public ModEditWindowVM(ModEditWindow window)
{
I18nEditWindow.Initialize();
//TODO
//I18nEditWindow.Initialize();
ModEditWindow = window;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
AddCultureCommand.ExecuteCommand += AddCultureCommand_ExecuteCommand;
@ -210,8 +211,8 @@ public class ModEditWindowVM : ObservableObjectX<ModEditWindowVM>
is not MessageBoxResult.Yes
)
return;
ModInfo.I18nDatas[culture].Name = ModInfo.Id;
ModInfo.I18nDatas[culture].Description = ModInfo.DescriptionId;
ModInfo.I18nDatas[culture].Name = ModInfo.ID;
ModInfo.I18nDatas[culture].Description = ModInfo.DescriptionID;
foreach (var food in ModInfo.Foods)
{
food.I18nDatas[culture].Name = food.ID;
@ -229,10 +230,10 @@ public class ModEditWindowVM : ObservableObjectX<ModEditWindowVM>
foreach (var pet in ModInfo.Pets)
{
pet.I18nDatas[culture].Name = pet.ID;
pet.I18nDatas[culture].PetName = pet.PetNameId;
pet.I18nDatas[culture].Description = pet.DescriptionId;
pet.I18nDatas[culture].PetName = pet.PetNameID;
pet.I18nDatas[culture].Description = pet.DescriptionID;
foreach (var work in pet.Works)
work.I18nDatas[culture].Name = work.Id;
work.I18nDatas[culture].Name = work.ID;
}
}
#endregion
@ -311,7 +312,7 @@ public class ModEditWindowVM : ObservableObjectX<ModEditWindowVM>
);
return false;
}
if (string.IsNullOrWhiteSpace(model.Id))
if (string.IsNullOrWhiteSpace(model.ID))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return false;

View File

@ -14,9 +14,16 @@ namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit;
public class MoveEditWindowVM : ObservableObjectX<MoveEditWindowVM>
{
#region Value
public PetModel CurrentPet { get; set; }
public MoveModel OldMove { get; set; }
public MoveEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImageCommand_ExecuteCommand;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
//Image.ValueChanged += Image_ValueChanged;
}
#region Property
public PetModel CurrentPet { get; set; } = null!;
public MoveModel? OldMove { get; set; }
#region Move
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -51,9 +58,9 @@ public class MoveEditWindowVM : ObservableObjectX<MoveEditWindowVM>
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
private BitmapImage? _image;
public BitmapImage Image
public BitmapImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
@ -63,13 +70,6 @@ public class MoveEditWindowVM : ObservableObjectX<MoveEditWindowVM>
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
#endregion
public MoveEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
//TODO
//Image.ValueChanged += Image_ValueChanged;
}
private void Image_ValueChanged(
ObservableValue<BitmapImage> sender,
@ -84,28 +84,26 @@ public class MoveEditWindowVM : ObservableObjectX<MoveEditWindowVM>
Image?.StreamSource?.Close();
}
private void AddImage()
private void AddImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
private void ChangeImage()
private void ChangeImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Image?.StreamSource?.Close();

View File

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
@ -15,27 +17,50 @@ namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit;
public class MovePageVM : ObservableObjectX<MovePageVM>
{
public MovePageVM()
{
Moves = new()
{
Filter = f => f.Graph.Contains(Search, StringComparison.OrdinalIgnoreCase),
FilteredList = new()
};
PropertyChanged += MovePageVM_PropertyChanged;
AddCommand.ExecuteCommand += AddCommand_ExecuteCommand;
EditCommand.ExecuteCommand += EditCommand_ExecuteCommand;
RemoveCommand.ExecuteCommand += RemoveCommand_ExecuteCommand;
}
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
#region Property
#region ShowMoves
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<MoveModel> _showMoves;
private ObservableFilterList<MoveModel, ObservableList<MoveModel>> _moves;
public ObservableCollection<MoveModel> ShowMoves
public ObservableFilterList<MoveModel, ObservableList<MoveModel>> Moves
{
get => _showMoves;
set => SetProperty(ref _showMoves, value);
get => _moves;
set => SetProperty(ref _moves, value);
}
#endregion
public ObservableCollection<MoveModel> Moves => CurrentPet.Value.Moves;
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public ObservableValue<PetModel> CurrentPet { get; } = new(new());
public static ObservableList<PetModel> Pets => ModInfoModel.Current.Pets;
#region CurrentPet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _currentPet;
public PetModel CurrentPet
{
get => _currentPet;
set => SetProperty(ref _currentPet, value);
}
#endregion
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
private string _search = string.Empty;
public string Search
{
@ -49,83 +74,49 @@ public class MovePageVM : ObservableObjectX<MovePageVM>
public ObservableCommand<MoveModel> EditCommand { get; } = new();
public ObservableCommand<MoveModel> RemoveCommand { get; } = new();
#endregion
public MovePageVM()
private void MovePageVM_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
ShowMoves = Moves;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
}
private void CurrentPet_ValueChanged(
ObservableValue<PetModel> sender,
ValueChangedEventArgs<PetModel> e
)
{
//ShowMoves.Value = e.NewValue.Moves;
}
private void Search_ValueChanged(
ObservableValue<string> sender,
ValueChangedEventArgs<string> e
)
{
if (string.IsNullOrWhiteSpace(e.NewValue))
if (e.PropertyName == nameof(CurrentPet))
{
ShowMoves = Moves;
Moves.Clear();
Moves.AddRange(CurrentPet.Moves);
}
else
else if (e.PropertyName == nameof(Search))
{
ShowMoves = new(
Moves.Where(m => m.Graph.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
Moves.Refresh();
}
}
public void Close() { }
private void Add()
private void AddCommand_ExecuteCommand()
{
var window = new MoveEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
window.ShowDialog();
if (window.IsCancel)
return;
Moves.Add(vm.Move);
}
public void Edit(MoveModel model)
public void EditCommand_ExecuteCommand(MoveModel model)
{
var window = new MoveEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
vm.OldMove = model;
var newMove = vm.Move = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
Moves[Moves.IndexOf(model)] = newMove;
if (ShowMoves.Count != Moves.Count)
ShowMoves[ShowMoves.IndexOf(model)] = newMove;
}
private void Remove(MoveModel model)
private void RemoveCommand_ExecuteCommand(MoveModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowMoves.Count == Moves.Count)
{
Moves.Remove(model);
}
else
{
ShowMoves.Remove(model);
Moves.Remove(model);
}
Moves.Remove(model);
}
}

View File

@ -15,17 +15,25 @@ namespace VPet.ModMaker.ViewModels.ModEdit.PetEdit;
public class PetEditWindowVM : ObservableObjectX<PetEditWindowVM>
{
public I18nHelper I18nData => I18nHelper.Current;
public PetModel OldPet { get; set; }
public PetEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImageCommand_ExecuteCommand;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
//Image.ValueChanged += Image_ValueChanged;
}
#region Property
public static I18nHelper I18nData => I18nHelper.Current;
public PetModel? OldPet { get; set; }
#region Pet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _Pet;
private PetModel _pet = new();
public PetModel Pet
{
get => _Pet;
set => SetProperty(ref _Pet, value);
get => _pet;
set => SetProperty(ref _pet, value);
}
#endregion
@ -41,7 +49,7 @@ public class PetEditWindowVM : ObservableObjectX<PetEditWindowVM>
#endregion
#region LengthRatio
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _lengthRatio = 250 / 500;
private double _lengthRatio = 0.5;
public double LengthRatio
{
@ -51,26 +59,20 @@ public class PetEditWindowVM : ObservableObjectX<PetEditWindowVM>
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
private BitmapImage? _image;
public BitmapImage Image
public BitmapImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
#endregion
public PetEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
//TODO
//Image.ValueChanged += Image_ValueChanged;
}
private void Image_ValueChanged(
ObservableValue<BitmapImage> sender,
ValueChangedEventArgs<BitmapImage> e
@ -84,28 +86,26 @@ public class PetEditWindowVM : ObservableObjectX<PetEditWindowVM>
Image?.CloseStream();
}
private void AddImage()
private void AddImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
private void ChangeImage()
private void ChangeImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Image?.StreamSource?.Close();

View File

@ -24,9 +24,9 @@ public class PetPageVM : ObservableObjectX<PetPageVM>
FilteredList = new()
};
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
AddCommand.ExecuteCommand += AddCommand_ExecuteCommand;
EditCommand.ExecuteCommand += EditCommand_ExecuteCommand;
RemoveCommand.ExecuteCommand += RemoveCommand_ExecuteCommand;
}
public static ModInfoModel ModInfo => ModInfoModel.Current;
@ -66,7 +66,7 @@ public class PetPageVM : ObservableObjectX<PetPageVM>
public void Close() { }
private void Add()
private void AddCommand_ExecuteCommand()
{
var window = new PetEditWindow();
var vm = window.ViewModel;
@ -76,7 +76,7 @@ public class PetPageVM : ObservableObjectX<PetPageVM>
Pets.Add(vm.Pet);
}
public void Edit(PetModel model)
public void EditCommand_ExecuteCommand(PetModel model)
{
if (model.FromMain)
{
@ -106,7 +106,7 @@ public class PetPageVM : ObservableObjectX<PetPageVM>
model.Close();
}
private void Remove(PetModel model)
private void RemoveCommand_ExecuteCommand(PetModel model)
{
if (model.FromMain)
{

View File

@ -29,7 +29,7 @@ public class SaveTranslationModWindowVM : ObservableObjectX<SaveTranslationModWi
}
#endregion
public ObservableCollection<CheckCultureModel> CheckCultures { get; } = [];
public ObservableList<CheckCultureModel> CheckCultures { get; } = [];
#endregion
#region Command

View File

@ -1,29 +1,109 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit;
public class WorkEditWindowVM : ObservableObjectX<WorkEditWindowVM>
{
public WorkEditWindowVM()
{
PropertyChangedX += WorkEditWindowVM_PropertyChangedX;
Work.PropertyChanged += NewWork_PropertyChanged;
AddImageCommand.ExecuteCommand += AddImageCommand_ExecuteCommand;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
FixOverLoadCommand.ExecuteCommand += FixOverLoadCommand_ExecuteCommand;
}
private void WorkEditWindowVM_PropertyChangedX(
WorkEditWindowVM sender,
PropertyChangedXEventArgs e
)
{
if (e.PropertyName == nameof(Work))
{
var newWork = e.NewValue as WorkModel;
var oldWork = e.OldValue as WorkModel;
if (oldWork is not null)
{
oldWork.PropertyChanged -= NewWork_PropertyChanged;
}
if (newWork is not null)
{
newWork.PropertyChanged -= NewWork_PropertyChanged;
newWork.PropertyChanged += NewWork_PropertyChanged;
SetGraphImage(newWork);
}
}
}
private void NewWork_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (sender is not WorkModel workModel)
return;
if (e.PropertyName == nameof(WorkModel.Graph))
{
SetGraphImage(workModel);
}
}
private void SetGraphImage(WorkModel workModel)
{
if (CurrentPet is null)
return;
var graph = workModel.Graph;
Image?.CloseStream();
Image = null;
// 随机挑一张图片
if (
CurrentPet.Animes.FirstOrDefault(
a =>
a.GraphType is VPet_Simulator.Core.GraphInfo.GraphType.Work
&& a.Name.Equals(graph, StringComparison.OrdinalIgnoreCase),
null!
)
is not AnimeTypeModel anime
)
return;
if (anime.HappyAnimes.HasValue())
{
Image = anime.HappyAnimes.Random().Images.Random().Image.CloneStream();
}
else if (anime.NomalAnimes.HasValue())
{
Image = anime.NomalAnimes.Random().Images.Random().Image.CloneStream();
}
else if (anime.PoorConditionAnimes.HasValue())
{
Image = anime.PoorConditionAnimes.Random().Images.Random().Image.CloneStream();
}
else if (anime.IllAnimes.HasValue())
{
Image = anime.IllAnimes.Random().Images.Random().Image.CloneStream();
}
}
public static ModInfoModel ModInfo => ModInfoModel.Current;
public static I18nHelper I18nData => I18nHelper.Current;
#region Value
public PetModel CurrentPet { get; set; }
public WorkModel OldWork { get; set; }
#region Property
public PetModel CurrentPet { get; set; } = null!;
public WorkModel? OldWork { get; set; }
#region Work
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private WorkModel _work;
private WorkModel _work = new();
public WorkModel Work
{
@ -52,52 +132,59 @@ public class WorkEditWindowVM : ObservableObjectX<WorkEditWindowVM>
set => SetProperty(ref _lengthRatio, value);
}
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage? _image;
/// <summary>
/// 图片
/// </summary>
public BitmapImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#region Command
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
public ObservableCommand FixOverLoadCommand { get; } = new();
#endregion
public WorkEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
FixOverLoadCommand.ExecuteCommand += FixOverLoadCommand_ExecuteCommand;
}
private void FixOverLoadCommand_ExecuteCommand()
{
//var work = Work.ToWork();
//work.FixOverLoad();
//Work = new(work);
Work.FixOverLoad();
}
private void AddImage()
private void AddImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Work.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
private void ChangeImage()
private void ChangeImageCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
var openFileDialog = new OpenFileDialog()
{
Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
};
if (openFileDialog.ShowDialog() is true)
{
Work.Image?.CloseStream();
Work.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image?.CloseStream();
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
public void Close()
{
Image?.CloseStream();
}
}

View File

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
@ -15,22 +17,34 @@ namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit;
public class WorkPageVM : ObservableObjectX<WorkPageVM>
{
public WorkPageVM()
{
Works = new()
{
Filter = f => f.ID.Contains(Search, StringComparison.OrdinalIgnoreCase),
FilteredList = new()
};
PropertyChanged += WorkPageVM_PropertyChanged;
AddCommand.ExecuteCommand += AddCommand_ExecuteCommand;
EditCommand.ExecuteCommand += EditCommand_ExecuteCommand;
RemoveCommand.ExecuteCommand += RemoveCommand_ExecuteCommand;
}
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
#region ShowWorks
#region Property
#region Works
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<WorkModel> _showWorks;
private ObservableFilterList<WorkModel, ObservableList<WorkModel>> _works;
public ObservableCollection<WorkModel> ShowWorks
public ObservableFilterList<WorkModel, ObservableList<WorkModel>> Works
{
get => _showWorks;
set => SetProperty(ref _showWorks, value);
get => _works;
set => SetProperty(ref _works, value);
}
#endregion
public ObservableCollection<WorkModel> Works => CurrentPet.Works;
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public static ObservableList<PetModel> Pets => ModInfoModel.Current.Pets;
#region CurrentPet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -45,7 +59,7 @@ public class WorkPageVM : ObservableObjectX<WorkPageVM>
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
private string _search = string.Empty;
public string Search
{
@ -59,44 +73,20 @@ public class WorkPageVM : ObservableObjectX<WorkPageVM>
public ObservableCommand<WorkModel> EditCommand { get; } = new();
public ObservableCommand<WorkModel> RemoveCommand { get; } = new();
#endregion
public WorkPageVM()
private void WorkPageVM_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
ShowWorks = Works;
//TODO
//CurrentPet.ValueChanged += CurrentPet_ValueChanged;
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
}
private void CurrentPet_ValueChanged(
ObservableValue<PetModel> sender,
ValueChangedEventArgs<PetModel> e
)
{
ShowWorks = e.NewValue.Works;
}
private void Search_ValueChanged(
ObservableValue<string> sender,
ValueChangedEventArgs<string> e
)
{
if (string.IsNullOrWhiteSpace(e.NewValue))
if (e.PropertyName == nameof(CurrentPet))
{
ShowWorks = Works;
Works.Clear();
Works.AddRange(CurrentPet.Works);
}
else
else if (e.PropertyName == nameof(Search))
{
ShowWorks = new(
Works.Where(m => m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
Works.Refresh();
}
}
private void Add()
private void AddCommand_ExecuteCommand()
{
var window = new WorkEditWindow();
var vm = window.ViewModel;
@ -107,7 +97,7 @@ public class WorkPageVM : ObservableObjectX<WorkPageVM>
Works.Add(vm.Work);
}
public void Edit(WorkModel model)
public void EditCommand_ExecuteCommand(WorkModel model)
{
var window = new WorkEditWindow();
var vm = window.ViewModel;
@ -118,22 +108,14 @@ public class WorkPageVM : ObservableObjectX<WorkPageVM>
if (window.IsCancel)
return;
Works[Works.IndexOf(model)] = newWork;
if (ShowWorks.Count != Works.Count)
ShowWorks[ShowWorks.IndexOf(model)] = newWork;
model.Close();
}
private void Remove(WorkModel model)
private void RemoveCommand_ExecuteCommand(WorkModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowWorks.Count == Works.Count)
{
Works.Remove(model);
}
else
{
ShowWorks.Remove(model);
Works.Remove(model);
}
Works.Remove(model);
model.Close();
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -8,6 +9,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using LinePutScript;
using LinePutScript.Converter;
@ -23,43 +25,63 @@ namespace VPet.ModMaker.ViewModels;
public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
{
#region Value
public ModMakerWindow ModMakerWindow { get; }
public ModMakerWindowVM(ModMakerWindow window)
{
Histories = new()
{
Filter = f => f.ID.Contains(Search, StringComparison.OrdinalIgnoreCase),
FilteredList = new()
};
LoadHistories();
ModMakerWindow = window;
PropertyChanged += ModMakerWindowVM_PropertyChanged;
CreateNewModCommand.ExecuteCommand += CreateNewModCommand_ExecuteCommand;
LoadModFromFileCommand.ExecuteCommand += LoadModFromFileCommand_ExecuteCommand;
ClearHistoriesCommand.ExecuteCommand += ClearHistoriesCommand_ExecuteCommand;
RemoveHistoryCommand.ExecuteCommand += RemoveHistoryCommand_ExecuteCommand;
}
public ModEditWindow ModEditWindow { get; private set; }
private void ModMakerWindowVM_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Search))
{
Histories.Refresh();
}
}
#region Property
public ModMakerWindow ModMakerWindow { get; } = null!;
public ModEditWindow ModEditWindow { get; private set; } = null!;
/// <summary>
/// 历史搜索文本
/// </summary>
#region HistoriesSearchText
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _historiesSearchText;
private string _search = string.Empty;
public string HistoriesSearchText
public string Search
{
get => _historiesSearchText;
set => SetProperty(ref _historiesSearchText, value);
}
#endregion
/// <summary>
/// 显示的历史
/// </summary>
#region ShowHistories
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<ModMakeHistory> _showHistories;
public ObservableCollection<ModMakeHistory> ShowHistories
{
get => _showHistories;
set => SetProperty(ref _showHistories, value);
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
/// <summary>
/// 历史
/// </summary>
public ObservableCollection<ModMakeHistory> Histories { get; set; } = new();
#region Histories
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableFilterList<ModMakeHistory, ObservableList<ModMakeHistory>> _histories = null!;
public ObservableFilterList<ModMakeHistory, ObservableList<ModMakeHistory>> Histories
{
get => _histories;
set => SetProperty(ref _histories, value);
}
#endregion
#endregion
#region Command
/// <summary>
@ -83,32 +105,8 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
public ObservableCommand<ModMakeHistory> RemoveHistoryCommand { get; } = new();
#endregion
public ModMakerWindowVM(ModMakerWindow window)
{
LoadHistories();
ModMakerWindow = window;
//TODO
ShowHistories = Histories;
CreateNewModCommand.ExecuteCommand += CreateNewMod;
LoadModFromFileCommand.ExecuteCommand += LoadModFromFile;
ClearHistoriesCommand.ExecuteCommand += ClearHistories;
RemoveHistoryCommand.ExecuteCommand += RemoveHistory;
//HistoriesSearchText.ValueChanged += HistoriesSearchText_ValueChanged;
}
private void HistoriesSearchText_ValueChanged(
ObservableValue<string> sender,
ValueChangedEventArgs<string> e
)
{
if (string.IsNullOrEmpty(e.NewValue))
ShowHistories = Histories;
else
ShowHistories = new(Histories.Where(i => i.Id.Contains(e.NewValue)));
}
#region History
private void RemoveHistory(ModMakeHistory value)
private void RemoveHistoryCommand_ExecuteCommand(ModMakeHistory value)
{
Histories.Remove(value);
SaveHistories();
@ -122,14 +120,14 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
if (File.Exists(ModMakerInfo.HistoryFile) is false)
return;
var lps = new LPS(File.ReadAllText(ModMakerInfo.HistoryFile));
var set = new HashSet<ModMakeHistory>();
foreach (var line in lps)
{
if (LPSConvert.DeserializeObject<ModMakeHistory>(line) is not ModMakeHistory history)
continue;
if (Histories.All(h => h.InfoFile != history.InfoFile))
Histories.Add(history);
set.Add(history);
}
Histories = new(Histories.OrderByDescending(h => h.LastTime));
Histories.AddRange(set.OrderByDescending(h => h.LastTime));
}
/// <summary>
@ -158,7 +156,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
is ModMakeHistory history
)
{
history.Id = modInfo.Id;
history.ID = modInfo.ID;
history.SourcePath = modInfo.SourcePath;
history.LastTime = DateTime.Now;
}
@ -167,7 +165,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
Histories.Add(
new()
{
Id = modInfo.Id,
ID = modInfo.ID,
SourcePath = modInfo.SourcePath,
LastTime = DateTime.Now,
}
@ -175,14 +173,14 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
}
}
private void ClearHistories()
private void ClearHistoriesCommand_ExecuteCommand()
{
if (
MessageBox.Show("确定要清空吗?".Translate(), "", MessageBoxButton.YesNo)
is not MessageBoxResult.Yes
)
return;
ShowHistories.Clear();
Histories.Clear();
Histories.Clear();
File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty);
}
@ -192,7 +190,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
/// <summary>
/// 创建新模组
/// </summary>
public void CreateNewMod()
public void CreateNewModCommand_ExecuteCommand()
{
ModInfoModel.Current = new();
ShowEditWindow();
@ -241,18 +239,17 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
/// <summary>
/// 从文件载入模组
/// </summary>
public void LoadModFromFile()
public void LoadModFromFileCommand_ExecuteCommand()
{
OpenFileDialog openFileDialog =
new()
{
Title = "模组信息文件".Translate(),
Filter = $"LPS文件|*.lps;".Translate(),
FileName = "info.lps"
};
var openFileDialog = new OpenFileDialog()
{
Title = "模组信息文件".Translate(),
Filter = $"LPS文件|*.lps;".Translate(),
FileName = "info.lps"
};
if (openFileDialog.ShowDialog() is true)
{
LoadMod(Path.GetDirectoryName(openFileDialog.FileName));
LoadMod(Path.GetDirectoryName(openFileDialog.FileName)!);
}
}
@ -279,19 +276,40 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
{
var modInfo = new ModInfoModel(loader);
EditMod(modInfo);
// 更新模组
if (ModUpdataHelper.CanUpdata(modInfo))
{
pendingHandler.Hide();
if (
MessageBox.Show(
ModEditWindow.Current,
"是否更新模组\n当前版本: {0}\n最新版本: {1}".Translate(
modInfo.ModVersion,
ModUpdataHelper.LastVersion
),
"更新模组".Translate(),
MessageBoxButton.YesNo
) is MessageBoxResult.Yes
)
{
if (ModUpdataHelper.Updata(modInfo))
MessageBox.Show("更新完成, 请手动保存".Translate());
}
}
pendingHandler.Close();
}
catch (Exception ex)
{
pendingHandler.Close();
ModEditWindow?.Close();
ModEditWindow = null;
ModEditWindow = null!;
ModInfoModel.Current?.Close();
I18nHelper.Current = new();
I18nEditWindow.Current?.Close(true);
ModMakerWindow.Show();
ModMakerWindow.Activate();
MessageBox.Show(ModMakerWindow, "模组载入失败:\n{0}".Translate(ex));
GC.Collect();
}
}
#endregion

View File

@ -39,12 +39,12 @@ public partial class AddCultureWindow : WindowX
TextBox_Lang.Dispatcher.InvokeAsync(TextBox_Lang.SelectAll);
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.Culture))
{
@ -60,7 +60,7 @@ public partial class AddCultureWindow : WindowX
Close();
}
private void Hyperlink_Click(object sender, RoutedEventArgs e)
private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{
Process.Start(
new ProcessStartInfo(

View File

@ -68,9 +68,9 @@
</TextBlock>
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}"
Text="{Binding Id, UpdateSourceTrigger=PropertyChanged}" />
<!-- pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}" -->
pu:TextBoxHelper.Watermark="{ll:Str 动画ID(非必要)}"
Text="{Binding ID, UpdateSourceTrigger=PropertyChanged}" />
<!-- pu:TextBoxHelper.Watermark="{ll:Str 动画ID(非必要)}" -->
<ComboBox
Grid.Column="2"
Margin="10,0,0,0"

View File

@ -43,18 +43,18 @@ public partial class AnimeEditWindow : Window
public bool IsCancel { get; private set; } = true;
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
IsCancel = false;
Close();
}
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (
sender is not TabControl tabControl
@ -70,7 +70,7 @@ public partial class AnimeEditWindow : Window
}
}
private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
private void ListBox_PreviewMouseWheel(object? sender, MouseWheelEventArgs e)
{
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
@ -84,7 +84,7 @@ public partial class AnimeEditWindow : Window
private object _dropSender;
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
private void ListBox_PreviewMouseMove(object? sender, MouseEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -102,7 +102,7 @@ public partial class AnimeEditWindow : Window
DragDrop.DoDragDrop(listBox, dataObj, DragDropEffects.Move);
}
private void ListBox_Drop(object sender, DragEventArgs e)
private void ListBox_Drop(object? sender, DragEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -136,7 +136,7 @@ public partial class AnimeEditWindow : Window
list[targetIndex] = temp;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void ListBox_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -146,7 +146,7 @@ public partial class AnimeEditWindow : Window
e.Handled = true;
}
private void ListBox_Animes_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void ListBox_Animes_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
e.Handled = true;
}

View File

@ -23,7 +23,7 @@
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}" Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}">
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索ID}" Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style BasedOn="{StaticResource StandardTextBoxStyle}" TargetType="TextBox">
<Setter Property="IsEnabled" Value="True" />
@ -61,7 +61,7 @@
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{ll:Str {} (来自本体)}" Visibility="{Binding FromMain, Converter={StaticResource FalseToCollapsedConverter}}" />
</StackPanel>
</DataTemplate>
@ -85,7 +85,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowAnimes}"
ItemsSource="{Binding AllAnimes.FilteredList}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="50"
@ -100,40 +100,40 @@
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Id}"
Binding="{Binding ID}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 动画类型}"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="ID" />
<DataGridTextColumn
Binding="{Binding HappyAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 开心状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="HappyAnimes.Count" />
<DataGridTextColumn
Binding="{Binding NomalAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 普通状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="NomalAnimes.Count" />
<DataGridTextColumn
Binding="{Binding PoorConditionAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 不开心状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="PoorConditionAnimes.Count" />
<DataGridTextColumn
Binding="{Binding IllAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 生病状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="IllAnimes.Count" />
</DataGrid.Columns>
</DataGrid>
<Button

View File

@ -30,10 +30,10 @@ public partial class AnimePage : Page
public AnimePageVM ViewModel => (AnimePageVM)DataContext;
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is null)
return;
ViewModel.Edit(dataGrid.SelectedItem);
ViewModel.EditCommand_ExecuteCommand(dataGrid.SelectedItem);
}
}

View File

@ -44,18 +44,18 @@ public partial class FoodAnimeEditWindow : Window
public bool IsCancel { get; private set; } = true;
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
IsCancel = false;
Close();
}
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (ViewModel is null)
return;
@ -75,7 +75,7 @@ public partial class FoodAnimeEditWindow : Window
}
}
private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
private void ListBox_PreviewMouseWheel(object? sender, MouseWheelEventArgs e)
{
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
@ -89,7 +89,7 @@ public partial class FoodAnimeEditWindow : Window
private object _dropSender;
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
private void ListBox_PreviewMouseMove(object? sender, MouseEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -107,7 +107,7 @@ public partial class FoodAnimeEditWindow : Window
DragDrop.DoDragDrop(listBox, dataObj, DragDropEffects.Move);
}
private void ListBox_Drop(object sender, DragEventArgs e)
private void ListBox_Drop(object? sender, DragEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -156,7 +156,7 @@ public partial class FoodAnimeEditWindow : Window
list[targetIndex] = temp;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void ListBox_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (sender is not ListBox listBox)
return;
@ -166,7 +166,7 @@ public partial class FoodAnimeEditWindow : Window
e.Handled = true;
}
private void ListBox_Animes_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void ListBox_Animes_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
e.Handled = true;
}

View File

@ -7,6 +7,7 @@
xmlns:local="clr-namespace:VPet.ModMaker.Views.ModEdit.AnimeEdit"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:vm="clr-namespace:VPet.ModMaker.ViewModels.ModEdit.AnimeEdit"
Title="SelectGraphTypeWindow"
Width="500"
Height="300"
@ -15,7 +16,7 @@
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
</Window.Resources>
<d:Window.DataContext>
<local:SelectGraphTypeWindow />
<vm:SelectGraphTypeWindowVM />
</d:Window.DataContext>
<Grid>
<Grid.RowDefinitions>
@ -38,19 +39,19 @@
<Label Content="{ll:Str 动画类型}" />
<ComboBox
Grid.Column="1"
ItemsSource="{Binding GraphTypes.Value}"
SelectedItem="{Binding GraphType.Value}"
ItemsSource="{Binding GraphTypes}"
SelectedItem="{Binding GraphType}"
Style="{DynamicResource StandardComboBoxStyle}" />
<Label
Grid.Row="1"
Content="{ll:Str 动画名称}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToCollapsedConverter}}" />
Visibility="{Binding HasNameAnime, Converter={StaticResource FalseToCollapsedConverter}}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding AnimeName.Value, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToCollapsedConverter}}" />
Text="{Binding AnimeName, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasNameAnime, Converter={StaticResource FalseToCollapsedConverter}}" />
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -16,6 +17,7 @@ using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
using VPet_Simulator.Core;
namespace VPet.ModMaker.Views.ModEdit.AnimeEdit;
@ -25,63 +27,22 @@ namespace VPet.ModMaker.Views.ModEdit.AnimeEdit;
/// </summary>
public partial class SelectGraphTypeWindow : Window
{
public SelectGraphTypeWindowVM ViewModel => (SelectGraphTypeWindowVM)DataContext;
public SelectGraphTypeWindow()
{
InitializeComponent();
DataContext = this;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
GraphType.ValueChanged += GraphType_ValueChanged;
Closed += (s, e) =>
{
try
{
DataContext = null;
}
catch { }
};
this.SetDataContext<SelectGraphTypeWindowVM>();
}
private void GraphType_ValueChanged(
ObservableValue<GraphInfo.GraphType> sender,
ValueChangedEventArgs<GraphInfo.GraphType> e
)
{
if (e.NewValue.IsHasNameAnime())
HasNameAnime.Value = true;
else
HasNameAnime.Value = false;
}
private void CurrentPet_ValueChanged(
ObservableValue<PetModel> sender,
ValueChangedEventArgs<PetModel> e
)
{
GraphTypes.Value = new(
AnimeTypeModel.GraphTypes.Except(CurrentPet.Value.Animes.Select(m => m.GraphType))
);
// 可添加多个项的类型
foreach (var graphType in AnimeTypeModel.HasNameAnimes)
if (GraphTypes.Value.Contains(graphType) is false)
GraphTypes.Value.Add(graphType);
}
public ObservableValue<PetModel> CurrentPet { get; } = new();
public ObservableValue<GraphInfo.GraphType> GraphType { get; } = new();
public ObservableValue<ObservableCollection<GraphInfo.GraphType>> GraphTypes { get; } =
new(new());
public ObservableValue<string> AnimeName { get; } = new();
public ObservableValue<bool> HasNameAnime { get; } = new(true);
public bool IsCancel { get; private set; } = true;
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
//if (string.IsNullOrWhiteSpace(AnimeName.Value))
//{

View File

@ -31,12 +31,12 @@ public partial class ClickTextEditWindow : Window
this.SetDataContext<ClickTextEditWindowVM>();
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.ClickText.ID))
{

View File

@ -60,12 +60,12 @@
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Text" />
<DataGridTextColumn
Binding="{Binding Mode.EnumValue}"
Binding="{Binding Mode.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 状态}"
IsReadOnly="True"
SortMemberPath="Mode.EnumValue" />
SortMemberPath="Mode.Value" />
<DataGridTextColumn
Binding="{Binding Working}"
CanUserSort="True"
@ -81,12 +81,12 @@
IsReadOnly="True"
SortMemberPath="WorkingState" />
<DataGridTextColumn
Binding="{Binding DayTime.EnumValue}"
Binding="{Binding DayTime.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 时间}"
IsReadOnly="True"
SortMemberPath="DayTime.EnumValue" />
SortMemberPath="DayTime.Value" />
<DataGridTextColumn
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"

View File

@ -30,7 +30,7 @@ public partial class ClickTextPage : Page
DataContext = new ClickTextPageVM();
}
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not ClickTextModel model)
return;

View File

@ -38,12 +38,12 @@ public partial class FoodEditWindow : Window
});
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.Food.ID))
{

View File

@ -33,7 +33,7 @@ public partial class FoodPage : Page
DataContext = new FoodPageVM();
}
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not FoodModel model)
return;

View File

@ -20,7 +20,7 @@ public partial class I18nEditWindow : WindowX
{
public bool IsCancel { get; private set; } = true;
public static I18nEditWindow Current { get; private set; }
public static I18nEditWindow Current { get; private set; } = null!;
public I18nEditWindowVM ViewModel => (I18nEditWindowVM)DataContext;
@ -64,7 +64,7 @@ public partial class I18nEditWindow : WindowX
Close();
}
private void ViewModel_CultureChanged(object sender, string newCulture)
private void ViewModel_CultureChanged(object? sender, string newCulture)
{
var oldCulture = sender as string;
if (string.IsNullOrEmpty(oldCulture))

View File

@ -32,12 +32,12 @@ public partial class LowTextEditWindow : Window
this.SetDataContext<LowTextEditWindowVM>();
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.LowText.ID))
{

View File

@ -33,7 +33,7 @@ public partial class LowTextPage : Page
DataContext = new LowTextPageVM();
}
private void DataGrid_LowText_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_LowText_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not LowTextModel lowText)
return;

View File

@ -92,7 +92,7 @@
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="ID"
Text="{Binding ModInfo.Id, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding ModInfo.ID, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Content="{ll:Str 作者}" />
<TextBox
x:Name="TextBox_Author"
@ -311,6 +311,7 @@
<Button
Command="{Binding EditI18nCommand}"
Content="{ll:Str 编辑多语言内容}"
IsEnabled="False"
Style="{DynamicResource ThemedButtonStyle}" />
<Button
Command="{Binding SaveCommand}"
@ -320,9 +321,11 @@
Command="{Binding SaveToCommand}"
Content="{ll:Str 保存至}"
Style="{DynamicResource ThemedButtonStyle}" />
<!-- TODO -->
<Button
Command="{Binding SaveAsTranslationModCommand}"
Content="{ll:Str 保存为翻译模组}"
IsEnabled="False"
Style="{DynamicResource ThemedButtonStyle}" />
<!--<Menu
x:Name="Button_SaveAs"

View File

@ -39,6 +39,7 @@ namespace VPet.ModMaker.Views.ModEdit;
/// </summary>
public partial class ModEditWindow : WindowX
{
public static ModEditWindow Current { get; private set; } = null!;
public ModEditWindowVM ViewModel => (ModEditWindowVM)DataContext;
public FoodPage FoodPage { get; } = null!;
public LowTextPage LowTextPage { get; } = null!;
@ -51,6 +52,7 @@ public partial class ModEditWindow : WindowX
public ModEditWindow()
{
Current = this;
InitializeComponent();
DataContext = new ModEditWindowVM(this);
Closing += ModEditWindow_Closing;
@ -60,10 +62,9 @@ public partial class ModEditWindow : WindowX
ClickTextPage = new();
SelectTextPage = new();
PetPage = new();
//TODO
//WorkPage = new();
//MovePage = new();
//AnimePage = new();
WorkPage = new();
MovePage = new();
AnimePage = new();
}
/// <summary>

View File

@ -39,12 +39,12 @@ public partial class MoveEditWindow : Window
};
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.Move.Graph))
{

View File

@ -61,7 +61,7 @@
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{ll:Str {} (来自本体)}" Visibility="{Binding FromMain, Converter={StaticResource FalseToCollapsedConverter}}" />
</StackPanel>
</DataTemplate>
@ -85,7 +85,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowMoves}"
ItemsSource="{Binding Moves.FilteredList}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="50"
@ -107,26 +107,26 @@
IsReadOnly="True"
SortMemberPath="Graph" />
<DataGridTextColumn
Binding="{Binding LocateType.EnumValue}"
Binding="{Binding LocateType.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 定位类型}"
IsReadOnly="True"
SortMemberPath="LocateType.EnumValue" />
SortMemberPath="LocateType.Value" />
<DataGridTextColumn
Binding="{Binding TriggerType.EnumValue}"
Binding="{Binding TriggerType.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 触发类型}"
IsReadOnly="True"
SortMemberPath="TriggerType.EnumValue" />
SortMemberPath="TriggerType.Value" />
<DataGridTextColumn
Binding="{Binding ModeType.EnumValue}"
Binding="{Binding ModeType.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 状态类型}"
IsReadOnly="True"
SortMemberPath="ModeType.EnumValue" />
SortMemberPath="ModeType.Value" />
<DataGridTextColumn
Binding="{Binding Distance}"
CanUserSort="True"

View File

@ -30,10 +30,10 @@ public partial class MovePage : Page
public MovePageVM ViewModel => (MovePageVM)DataContext;
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not MoveModel model)
return;
ViewModel.Edit(model);
ViewModel.EditCommand_ExecuteCommand(model);
}
}

View File

@ -20,7 +20,7 @@
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
<ResourceDictionary>
<Style
x:Key="Label_ThouchRect"
x:Key="Label_ThouchRectangleLocation"
BasedOn="{StaticResource {x:Type Label}}"
TargetType="Label">
<Setter Property="Visibility" Value="Collapsed" />
@ -40,7 +40,6 @@
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
@ -68,11 +67,11 @@
<Grid>
<Label Content="{ll:Str 头部触碰范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchHead}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchHeadRect.Width" />
<Binding Path="Pet.TouchHeadRectangleLocation.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -80,7 +79,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchHeadRect.Height" />
<Binding Path="Pet.TouchHeadRectangleLocation.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -89,8 +88,8 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchHeadRect.X" />
<Binding Path="Pet.TouchHeadRect.Y" />
<Binding Path="Pet.TouchHeadRectangleLocation.X" />
<Binding Path="Pet.TouchHeadRectangleLocation.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
@ -99,11 +98,11 @@
</Label>
<Label Content="{ll:Str 身体触碰范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchBody}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchBodyRect.Width" />
<Binding Path="Pet.TouchBodyRectangleLocation.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -111,7 +110,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchBodyRect.Height" />
<Binding Path="Pet.TouchBodyRectangleLocation.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -120,21 +119,21 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchBodyRect.X" />
<Binding Path="Pet.TouchBodyRect.Y" />
<Binding Path="Pet.TouchBodyRectangleLocation.X" />
<Binding Path="Pet.TouchBodyRectangleLocation.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>
<Label Content="{ll:Str 开心状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRect_HappyState}">
<Label Content="{ll:Str 开心状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRectangleLocation_HappyState}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Happy.Width" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Happy.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -142,7 +141,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Happy.Height" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Happy.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -151,21 +150,21 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchRaisedRect.Happy.X" />
<Binding Path="Pet.TouchRaisedRect.Happy.Y" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Happy.X" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Happy.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>
<Label Content="{ll:Str 普通状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRect_NomalState}">
<Label Content="{ll:Str 普通状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRectangleLocation_NomalState}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Nomal.Width" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Nomal.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -173,7 +172,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Nomal.Height" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Nomal.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -182,21 +181,21 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchRaisedRect.Nomal.X" />
<Binding Path="Pet.TouchRaisedRect.Nomal.Y" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Nomal.X" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Nomal.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>
<Label Content="{ll:Str 低状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRect_PoorConditionState}">
<Label Content="{ll:Str 低状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRectangleLocation_PoorConditionState}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.PoorCondition.Width" />
<Binding Path="Pet.TouchRaisedRectangleLocation.PoorCondition.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -204,7 +203,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.PoorCondition.Height" />
<Binding Path="Pet.TouchRaisedRectangleLocation.PoorCondition.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -213,21 +212,21 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchRaisedRect.PoorCondition.X" />
<Binding Path="Pet.TouchRaisedRect.PoorCondition.Y" />
<Binding Path="Pet.TouchRaisedRectangleLocation.PoorCondition.X" />
<Binding Path="Pet.TouchRaisedRectangleLocation.PoorCondition.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>
<Label Content="{ll:Str 生病状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRect_IllState}">
<Label Content="{ll:Str 生病状态提起范围}" Tag="{Binding IsChecked, ElementName=ToggleButton_TouchRaisedRectangleLocation_IllState}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Ill.Width" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Ill.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -235,7 +234,7 @@
<Setter Property="Height">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.TouchRaisedRect.Ill.Height" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Ill.Height" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
@ -244,8 +243,8 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio" />
<Binding Path="Pet.TouchRaisedRect.Ill.X" />
<Binding Path="Pet.TouchRaisedRect.Ill.Y" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Ill.X" />
<Binding Path="Pet.TouchRaisedRectangleLocation.Ill.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
@ -259,7 +258,7 @@
Content="{ll:Str 开心状态提起点位}"
Tag="{Binding IsChecked, ElementName=ToggleButton_RaisePoint_Happy}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
@ -279,7 +278,7 @@
Content="{ll:Str 普通状态提起点位}"
Tag="{Binding IsChecked, ElementName=ToggleButton_RaisePoint_Nomal}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
@ -299,7 +298,7 @@
Content="{ll:Str 低状态提起点位}"
Tag="{Binding IsChecked, ElementName=ToggleButton_RaisePoint_PoorCondition}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
@ -319,7 +318,7 @@
Content="{ll:Str 生病状态提起点位}"
Tag="{Binding IsChecked, ElementName=ToggleButton_RaisePoint_Ill}">
<Label.Style>
<Style BasedOn="{StaticResource Label_ThouchRect}" TargetType="Label">
<Style BasedOn="{StaticResource Label_ThouchRectangleLocation}" TargetType="Label">
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
@ -358,6 +357,12 @@
Grid.Column="1"
pu:TextBoxHelper.Watermark="ID"
Text="{Binding Pet.ID, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Content="{ll:Str 标签}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str '标签, 用英文逗号分隔'}"
Text="{Binding Pet.Tags, UpdateSourceTrigger=PropertyChanged}" />
<!--<Label Grid.Row="1" Content="{ll:Str 名称}" />
<TextBox
Grid.Row="1"
@ -401,6 +406,7 @@
x:Name="ToggleButton_TouchHead"
Padding="5"
HorizontalContentAlignment="Stretch"
d:IsChecked="True"
Content="{ll:Str 头部触碰范围}" />
<Grid Grid.Column="1" Margin="5">
<Grid.RowDefinitions>
@ -414,12 +420,18 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchHeadRect.X}" />
<pu:NumberInput
Grid.Column="1"
d:Value="100"
Value="{Binding Pet.TouchHeadRectangleLocation.X}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchHeadRect.Y, Mode=TwoWay}" />
<pu:NumberInput
Grid.Column="3"
d:Value="100"
Value="{Binding Pet.TouchHeadRectangleLocation.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -427,7 +439,8 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchHeadRect.Width, Mode=TwoWay}" />
d:Value="100"
Value="{Binding Pet.TouchHeadRectangleLocation.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -436,7 +449,8 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchHeadRect.Height, Mode=TwoWay}" />
d:Value="100"
Value="{Binding Pet.TouchHeadRectangleLocation.Height, Mode=TwoWay}" />
</Grid>
</Grid>
<Grid>
@ -461,12 +475,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchBodyRect.X}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchBodyRectangleLocation.X}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchBodyRect.Y, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchBodyRectangleLocation.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -474,7 +488,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchBodyRect.Width, Mode=TwoWay}" />
Value="{Binding Pet.TouchBodyRectangleLocation.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -483,7 +497,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchBodyRect.Height, Mode=TwoWay}" />
Value="{Binding Pet.TouchBodyRectangleLocation.Height, Mode=TwoWay}" />
</Grid>
</Grid>
<Expander Header="{ll:Str 提起范围}">
@ -499,7 +513,7 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToggleButton
x:Name="ToggleButton_TouchRaisedRect_HappyState"
x:Name="ToggleButton_TouchRaisedRectangleLocation_HappyState"
Padding="5"
HorizontalContentAlignment="Stretch"
d:IsChecked="True"
@ -516,12 +530,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRect.Happy.X, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRectangleLocation.Happy.X, Mode=TwoWay}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRect.Happy.Y, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRectangleLocation.Happy.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -529,7 +543,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchRaisedRect.Happy.Width, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Happy.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -538,10 +552,10 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchRaisedRect.Happy.Height, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Happy.Height, Mode=TwoWay}" />
</Grid>
<ToggleButton
x:Name="ToggleButton_TouchRaisedRect_NomalState"
x:Name="ToggleButton_TouchRaisedRectangleLocation_NomalState"
Grid.Row="1"
Padding="5"
HorizontalContentAlignment="Stretch"
@ -562,12 +576,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRect.Nomal.X, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRectangleLocation.Nomal.X, Mode=TwoWay}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRect.Nomal.Y, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRectangleLocation.Nomal.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -575,7 +589,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchRaisedRect.Nomal.Width, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Nomal.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -584,10 +598,10 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchRaisedRect.Nomal.Height, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Nomal.Height, Mode=TwoWay}" />
</Grid>
<ToggleButton
x:Name="ToggleButton_TouchRaisedRect_PoorConditionState"
x:Name="ToggleButton_TouchRaisedRectangleLocation_PoorConditionState"
Grid.Row="2"
Padding="5"
HorizontalContentAlignment="Stretch"
@ -608,12 +622,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRect.PoorCondition.X, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRectangleLocation.PoorCondition.X, Mode=TwoWay}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRect.PoorCondition.Y, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRectangleLocation.PoorCondition.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -621,7 +635,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchRaisedRect.PoorCondition.Width, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.PoorCondition.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -630,10 +644,10 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchRaisedRect.PoorCondition.Height, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.PoorCondition.Height, Mode=TwoWay}" />
</Grid>
<ToggleButton
x:Name="ToggleButton_TouchRaisedRect_IllState"
x:Name="ToggleButton_TouchRaisedRectangleLocation_IllState"
Grid.Row="3"
Padding="5"
HorizontalContentAlignment="Stretch"
@ -654,12 +668,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Background="{x:Null}" Content="x:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRect.Ill.X, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Pet.TouchRaisedRectangleLocation.Ill.X, Mode=TwoWay}" />
<Label
Grid.Column="2"
Background="{x:Null}"
Content="y:" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRect.Ill.Y, Mode=TwoWay}" />
<pu:NumberInput Grid.Column="3" Value="{Binding Pet.TouchRaisedRectangleLocation.Ill.Y, Mode=TwoWay}" />
<Label
Grid.Row="1"
Background="{x:Null}"
@ -667,7 +681,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Pet.TouchRaisedRect.Ill.Width, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Ill.Width, Mode=TwoWay}" />
<Label
Grid.Row="1"
Grid.Column="2"
@ -676,7 +690,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="3"
Value="{Binding Pet.TouchRaisedRect.Ill.Height, Mode=TwoWay}" />
Value="{Binding Pet.TouchRaisedRectangleLocation.Ill.Height, Mode=TwoWay}" />
</Grid>
</Grid>
</Expander>

View File

@ -40,12 +40,12 @@ public partial class PetEditWindow : Window
};
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.Pet.ID))
{

View File

@ -95,6 +95,13 @@
Header="{ll:Str 宠物名称}"
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" />
<DataGridTextColumn
Binding="{Binding Tags}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 标签}"
IsReadOnly="True"
SortMemberPath="Tags" />
<DataGridTextColumn
Binding="{Binding CurrentI18nData.Description}"
CanUserSort="True"

View File

@ -30,10 +30,10 @@ public partial class PetPage : Page
DataContext = new PetPageVM();
}
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not PetModel model)
return;
ViewModel.Edit(model);
ViewModel.EditCommand_ExecuteCommand(model);
}
}

View File

@ -39,12 +39,12 @@ public partial class SelectTextEditWindow : Window
};
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.ID))
{

View File

@ -84,12 +84,12 @@
IsReadOnly="True"
SortMemberPath="ToTags" />
<DataGridTextColumn
Binding="{Binding Mode.EnumValue}"
Binding="{Binding Mode.Value}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 状态}"
IsReadOnly="True"
SortMemberPath="Mode.EnumValue" />
SortMemberPath="Mode.Value" />
<DataGridTextColumn
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"

View File

@ -30,7 +30,7 @@ public partial class SelectTextPage : Page
DataContext = new SelectTextPageVM();
}
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not SelectTextModel model)
return;

View File

@ -126,8 +126,8 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="Id" />
<TextBox Grid.Column="1" Text="{Binding Work.Id}" />
<Label Content="ID" />
<TextBox Grid.Column="1" Text="{Binding Work.ID}" />
<Label Grid.Row="1" Content="{ll:Str 名称}" />
<TextBox
Grid.Row="1"
@ -143,7 +143,7 @@
<TextBox
Grid.Row="3"
Grid.Column="1"
Text="{Binding Work.Graph}" />
Text="{Binding Work.Graph, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="4" Content="{ll:Str 是否超模}" />
<Grid Grid.Row="4" Grid.Column="1">
<Grid.ColumnDefinitions>
@ -154,7 +154,10 @@
d:Text="True"
Style="{DynamicResource TextBlock_LeftCenter}"
Text="{Binding Work.IsOverLoad}" />
<Button Grid.Column="1" Content="{ll:Str 修复超模}" />
<Button
Grid.Column="1"
Command="{Binding FixOverLoadCommand}"
Content="{ll:Str 修复超模}" />
</Grid>
<!--<Label Grid.Row="3" Content="{ll:Str 宠物描述}" />
<TextBox

View File

@ -28,27 +28,20 @@ public partial class WorkEditWindow : Window
public WorkEditWindow()
{
InitializeComponent();
DataContext = new WorkEditWindowVM();
Closed += (s, e) =>
{
this.SetDataContext<WorkEditWindowVM>(() => {
//TODO
//ViewModel.Close();
try
{
DataContext = null;
}
catch { }
};
});
}
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
private void Button_Cancel_Click(object? sender, RoutedEventArgs e)
{
Close();
}
private void Button_Yes_Click(object sender, RoutedEventArgs e)
private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.Work.Id))
if (string.IsNullOrEmpty(ViewModel.Work.ID))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
@ -64,8 +57,8 @@ public partial class WorkEditWindow : Window
return;
}
if (
ViewModel.OldWork?.Id != ViewModel.Work.Id
&& ViewModel.CurrentPet.Works.Any(i => i.Id == ViewModel.Work.Id)
ViewModel.OldWork?.ID != ViewModel.Work.ID
&& ViewModel.CurrentPet.Works.Any(i => i.ID == ViewModel.Work.ID)
)
{
MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);

View File

@ -26,7 +26,7 @@
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}" Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}">
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索ID}" Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style BasedOn="{StaticResource StandardTextBoxStyle}" TargetType="TextBox">
<Setter Property="IsEnabled" Value="True" />
@ -65,7 +65,7 @@
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{ll:Str {} (来自本体)}" Visibility="{Binding FromMain, Converter={StaticResource FalseToCollapsedConverter}}" />
</StackPanel>
</DataTemplate>
@ -89,7 +89,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowWorks}"
ItemsSource="{Binding Works.FilteredList}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="64"
@ -104,12 +104,12 @@
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Id}"
Binding="{Binding ID}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="Id"
Header="ID"
IsReadOnly="True"
SortMemberPath="Id" />
SortMemberPath="ID" />
<DataGridTextColumn
Binding="{Binding CurrentI18nData.Name}"
CanUserSort="True"

View File

@ -30,10 +30,10 @@ public partial class WorkPage : Page
DataContext = new WorkPageVM();
}
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void DataGrid_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not WorkModel model)
return;
ViewModel.Edit(model);
ViewModel.EditCommand_ExecuteCommand(model);
}
}

View File

@ -37,7 +37,7 @@
<TextBox
pu:TextBoxHelper.Watermark="{ll:Str 最近的内容}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding HistoriesSearchText}" />
Text="{Binding Search}" />
<Button
Grid.Column="1"
Command="{Binding ClearHistoriesCommand}"
@ -47,7 +47,7 @@
<ListBox
Grid.Row="2"
d:ItemsSource="{d:SampleData ItemCount=5}"
ItemsSource="{Binding ShowHistories}"
ItemsSource="{Binding Histories.FilteredList}"
Style="{DynamicResource SideMenuListBoxStyle}">
<ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
@ -82,7 +82,7 @@
<TextBlock
d:Text="{ll:Str Mod名称}"
FontWeight="Bold"
Text="{Binding Id}"
Text="{Binding ID}"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Right"

View File

@ -41,7 +41,7 @@ public partial class ModMakerWindow : WindowX
//new AnimeEditWindow().Show();
}
private void ModMakerWindow_Closed(object sender, EventArgs e)
private void ModMakerWindow_Closed(object? sender, EventArgs e)
{
// 当模组载入错误时, 会产生野窗口, 需要手动关闭
foreach (var item in Application.Current.Windows)
@ -51,7 +51,7 @@ public partial class ModMakerWindow : WindowX
}
}
private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
private void ListBoxItem_MouseDoubleClick(object? sender, MouseButtonEventArgs e)
{
if (sender is not ListBoxItem item)
return;
@ -65,13 +65,12 @@ public partial class ModMakerWindow : WindowX
)
{
ViewModel.Histories.Remove(history);
ViewModel.ShowHistories.Remove(history);
}
}
ViewModel.LoadMod(history.SourcePath);
}
private void Hyperlink_Click(object sender, RoutedEventArgs e)
private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{
Process.Start(new ProcessStartInfo("https://github.com/LorisYounger/VPet.ModMaker/wiki"));
}