- 完全重构
- 添加版本升级提示(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="EqualsConverter" />
<c:EqualsMultiConverter x:Key="NotEqualsConverter" IsInverted="True" /> <c:EqualsMultiConverter x:Key="NotEqualsConverter" IsInverted="True" />
<c:NullToBoolConverter x:Key="NullToFalseConverter" /> <c:NullToBoolConverter x:Key="NullToFalseConverter" />
<c:AllBoolToVisibilityMultiConverter x:Key="AllTrueToCollapsedConverter" /> <c:AllBoolToVisibilityMultiConverter
x:Key="AllTrueToCollapsedConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<c:BoolInverteConverter x:Key="BoolInverter" /> <c:BoolInverteConverter x:Key="BoolInverter" />
</ResourceDictionary> </ResourceDictionary>

View File

@ -32,5 +32,5 @@ public class I18nData : ObservableObjectX<I18nData>
/// <summary> /// <summary>
/// 基于 <see cref="I18nHelper.Current.CultureNames"/> 的索引的数据列表 /// 基于 <see cref="I18nHelper.Current.CultureNames"/> 的索引的数据列表
/// </summary> /// </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>
/// 模组制作历史 /// 模组制作历史
/// </summary> /// </summary>
public class ModMakeHistory public class ModMakeHistory : IEquatable<ModMakeHistory>
{ {
/// <summary> /// <summary>
/// 图片 /// 图片
/// </summary> /// </summary>
public BitmapImage Image { get; set; } public BitmapImage? Image { get; set; }
/// <summary> /// <summary>
/// Id /// Id
/// </summary> /// </summary>
[Line(ignoreCase: true)] [Line(ignoreCase: true)]
public string Id { get; set; } public string ID { get; set; } = string.Empty;
/// <summary> /// <summary>
/// 路径 /// 路径
/// </summary> /// </summary>
private string _path; private string _path = string.Empty;
/// <summary> /// <summary>
/// 资源路径 /// 资源路径
@ -56,4 +56,20 @@ public class ModMakeHistory
/// </summary> /// </summary>
[Line(ignoreCase: true)] [Line(ignoreCase: true)]
public DateTime LastTime { get; set; } = DateTime.Now; 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 ILine Set;
public override string PluginName => "ModMaker"; public override string PluginName => "ModMaker";
public ModMakerWindow Maker; public ModMakerWindow Maker = null!;
public ModMaker(IMainWindow mainwin) public ModMaker(IMainWindow mainwin)
: base(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>
/// 动画模型 /// 动画模型
/// </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)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// Id
/// </summary> /// </summary>
public string Id public string ID
{ {
get => _id; get => _id;
set => SetProperty(ref _id, value); set => SetProperty(ref _id, value);
@ -43,40 +61,24 @@ public class AnimeModel : ObservableObjectX<AnimeModel>
/// <summary> /// <summary>
/// 图像列表 /// 图像列表
/// </summary> /// </summary>
public ObservableCollection<ImageModel> Images { get; } = new(); public ObservableList<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);
}
}
/// <summary> /// <summary>
/// 复制 /// 复制
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public AnimeModel Copy() public AnimeModel Clone()
{ {
var model = new AnimeModel(); var model = new AnimeModel();
model.Id = Id; model.ID = ID;
model.AnimeType = AnimeType; model.AnimeType = AnimeType;
foreach (var image in Images) foreach (var image in Images)
model.Images.Add(image.Copy()); model.Images.Add(image.Clone());
return model; return model;
} }
object ICloneable.Clone() => Clone();
/// <summary> /// <summary>
/// 关闭所有图像流 /// 关闭所有图像流
/// </summary> /// </summary>

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -16,43 +18,72 @@ namespace VPet.ModMaker.Models.ModModel;
public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel> 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>
/// 动作类型 /// 动作类型
/// </summary> /// </summary>
public static ObservableCollection<GraphInfo.GraphType> GraphTypes { get; } = public static FrozenSet<GraphInfo.GraphType> GraphTypes { get; } =
new(Enum.GetValues<GraphInfo.GraphType>()); Enum.GetValues<GraphInfo.GraphType>().ToFrozenSet();
/// <summary> /// <summary>
/// 动画类型 /// 动画类型
/// </summary> /// </summary>
public static ObservableCollection<GraphInfo.AnimatType> AnimatTypes { get; } = public static FrozenSet<GraphInfo.AnimatType> AnimatTypes { get; } =
new(Enum.GetValues(typeof(GraphInfo.AnimatType)).Cast<GraphInfo.AnimatType>()); Enum.GetValues<GraphInfo.AnimatType>().ToFrozenSet();
/// <summary> /// <summary>
/// 模式类型 /// 模式类型
/// </summary> /// </summary>
public static ObservableCollection<ModeType> ModeTypes { get; } = public static FrozenSet<ModeType> ModeTypes { get; } = Enum.GetValues<ModeType>().ToFrozenSet();
new(Enum.GetValues(typeof(ModeType)).Cast<ModeType>());
/// <summary> /// <summary>
/// 含有名称的动作列表 /// 含有名称的动作列表
/// </summary> /// </summary>
public static HashSet<GraphInfo.GraphType> HasNameAnimes { get; } = public static FrozenSet<GraphInfo.GraphType> HasNameAnimes { get; } =
new() FrozenSet.ToFrozenSet(
{ [
GraphInfo.GraphType.Common, GraphInfo.GraphType.Common,
GraphInfo.GraphType.Work, GraphInfo.GraphType.Work,
GraphInfo.GraphType.Idel, GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move, GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say GraphInfo.GraphType.Say
}; ]
);
/// <summary> /// <summary>
/// 含有不同动画类型的动作列表 /// 含有不同动画类型的动作列表
/// </summary> /// </summary>
public static HashSet<GraphInfo.GraphType> HasMultiTypeAnimes { get; } = public static FrozenSet<GraphInfo.GraphType> HasMultiTypeAnimes { get; } =
new() FrozenSet.ToFrozenSet(
{ [
GraphInfo.GraphType.Touch_Head, GraphInfo.GraphType.Touch_Head,
GraphInfo.GraphType.Touch_Body, GraphInfo.GraphType.Touch_Body,
GraphInfo.GraphType.Sleep, GraphInfo.GraphType.Sleep,
@ -64,16 +95,17 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
GraphInfo.GraphType.Idel, GraphInfo.GraphType.Idel,
GraphInfo.GraphType.Move, GraphInfo.GraphType.Move,
GraphInfo.GraphType.Say GraphInfo.GraphType.Say
}; ]
);
#region Id #region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// Id
/// </summary> /// </summary>
public string Id public string ID
{ {
get => _id; get => _id;
set => SetProperty(ref _id, value); set => SetProperty(ref _id, value);
@ -82,7 +114,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
#region Name #region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name; private string _name = string.Empty;
/// <summary> /// <summary>
/// 名称 /// 名称
@ -96,61 +128,37 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
#region GraphType #region GraphType
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GraphInfo.GraphType _GraphType; private GraphInfo.GraphType _graphType;
/// <summary> /// <summary>
/// 动作类型 /// 动作类型
/// </summary> /// </summary>
public GraphInfo.GraphType GraphType public GraphInfo.GraphType GraphType
{ {
get => _GraphType; get => _graphType;
set => SetProperty(ref _GraphType, value); set => SetProperty(ref _graphType, value);
} }
#endregion #endregion
/// <summary> /// <summary>
/// 开心动画 /// 开心动画
/// </summary> /// </summary>
public ObservableCollection<AnimeModel> HappyAnimes { get; } = new(); public ObservableList<AnimeModel> HappyAnimes { get; } = new();
/// <summary> /// <summary>
/// 普通动画 (默认) /// 普通动画 (默认)
/// </summary> /// </summary>
public ObservableCollection<AnimeModel> NomalAnimes { get; } = new(); public ObservableList<AnimeModel> NomalAnimes { get; } = new();
/// <summary> /// <summary>
/// 低状态动画 /// 低状态动画
/// </summary> /// </summary>
public ObservableCollection<AnimeModel> PoorConditionAnimes { get; } = new(); public ObservableList<AnimeModel> PoorConditionAnimes { get; } = new();
/// <summary> /// <summary>
/// 生病动画 /// 生病动画
/// </summary> /// </summary>
public ObservableCollection<AnimeModel> IllAnimes { get; } = new(); public ObservableList<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());
}
/// <summary> /// <summary>
/// 创建动画类型模型 /// 创建动画类型模型
@ -196,9 +204,9 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
Name = Path.GetFileName(path); Name = Path.GetFileName(path);
// 为带有名字的类型设置Id // 为带有名字的类型设置Id
if (graphType.IsHasNameAnime()) if (graphType.IsHasNameAnime())
Id = $"{graphType}_{Name}"; ID = $"{graphType}_{Name}";
else else
Id = graphType.ToString(); ID = graphType.ToString();
GraphType = graphType; GraphType = graphType;
if ( if (
graphType graphType
@ -389,7 +397,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
/// <param name="path">路径</param> /// <param name="path">路径</param>
/// <param name="animatType">动画类型</param> /// <param name="animatType">动画类型</param>
private static void AddAnime( private static void AddAnime(
ObservableCollection<AnimeModel> collection, ObservableList<AnimeModel> collection,
string path, string path,
GraphInfo.AnimatType animatType = AnimatType.Single GraphInfo.AnimatType animatType = AnimatType.Single
) )
@ -572,7 +580,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
SaveAnimes(modePath, animeTypeModel.IllAnimes); SaveAnimes(modePath, animeTypeModel.IllAnimes);
} }
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes) static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{ {
Directory.CreateDirectory(animePath); Directory.CreateDirectory(animePath);
var countA = 0; var countA = 0;
@ -632,7 +640,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
var modePath = Path.Combine(animePath, nameof(ModeType.Ill)); var modePath = Path.Combine(animePath, nameof(ModeType.Ill));
SaveAnimes(modePath, animeType.IllAnimes); SaveAnimes(modePath, animeType.IllAnimes);
} }
static void SaveAnimes(string animePath, ObservableCollection<AnimeModel> animes) static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{ {
Directory.CreateDirectory(animePath); Directory.CreateDirectory(animePath);
foreach (var anime in animes.EnumerateIndex()) foreach (var anime in animes.EnumerateIndex())
@ -651,7 +659,7 @@ public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
foreach (var image in model.Images.EnumerateIndex()) foreach (var image in model.Images.EnumerateIndex())
{ {
image.Value.Image.SaveToPng( 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>
/// 食物图像位置模型 /// 食物图像位置模型
/// </summary> /// </summary>
public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel> public class FoodAnimeLocationModel
: ObservableObjectX<FoodAnimeLocationModel>,
ICloneable<FoodAnimeLocationModel>
{ {
public FoodAnimeLocationModel() { }
#region Duration #region Duration
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _duration; private int _duration;
@ -30,7 +34,7 @@ public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel>
/// <summary> /// <summary>
/// 范围 /// 范围
/// </summary> /// </summary>
public ObservableRectangleLocation<double> Rect { get; set; } = new(); public ObservableRectangleLocation<double> RectangleLocation { get; set; } = new();
/// <summary> /// <summary>
/// 旋转角度 /// 旋转角度
@ -59,27 +63,27 @@ public class FoodAnimeLocationModel : ObservableObjectX<FoodAnimeLocationModel>
set => SetProperty(ref _opacity, value); set => SetProperty(ref _opacity, value);
} }
#endregion #endregion
public FoodAnimeLocationModel Clone()
public FoodAnimeLocationModel()
{ {
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; return model;
} }
object ICloneable.Clone() => Clone();
public override string ToString() 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; 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() { }
public FoodAnimeModel(ILine line) public FoodAnimeModel(ILine line)
: this() : 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 index = int.Parse(item.Name.Substring(1));
var infos = item.Info.Split(','); var infos = item.Info.Split(',');
@ -56,7 +28,7 @@ public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>
foodLocationInfo.Duration = int.Parse(infos[0]); foodLocationInfo.Duration = int.Parse(infos[0]);
if (infos.Length > 1) if (infos.Length > 1)
{ {
foodLocationInfo.Rect = new( foodLocationInfo.RectangleLocation = new(
double.Parse(infos[1]), double.Parse(infos[1]),
double.Parse(infos[2]), double.Parse(infos[2]),
double.Parse(infos[3]), 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>
/// 复制 /// 复制
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public FoodAnimeModel Copy() public FoodAnimeModel Clone()
{ {
var model = new FoodAnimeModel(); var model = new FoodAnimeModel();
model.Id = Id; model.ID = ID;
foreach (var image in FrontImages) foreach (var image in FrontImages)
model.FrontImages.Add(image.Copy()); model.FrontImages.Add(image.Clone());
foreach (var image in BackImages) foreach (var image in BackImages)
model.BackImages.Add(image.Copy()); model.BackImages.Add(image.Clone());
foreach (var foodLocation in FoodLocations) foreach (var foodLocation in FoodLocations)
model.FoodLocations.Add(foodLocation.Copy()); model.FoodLocations.Add(foodLocation.Clone());
return model; return model;
} }
object ICloneable.Clone() => Clone();
/// <summary> /// <summary>
/// 关闭所有图像流 /// 关闭所有图像流
/// </summary> /// </summary>

View File

@ -17,6 +17,8 @@ namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel> public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
{ {
public FoodAnimeTypeModel() { }
/// <summary> /// <summary>
/// 动作类型 /// 动作类型
/// </summary> /// </summary>
@ -38,11 +40,11 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
/// </summary> /// </summary>
public const string BackLayName = "back_lay"; public const string BackLayName = "back_lay";
#region Id #region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id; private string _id;
public string Id public string ID
{ {
get => _id; get => _id;
set => SetProperty(ref _id, value); set => SetProperty(ref _id, value);
@ -59,37 +61,34 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public string Name public string Name
{ {
get => _name; get => _name;
set => SetProperty(ref _name, value); set
{
if (SetProperty(ref _name, value) is false)
return;
ID = $"{GraphType}_{Name}";
}
} }
#endregion #endregion
/// <summary> /// <summary>
/// 开心动画 /// 开心动画
/// </summary> /// </summary>
public ObservableCollection<FoodAnimeModel> HappyAnimes { get; } = new(); public ObservableList<FoodAnimeModel> HappyAnimes { get; } = new();
/// <summary> /// <summary>
/// 普通动画 (默认) /// 普通动画 (默认)
/// </summary> /// </summary>
public ObservableCollection<FoodAnimeModel> NomalAnimes { get; } = new(); public ObservableList<FoodAnimeModel> NomalAnimes { get; } = new();
/// <summary> /// <summary>
/// 低状态动画 /// 低状态动画
/// </summary> /// </summary>
public ObservableCollection<FoodAnimeModel> PoorConditionAnimes { get; } = new(); public ObservableList<FoodAnimeModel> PoorConditionAnimes { get; } = new();
/// <summary> /// <summary>
/// 生病动画 /// 生病动画
/// </summary> /// </summary>
public ObservableCollection<FoodAnimeModel> IllAnimes { get; } = new(); public ObservableList<FoodAnimeModel> IllAnimes { get; } = new();
public FoodAnimeTypeModel()
{ //TODO
//Name.ValueChanged += (_, _) =>
//{
// Id.Value = $"{GraphType}_{Name.Value}";
//};
}
public void Close() public void Close()
{ {
@ -131,16 +130,16 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public FoodAnimeTypeModel(FoodAnimeTypeModel model) public FoodAnimeTypeModel(FoodAnimeTypeModel model)
: this() : this()
{ {
Id = model.Id; ID = model.ID;
Name = model.Name; Name = model.Name;
foreach (var anime in model.HappyAnimes) foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy()); HappyAnimes.Add(anime.Clone());
foreach (var anime in model.NomalAnimes) foreach (var anime in model.NomalAnimes)
NomalAnimes.Add(anime.Copy()); NomalAnimes.Add(anime.Clone());
foreach (var anime in model.PoorConditionAnimes) foreach (var anime in model.PoorConditionAnimes)
PoorConditionAnimes.Add(anime.Copy()); PoorConditionAnimes.Add(anime.Clone());
foreach (var anime in model.IllAnimes) foreach (var anime in model.IllAnimes)
IllAnimes.Add(anime.Copy()); IllAnimes.Add(anime.Clone());
} }
/// <summary> /// <summary>
@ -217,7 +216,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
public void AddModeAnime( public void AddModeAnime(
string path, string path,
ModeType mode, ModeType mode,
ObservableCollection<FoodAnimeModel> foodAnimes, ObservableList<FoodAnimeModel> foodAnimes,
ILine line, ILine line,
List<PNGAnimeInfo> pngAnimeInfos List<PNGAnimeInfo> pngAnimeInfos
) )
@ -250,7 +249,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
} }
foodAnimes.Add(anime); foodAnimes.Add(anime);
static ObservableCollection<ImageModel> GetImages(string path, PNGAnimeInfo pngAnimeInfo) static ObservableList<ImageModel> GetImages(string path, PNGAnimeInfo pngAnimeInfo)
{ {
return new( return new(
Directory Directory
@ -299,7 +298,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
/// <param name="mode">模式</param> /// <param name="mode">模式</param>
private void SaveAnimeInfo( private void SaveAnimeInfo(
string animePath, string animePath,
ObservableCollection<FoodAnimeModel> animes, ObservableList<FoodAnimeModel> animes,
ModeType mode ModeType mode
) )
{ {
@ -334,7 +333,7 @@ public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
frontImage.Value.Image.SaveToPng( frontImage.Value.Image.SaveToPng(
Path.Combine( Path.Combine(
frontLayPath, 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( backImage.Value.Image.SaveToPng(
Path.Combine( Path.Combine(
backLayPath, 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() 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; PropertyChangedX += FoodModel_PropertyChangedX;
} }
@ -64,11 +45,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
PropertyChangedXEventArgs e PropertyChangedXEventArgs e
) )
{ {
if (e.PropertyName == nameof(ID)) if (e.PropertyName is not null && _notifyReferencePrice.Contains(e.PropertyName))
{
DescriptionID = $"{e.NewValue}_{nameof(DescriptionID)}";
}
else if (_notifyReferencePrice.Contains(e.PropertyName))
{ {
this.Adapt(_food); this.Adapt(_food);
ReferencePrice = Math.Floor(_food.RealPrice); ReferencePrice = Math.Floor(_food.RealPrice);
@ -96,7 +73,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
/// <summary> /// <summary>
/// 食物类型 /// 食物类型
/// </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>()); new(Enum.GetValues(typeof(Food.FoodType)).Cast<Food.FoodType>());
#region ID #region ID

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -285,6 +285,24 @@ public static class NativeExtensions
catch { } 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> /// <summary>

View File

@ -27,7 +27,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <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="HKW.WPF" Version="1.0.3" />
<PackageReference Include="Mapster" Version="7.4.0" /> <PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup> </ItemGroup>

View File

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

View File

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

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,6 +21,62 @@ namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM> 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>
/// 当前宠物 /// 当前宠物
/// </summary> /// </summary>
@ -67,7 +124,16 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// <summary> /// <summary>
/// 动画 /// 动画
/// </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 #region CurrentFrontImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -284,37 +350,6 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// </summary> /// </summary>
private Task _foodPlayerTask; 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() private void ResetFoodImageCommand_ExecuteEvent()
{ {
if (FoodImage != DefaultFoodImage) if (FoodImage != DefaultFoodImage)
@ -353,13 +388,13 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
private void AddAnimeCommand_ExecuteEvent() private void AddAnimeCommand_ExecuteEvent()
{ {
if (CurrentMode is ModeType.Happy) if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Add(new()); Anime.HappyAnimes.Add(new());
else if (CurrentMode is ModeType.Nomal) else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Add(new()); Anime.NomalAnimes.Add(new());
else if (CurrentMode is ModeType.PoorCondition) else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Add(new()); Anime.PoorConditionAnimes.Add(new());
else if (CurrentMode is ModeType.Ill) else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Add(new()); Anime.IllAnimes.Add(new());
} }
/// <summary> /// <summary>
@ -374,13 +409,13 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
) )
{ {
if (CurrentMode is ModeType.Happy) if (CurrentMode is ModeType.Happy)
Anime.Value.HappyAnimes.Remove(value); Anime.HappyAnimes.Remove(value);
else if (CurrentMode is ModeType.Nomal) else if (CurrentMode is ModeType.Nomal)
Anime.Value.NomalAnimes.Remove(value); Anime.NomalAnimes.Remove(value);
else if (CurrentMode is ModeType.PoorCondition) else if (CurrentMode is ModeType.PoorCondition)
Anime.Value.PoorConditionAnimes.Remove(value); Anime.PoorConditionAnimes.Remove(value);
else if (CurrentMode is ModeType.Ill) else if (CurrentMode is ModeType.Ill)
Anime.Value.IllAnimes.Remove(value); Anime.IllAnimes.Remove(value);
value.Close(); value.Close();
} }
} }
@ -540,7 +575,7 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
/// </summary> /// </summary>
/// <param name="images">动画</param> /// <param name="images">动画</param>
/// <param name="paths">路径</param> /// <param name="paths">路径</param>
public void AddImages(ObservableCollection<ImageModel> images, IEnumerable<string> paths) public void AddImages(ObservableList<ImageModel> images, IEnumerable<string> paths)
{ {
try try
{ {
@ -591,27 +626,8 @@ public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
} }
#endregion #endregion
#region FrontPlayer #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(); 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> // /// <summary>
// /// 全部I18n数据 // /// 全部I18n数据
// /// </summary> // /// </summary>
// public ObservableCollection<I18nData> I18nDatas { get; } = new(); // public ObservableList<I18nData> I18nDatas { get; } = new();
// /// <summary> // /// <summary>
// /// 显示的I18n数据 // /// 显示的I18n数据
// /// </summary> // /// </summary>
// #region ShowI18nDatas // #region ShowI18nDatas
// [DebuggerBrowsable(DebuggerBrowsableState.Never)] // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private ObservableCollection<I18nData> _showI18nDatas; // private ObservableList<I18nData> _showI18nDatas;
// public ObservableCollection<I18nData> ShowI18nDatas // public ObservableList<I18nData> ShowI18nDatas
// { // {
// get => _showI18nDatas; // get => _showI18nDatas;
// set => SetProperty(ref _showI18nDatas, value); // set => SetProperty(ref _showI18nDatas, value);
@ -54,7 +54,7 @@ public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
// /// <summary> // /// <summary>
// /// 搜索目标列表 // /// 搜索目标列表
// /// </summary> // /// </summary>
// public ObservableCollection<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) }; // public ObservableList<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) };
// /// <summary> // /// <summary>
// /// 搜索目标 // /// 搜索目标
@ -117,7 +117,7 @@ public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
// /// </summary> // /// </summary>
// /// <param name="sender"></param> // /// <param name="sender"></param>
// /// <param name="e"></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) // if (e.Action is NotifyCollectionChangedAction.Add)
// { // {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,29 +1,109 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using VPet.ModMaker.Models; using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Windows.Interface; using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit; namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit;
public class WorkEditWindowVM : ObservableObjectX<WorkEditWindowVM> 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 ModInfoModel ModInfo => ModInfoModel.Current;
public static I18nHelper I18nData => I18nHelper.Current; public static I18nHelper I18nData => I18nHelper.Current;
#region Value #region Property
public PetModel CurrentPet { get; set; } public PetModel CurrentPet { get; set; } = null!;
public WorkModel OldWork { get; set; } public WorkModel? OldWork { get; set; }
#region Work #region Work
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private WorkModel _work; private WorkModel _work = new();
public WorkModel Work public WorkModel Work
{ {
@ -52,52 +132,59 @@ public class WorkEditWindowVM : ObservableObjectX<WorkEditWindowVM>
set => SetProperty(ref _lengthRatio, value); set => SetProperty(ref _lengthRatio, value);
} }
#endregion #endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage? _image;
/// <summary>
/// 图片
/// </summary>
public BitmapImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#region Command #region Command
public ObservableCommand AddImageCommand { get; } = new(); public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new(); public ObservableCommand ChangeImageCommand { get; } = new();
public ObservableCommand FixOverLoadCommand { get; } = new(); public ObservableCommand FixOverLoadCommand { get; } = new();
#endregion #endregion
public WorkEditWindowVM()
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
FixOverLoadCommand.ExecuteCommand += FixOverLoadCommand_ExecuteCommand;
}
private void FixOverLoadCommand_ExecuteCommand() private void FixOverLoadCommand_ExecuteCommand()
{ {
//var work = Work.ToWork(); Work.FixOverLoad();
//work.FixOverLoad();
//Work = new(work);
} }
private void AddImage() private void AddImageCommand_ExecuteCommand()
{ {
OpenFileDialog openFileDialog = var openFileDialog = new OpenFileDialog()
new()
{ {
Title = "选择图片".Translate(), Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate() Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
}; };
if (openFileDialog.ShowDialog() is true) 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 = var openFileDialog = new OpenFileDialog()
new()
{ {
Title = "选择图片".Translate(), Title = "选择图片".Translate(),
Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate() Filter = $"图片|*.jpg;*.jpeg;*.png;*.bmp".Translate()
}; };
if (openFileDialog.ShowDialog() is true) if (openFileDialog.ShowDialog() is true)
{ {
Work.Image?.CloseStream(); Image?.CloseStream();
Work.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName); Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
} }
} }
public void Close()
{
Image?.CloseStream();
}
} }

View File

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

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -8,6 +9,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript; using LinePutScript;
using LinePutScript.Converter; using LinePutScript.Converter;
@ -23,43 +25,63 @@ namespace VPet.ModMaker.ViewModels;
public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM> public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
{ {
#region Value public ModMakerWindowVM(ModMakerWindow window)
public ModMakerWindow ModMakerWindow { get; } {
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>
/// 历史搜索文本 /// 历史搜索文本
/// </summary> /// </summary>
#region HistoriesSearchText #region HistoriesSearchText
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _historiesSearchText; private string _search = string.Empty;
public string HistoriesSearchText public string Search
{ {
get => _historiesSearchText; get => _search;
set => SetProperty(ref _historiesSearchText, value); set => SetProperty(ref _search, value);
}
#endregion
/// <summary>
/// 显示的历史
/// </summary>
#region ShowHistories
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<ModMakeHistory> _showHistories;
public ObservableCollection<ModMakeHistory> ShowHistories
{
get => _showHistories;
set => SetProperty(ref _showHistories, value);
} }
#endregion #endregion
/// <summary> /// <summary>
/// 历史 /// 历史
/// </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 #endregion
#region Command #region Command
/// <summary> /// <summary>
@ -83,32 +105,8 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
public ObservableCommand<ModMakeHistory> RemoveHistoryCommand { get; } = new(); public ObservableCommand<ModMakeHistory> RemoveHistoryCommand { get; } = new();
#endregion #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 #region History
private void RemoveHistory(ModMakeHistory value) private void RemoveHistoryCommand_ExecuteCommand(ModMakeHistory value)
{ {
Histories.Remove(value); Histories.Remove(value);
SaveHistories(); SaveHistories();
@ -122,14 +120,14 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
if (File.Exists(ModMakerInfo.HistoryFile) is false) if (File.Exists(ModMakerInfo.HistoryFile) is false)
return; return;
var lps = new LPS(File.ReadAllText(ModMakerInfo.HistoryFile)); var lps = new LPS(File.ReadAllText(ModMakerInfo.HistoryFile));
var set = new HashSet<ModMakeHistory>();
foreach (var line in lps) foreach (var line in lps)
{ {
if (LPSConvert.DeserializeObject<ModMakeHistory>(line) is not ModMakeHistory history) if (LPSConvert.DeserializeObject<ModMakeHistory>(line) is not ModMakeHistory history)
continue; continue;
if (Histories.All(h => h.InfoFile != history.InfoFile)) set.Add(history);
Histories.Add(history);
} }
Histories = new(Histories.OrderByDescending(h => h.LastTime)); Histories.AddRange(set.OrderByDescending(h => h.LastTime));
} }
/// <summary> /// <summary>
@ -158,7 +156,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
is ModMakeHistory history is ModMakeHistory history
) )
{ {
history.Id = modInfo.Id; history.ID = modInfo.ID;
history.SourcePath = modInfo.SourcePath; history.SourcePath = modInfo.SourcePath;
history.LastTime = DateTime.Now; history.LastTime = DateTime.Now;
} }
@ -167,7 +165,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
Histories.Add( Histories.Add(
new() new()
{ {
Id = modInfo.Id, ID = modInfo.ID,
SourcePath = modInfo.SourcePath, SourcePath = modInfo.SourcePath,
LastTime = DateTime.Now, LastTime = DateTime.Now,
} }
@ -175,14 +173,14 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
} }
} }
private void ClearHistories() private void ClearHistoriesCommand_ExecuteCommand()
{ {
if ( if (
MessageBox.Show("确定要清空吗?".Translate(), "", MessageBoxButton.YesNo) MessageBox.Show("确定要清空吗?".Translate(), "", MessageBoxButton.YesNo)
is not MessageBoxResult.Yes is not MessageBoxResult.Yes
) )
return; return;
ShowHistories.Clear(); Histories.Clear();
Histories.Clear(); Histories.Clear();
File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty); File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty);
} }
@ -192,7 +190,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
/// <summary> /// <summary>
/// 创建新模组 /// 创建新模组
/// </summary> /// </summary>
public void CreateNewMod() public void CreateNewModCommand_ExecuteCommand()
{ {
ModInfoModel.Current = new(); ModInfoModel.Current = new();
ShowEditWindow(); ShowEditWindow();
@ -241,10 +239,9 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
/// <summary> /// <summary>
/// 从文件载入模组 /// 从文件载入模组
/// </summary> /// </summary>
public void LoadModFromFile() public void LoadModFromFileCommand_ExecuteCommand()
{ {
OpenFileDialog openFileDialog = var openFileDialog = new OpenFileDialog()
new()
{ {
Title = "模组信息文件".Translate(), Title = "模组信息文件".Translate(),
Filter = $"LPS文件|*.lps;".Translate(), Filter = $"LPS文件|*.lps;".Translate(),
@ -252,7 +249,7 @@ public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
}; };
if (openFileDialog.ShowDialog() is true) 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); var modInfo = new ModInfoModel(loader);
EditMod(modInfo); 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(); pendingHandler.Close();
} }
catch (Exception ex) catch (Exception ex)
{ {
pendingHandler.Close(); pendingHandler.Close();
ModEditWindow?.Close(); ModEditWindow?.Close();
ModEditWindow = null; ModEditWindow = null!;
ModInfoModel.Current?.Close(); ModInfoModel.Current?.Close();
I18nHelper.Current = new(); I18nHelper.Current = new();
I18nEditWindow.Current?.Close(true); I18nEditWindow.Current?.Close(true);
ModMakerWindow.Show(); ModMakerWindow.Show();
ModMakerWindow.Activate(); ModMakerWindow.Activate();
MessageBox.Show(ModMakerWindow, "模组载入失败:\n{0}".Translate(ex)); MessageBox.Show(ModMakerWindow, "模组载入失败:\n{0}".Translate(ex));
GC.Collect();
} }
} }
#endregion #endregion

View File

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

View File

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

View File

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

View File

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

View File

@ -30,10 +30,10 @@ public partial class AnimePage : Page
public AnimePageVM ViewModel => (AnimePageVM)DataContext; 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is null)
return; 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; 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(); Close();
} }
private void Button_Yes_Click(object sender, RoutedEventArgs e) private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{ {
IsCancel = false; IsCancel = false;
Close(); Close();
} }
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) private void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
if (ViewModel is null) if (ViewModel is null)
return; 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) var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{ {
@ -89,7 +89,7 @@ public partial class FoodAnimeEditWindow : Window
private object _dropSender; 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) if (sender is not ListBox listBox)
return; return;
@ -107,7 +107,7 @@ public partial class FoodAnimeEditWindow : Window
DragDrop.DoDragDrop(listBox, dataObj, DragDropEffects.Move); 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) if (sender is not ListBox listBox)
return; return;
@ -156,7 +156,7 @@ public partial class FoodAnimeEditWindow : Window
list[targetIndex] = temp; 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) if (sender is not ListBox listBox)
return; return;
@ -166,7 +166,7 @@ public partial class FoodAnimeEditWindow : Window
e.Handled = true; e.Handled = true;
} }
private void ListBox_Animes_SelectionChanged(object sender, SelectionChangedEventArgs e) private void ListBox_Animes_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
e.Handled = true; e.Handled = true;
} }

View File

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

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -16,6 +17,7 @@ using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models; using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel; using VPet.ModMaker.Models.ModModel;
using VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
using VPet_Simulator.Core; using VPet_Simulator.Core;
namespace VPet.ModMaker.Views.ModEdit.AnimeEdit; namespace VPet.ModMaker.Views.ModEdit.AnimeEdit;
@ -25,63 +27,22 @@ namespace VPet.ModMaker.Views.ModEdit.AnimeEdit;
/// </summary> /// </summary>
public partial class SelectGraphTypeWindow : Window public partial class SelectGraphTypeWindow : Window
{ {
public SelectGraphTypeWindowVM ViewModel => (SelectGraphTypeWindowVM)DataContext;
public SelectGraphTypeWindow() public SelectGraphTypeWindow()
{ {
InitializeComponent(); InitializeComponent();
DataContext = this; this.SetDataContext<SelectGraphTypeWindowVM>();
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
GraphType.ValueChanged += GraphType_ValueChanged;
Closed += (s, e) =>
{
try
{
DataContext = null;
} }
catch { }
};
}
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; 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(); Close();
} }
private void Button_Yes_Click(object sender, RoutedEventArgs e) private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{ {
//if (string.IsNullOrWhiteSpace(AnimeName.Value)) //if (string.IsNullOrWhiteSpace(AnimeName.Value))
//{ //{

View File

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

View File

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

View File

@ -30,7 +30,7 @@ public partial class ClickTextPage : Page
DataContext = new ClickTextPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not ClickTextModel model)
return; 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(); 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)) if (string.IsNullOrWhiteSpace(ViewModel.Food.ID))
{ {

View File

@ -33,7 +33,7 @@ public partial class FoodPage : Page
DataContext = new FoodPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not FoodModel model)
return; return;

View File

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

View File

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

View File

@ -33,7 +33,7 @@ public partial class LowTextPage : Page
DataContext = new LowTextPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not LowTextModel lowText)
return; return;

View File

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

View File

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

View File

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

View File

@ -30,10 +30,10 @@ public partial class MovePage : Page
public MovePageVM ViewModel => (MovePageVM)DataContext; 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not MoveModel model)
return; return;
ViewModel.Edit(model); ViewModel.EditCommand_ExecuteCommand(model);
} }
} }

View File

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

View File

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

View File

@ -30,10 +30,10 @@ public partial class PetPage : Page
DataContext = new PetPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not PetModel model)
return; 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(); 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)) if (string.IsNullOrWhiteSpace(ViewModel.SelectText.ID))
{ {

View File

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

View File

@ -30,7 +30,7 @@ public partial class SelectTextPage : Page
DataContext = new SelectTextPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not SelectTextModel model)
return; return;

View File

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

View File

@ -28,27 +28,20 @@ public partial class WorkEditWindow : Window
public WorkEditWindow() public WorkEditWindow()
{ {
InitializeComponent(); InitializeComponent();
DataContext = new WorkEditWindowVM(); this.SetDataContext<WorkEditWindowVM>(() => {
Closed += (s, e) =>
{
//TODO //TODO
//ViewModel.Close(); //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(); 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); MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
@ -64,8 +57,8 @@ public partial class WorkEditWindow : Window
return; return;
} }
if ( if (
ViewModel.OldWork?.Id != ViewModel.Work.Id ViewModel.OldWork?.ID != ViewModel.Work.ID
&& ViewModel.CurrentPet.Works.Any(i => i.Id == ViewModel.Work.Id) && ViewModel.CurrentPet.Works.Any(i => i.ID == ViewModel.Work.ID)
) )
{ {
MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);

View File

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

View File

@ -30,10 +30,10 @@ public partial class WorkPage : Page
DataContext = new WorkPageVM(); 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) if (sender is not DataGrid dataGrid || dataGrid.SelectedItem is not WorkModel model)
return; return;
ViewModel.Edit(model); ViewModel.EditCommand_ExecuteCommand(model);
} }
} }

View File

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

View File

@ -41,7 +41,7 @@ public partial class ModMakerWindow : WindowX
//new AnimeEditWindow().Show(); //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) 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) if (sender is not ListBoxItem item)
return; return;
@ -65,13 +65,12 @@ public partial class ModMakerWindow : WindowX
) )
{ {
ViewModel.Histories.Remove(history); ViewModel.Histories.Remove(history);
ViewModel.ShowHistories.Remove(history);
} }
} }
ViewModel.LoadMod(history.SourcePath); 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")); Process.Start(new ProcessStartInfo("https://github.com/LorisYounger/VPet.ModMaker/wiki"));
} }