- 保存宠物时, 若本体存在同名宠物, 则只会保存差异数据
修复:
- 模组宠物和本体宠物同时出现的问题
This commit is contained in:
Hakoyu 2023-12-11 01:29:44 +08:00
parent fb81811be0
commit 9546fb604a
64 changed files with 1434 additions and 646 deletions

View File

@ -9,6 +9,7 @@
<c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" /> <c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" />
<c:MaxConverter x:Key="MaxConverter" /> <c:MaxConverter x:Key="MaxConverter" />
<c:FalseToHiddenConverter x:Key="FalseToHiddenConverter" /> <c:FalseToHiddenConverter x:Key="FalseToHiddenConverter" />
<c:FalseToCollapsedConverter x:Key="FalseToCollapsedConverter" />
<c:EqualsConverter x:Key="EqualsConverter" /> <c:EqualsConverter x:Key="EqualsConverter" />
<c:NotEqualsConverter x:Key="NotEqualsConverter" /> <c:NotEqualsConverter x:Key="NotEqualsConverter" />
<c:NullToFalseConverter x:Key="NullToFalseConverter" /> <c:NullToFalseConverter x:Key="NullToFalseConverter" />

View File

@ -1,5 +1,4 @@
using HKW.Models; using LinePutScript;
using LinePutScript;
using LinePutScript.Converter; using LinePutScript.Converter;
using LinePutScript.Dictionary; using LinePutScript.Dictionary;
using System; using System;

View File

@ -1,5 +1,4 @@
using HKW.Models; using LinePutScript.Converter;
using LinePutScript.Converter;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -9,7 +9,6 @@ using System.Windows.Controls;
using System.Windows; using System.Windows;
using VPet_Simulator.Windows.Interface; using VPet_Simulator.Windows.Interface;
using VPet.ModMaker.Views; using VPet.ModMaker.Views;
using HKW.Models;
namespace VPet.ModMaker.Models; namespace VPet.ModMaker.Models;
@ -51,12 +50,7 @@ public class ModMaker : MainPlugin
ModMakerInfo.GameVersion = MW.version; ModMakerInfo.GameVersion = MW.version;
// 载入本体宠物 // 载入本体宠物
foreach (var pet in MW.Pets) foreach (var pet in MW.Pets)
{ ModMakerInfo.MainPets.Add(pet.Name, new(pet, true));
var petModel = new PetModel();
petModel.SourceId = pet.Name;
petModel.Id.Value = pet.Name + " (来自本体)".Translate();
ModMakerInfo.Pets.Add(petModel);
}
//Maker.ModMaker = this; //Maker.ModMaker = this;
Maker.Show(); Maker.Show();
Maker.Closed += Maker_Closed; Maker.Closed += Maker_Closed;

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VPet.ModMaker.Models.ModModel; using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
namespace VPet.ModMaker.Models; namespace VPet.ModMaker.Models;
@ -34,11 +35,24 @@ public static class ModMakerInfo
/// <summary> /// <summary>
/// 本体的宠物 /// 本体的宠物
/// <para>
/// (PetId, PetModel)
/// </para>
/// </summary> /// </summary>
public static List<PetModel> Pets { get; } = new(); public static Dictionary<string, PetModel> MainPets { get; } = new();
/// <summary> /// <summary>
/// 本地风格 /// 本地风格
/// </summary> /// </summary>
public static NativeStyles NativeStyles { get; } = new(); public static NativeStyles NativeStyles { get; } = new();
/// <summary>
/// 是含有名称的动画
/// </summary>
/// <param name="graphType"></param>
/// <returns></returns>
public static bool IsHasNameAnime(this GraphInfo.GraphType graphType)
{
return AnimeTypeModel.HasNameAnimes.Contains(graphType);
}
} }

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;

View File

@ -1,5 +1,6 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils;
using HKW.Models; using HKW.HKWUtils.Observable;
using LinePutScript.Converter; using LinePutScript.Converter;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -145,14 +146,14 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
Working.Value = clickText.Working; Working.Value = clickText.Working;
WorkingState.Value = clickText.State; WorkingState.Value = clickText.State;
DayTime.EnumValue.Value = clickText.DaiTime; DayTime.EnumValue.Value = clickText.DaiTime;
Like.SetValue(clickText.LikeMin, clickText.LikeMax); Like = new(clickText.LikeMin, clickText.LikeMax);
Health.SetValue(clickText.HealthMin, clickText.HealthMax); Health = new(clickText.HealthMin, clickText.HealthMax);
Level.SetValue(clickText.LevelMin, clickText.LevelMax); Level = new(clickText.LevelMin, clickText.LevelMax);
Money.SetValue(clickText.MoneyMin, clickText.MoneyMax); Money = new(clickText.MoneyMin, clickText.MoneyMax);
Food.SetValue(clickText.FoodMin, clickText.FoodMax); Food = new(clickText.FoodMin, clickText.FoodMax);
Drink.SetValue(clickText.DrinkMin, clickText.DrinkMax); Drink = new(clickText.DrinkMin, clickText.DrinkMax);
Feel.SetValue(clickText.FeelMin, clickText.FeelMax); Feel = new(clickText.FeelMin, clickText.FeelMax);
Strength.SetValue(clickText.StrengthMin, clickText.StrengthMax); Strength = new(clickText.StrengthMin, clickText.StrengthMax);
} }
public ClickText ToClickText() public ClickText ToClickText()
@ -164,22 +165,22 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
Working = Working.Value, Working = Working.Value,
State = WorkingState.Value, State = WorkingState.Value,
DaiTime = DayTime.EnumValue.Value, DaiTime = DayTime.EnumValue.Value,
LikeMax = Like.Max.Value, LikeMax = Like.Max,
LikeMin = Like.Min.Value, LikeMin = Like.Min,
HealthMin = Health.Min.Value, HealthMin = Health.Min,
HealthMax = Health.Max.Value, HealthMax = Health.Max,
LevelMin = Level.Min.Value, LevelMin = Level.Min,
LevelMax = Level.Max.Value, LevelMax = Level.Max,
MoneyMin = Money.Min.Value, MoneyMin = Money.Min,
MoneyMax = Money.Max.Value, MoneyMax = Money.Max,
FoodMin = Food.Min.Value, FoodMin = Food.Min,
FoodMax = Food.Max.Value, FoodMax = Food.Max,
DrinkMin = Drink.Min.Value, DrinkMin = Drink.Min,
DrinkMax = Drink.Max.Value, DrinkMax = Drink.Max,
FeelMin = Feel.Min.Value, FeelMin = Feel.Min,
FeelMax = Feel.Max.Value, FeelMax = Feel.Max,
StrengthMin = Strength.Min.Value, StrengthMin = Strength.Min,
StrengthMax = Strength.Max.Value, StrengthMax = Strength.Max,
}; };
} }
} }

View File

@ -48,7 +48,7 @@ public class FoodAnimeModel
foodLocationInfo.Duration.Value = int.Parse(infos[0]); foodLocationInfo.Duration.Value = int.Parse(infos[0]);
if (infos.Length > 1) if (infos.Length > 1)
{ {
foodLocationInfo.Rect.SetValue( foodLocationInfo.Rect = 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]),

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript; using LinePutScript;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;

View File

@ -20,7 +20,7 @@ public class FoodLocationModel
/// <summary> /// <summary>
/// 范围 /// 范围
/// </summary> /// </summary>
public ObservableRect<double> Rect { get; } = new(); public ObservableRect<double> Rect { get; set; } = new();
/// <summary> /// <summary>
/// 旋转角度 /// 旋转角度
@ -34,9 +34,9 @@ public class FoodLocationModel
public FoodLocationModel() public FoodLocationModel()
{ {
Rect.Width.ValueChanged += (s, e) => Rect.PropertyChangedX += (s, e) =>
{ {
Rect.Height.Value = e.NewValue; Rect.Height = (int)e.NewValue;
}; };
} }
@ -44,7 +44,7 @@ public class FoodLocationModel
{ {
var model = new FoodLocationModel(); var model = new FoodLocationModel();
model.Duration.Value = Duration.Value; model.Duration.Value = Duration.Value;
model.Rect.SetValue(Rect.X.Value, Rect.Y.Value, Rect.Width.Value, Rect.Height.Value); model.Rect = new(Rect.X, Rect.Y, Rect.Width, Rect.Height);
model.Rotate.Value = Rotate.Value; model.Rotate.Value = Rotate.Value;
model.Opacity.Value = Opacity.Value; model.Opacity.Value = Opacity.Value;
return model; return model;
@ -52,6 +52,6 @@ public class FoodLocationModel
public override string ToString() public override string ToString()
{ {
return $"{Duration.Value},{Rect.X.Value},{Rect.Y.Value},{Rect.Width.Value},{Rotate.Value},{Opacity.Value}"; return $"{Duration.Value}, {Rect.X}, {Rect.Y}, {Rect.Width}, {Rotate.Value}, {Opacity.Value}";
} }
} }

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript; using LinePutScript;
using LinePutScript.Converter; using LinePutScript.Converter;
using System; using System;

View File

@ -1,5 +1,6 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils;
using HKW.Models; using HKW.HKWUtils.Observable;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,5 +1,6 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils;
using HKW.Models; using HKW.HKWUtils.Observable;
using LinePutScript; using LinePutScript;
using LinePutScript.Converter; using LinePutScript.Converter;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
@ -20,6 +21,7 @@ using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.Models; namespace VPet.ModMaker.Models;
// TODO: 本体模组显示开关
/// <summary> /// <summary>
/// 模组信息模型 /// 模组信息模型
/// </summary> /// </summary>
@ -142,6 +144,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
foreach (var selectText in loader.SelectTexts) foreach (var selectText in loader.SelectTexts)
SelectTexts.Add(new(selectText)); SelectTexts.Add(new(selectText));
// 载入模组宠物
foreach (var pet in loader.Pets) foreach (var pet in loader.Pets)
{ {
var petModel = new PetModel(pet); var petModel = new PetModel(pet);
@ -149,14 +152,16 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
foreach (var p in pet.path) foreach (var p in pet.path)
LoadAnime(petModel, p); LoadAnime(petModel, p);
} }
// 插入本体宠物 // 插入本体宠物
foreach (var pet in ModMakerInfo.Pets) foreach (var pet in ModMakerInfo.MainPets)
{ {
// 确保Id不重复 // 确保Id不重复
if (Pets.All(i => i.Id.Value != pet.SourceId)) if (Pets.All(i => i.Id.Value != pet.Key))
Pets.Insert(0, pet); Pets.Insert(0, pet.Value);
} }
// 载入本地化
foreach (var lang in loader.I18nDatas) foreach (var lang in loader.I18nDatas)
I18nDatas.Add(lang.Key, lang.Value); I18nDatas.Add(lang.Key, lang.Value);
OtherI18nDatas = loader.OtherI18nDatas; OtherI18nDatas = loader.OtherI18nDatas;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils;
using HKW.Models; using HKW.HKWUtils.Observable;
using LinePutScript; using LinePutScript;
using LinePutScript.Converter; using LinePutScript.Converter;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
@ -23,9 +23,9 @@ namespace VPet.ModMaker.Models;
public class PetModel : I18nModel<I18nPetInfoModel> public class PetModel : I18nModel<I18nPetInfoModel>
{ {
/// <summary> /// <summary>
/// 显示的Id 若不为空则判断为来自本体的宠物 /// 来自本体
/// </summary> /// </summary>
public string? SourceId { get; set; } = null; public ObservableValue<bool> FromMain { get; set; } = new(false);
/// <summary> /// <summary>
/// Id /// Id
@ -95,8 +95,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
public ObservableValue<int> AnimeCount { get; } = new(); public ObservableValue<int> AnimeCount { get; } = new();
public bool IsSimplePetModel { get; } = false;
public PetModel() public PetModel()
{ {
PetNameId.Value = $"{Id.Value}_{nameof(PetNameId)}"; PetNameId.Value = $"{Id.Value}_{nameof(PetNameId)}";
@ -131,68 +129,62 @@ public class PetModel : I18nModel<I18nPetInfoModel>
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value]; CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
} }
public PetModel(PetLoader loader) public PetModel(PetLoader loader, bool fromMain = false)
: this() : this()
{ {
Id.Value = loader.Name; Id.Value = loader.Name;
PetNameId.Value = loader.PetName; PetNameId.Value = loader.PetName;
DescriptionId.Value = loader.Intor; DescriptionId.Value = loader.Intor;
TouchHeadRect.Value.SetValue( TouchHeadRect.Value = 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.Value.SetValue( TouchBodyRect.Value = 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.Value.Happy.Value.SetValue( TouchRaisedRect.Value.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.Value.Nomal.Value.SetValue( TouchRaisedRect.Value.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.Value.PoorCondition.Value.SetValue( TouchRaisedRect.Value.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.Value.Ill.Value.SetValue( TouchRaisedRect.Value.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,
loader.Config.TouchRaisedSize[3].Height loader.Config.TouchRaisedSize[3].Height
); );
RaisePoint.Value.Happy.Value.SetValue( RaisePoint.Value.Happy = new(loader.Config.RaisePoint[0].X, loader.Config.RaisePoint[0].Y);
loader.Config.RaisePoint[0].X, RaisePoint.Value.Nomal = new(loader.Config.RaisePoint[1].X, loader.Config.RaisePoint[1].Y);
loader.Config.RaisePoint[0].Y RaisePoint.Value.PoorCondition = new(
);
RaisePoint.Value.Nomal.Value.SetValue(
loader.Config.RaisePoint[1].X,
loader.Config.RaisePoint[1].Y
);
RaisePoint.Value.PoorCondition.Value.SetValue(
loader.Config.RaisePoint[2].X, loader.Config.RaisePoint[2].X,
loader.Config.RaisePoint[2].Y loader.Config.RaisePoint[2].Y
); );
RaisePoint.Value.Ill.Value.SetValue( RaisePoint.Value.Ill = new(loader.Config.RaisePoint[3].X, loader.Config.RaisePoint[3].Y);
loader.Config.RaisePoint[3].X, // 如果这个宠物数据来自本体, 则不载入 Work 和 Move
loader.Config.RaisePoint[3].Y if (FromMain.Value = fromMain)
); return;
foreach (var work in loader.Config.Works) foreach (var work in loader.Config.Works)
Works.Add(new(work)); Works.Add(new(work));
@ -200,13 +192,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
Moves.Add(new(move)); Moves.Add(new(move));
} }
public PetModel(PetLoader loader, bool isSimplePet)
: this()
{
Id.Value = loader.Name;
IsSimplePetModel = isSimplePet;
}
public void Close() public void Close()
{ {
foreach (var anime in Animes) foreach (var anime in Animes)
@ -222,13 +207,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// <param name="path">路径</param> /// <param name="path">路径</param>
public void Save(string path) public void Save(string path)
{ {
if (IsSimplePetModel)
{
Id.Value = SourceId;
SaveSimplePetInfo(path);
Id.Value = SourceId + " (来自本体)".Translate();
return;
}
foreach (var cultureName in I18nHelper.Current.CultureNames) foreach (var cultureName in I18nHelper.Current.CultureNames)
{ {
ModInfoModel.SaveI18nDatas[cultureName].TryAdd( ModInfoModel.SaveI18nDatas[cultureName].TryAdd(
@ -248,7 +226,11 @@ public class PetModel : I18nModel<I18nPetInfoModel>
if (File.Exists(petFile) is false) if (File.Exists(petFile) is false)
File.Create(petFile).Close(); File.Create(petFile).Close();
var lps = new LPS(); var lps = new LPS();
SavePetInfo(lps); // 如果本体中存在相同的宠物, 则只保存差异信息
if (ModMakerInfo.MainPets.TryGetValue(Id.Value, out var mainPet))
SaveDifferentPetInfo(lps, mainPet);
else
SavePetInfo(lps);
SaveWorksInfo(lps); SaveWorksInfo(lps);
SaveMoveInfo(lps); SaveMoveInfo(lps);
File.WriteAllText(petFile, lps.ToString()); File.WriteAllText(petFile, lps.ToString());
@ -257,18 +239,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
SaveAnime(path); SaveAnime(path);
} }
private void SaveSimplePetInfo(string path)
{
if (Works.Count == 0 && Moves.Count == 0 && Animes.Count == 0)
return;
var petFile = Path.Combine(path, $"{Id.Value}.lps");
var lps = new LPS { new Line("pet", Id.Value) { new Sub("path", Id.Value), } };
SaveWorksInfo(lps);
SaveMoveInfo(lps);
File.WriteAllText(petFile, lps.ToString());
SaveAnime(path);
}
private void SaveAnime(string path) private void SaveAnime(string path)
{ {
var petAnimePath = Path.Combine(path, Id.Value); var petAnimePath = Path.Combine(path, Id.Value);
@ -311,12 +281,42 @@ public class PetModel : I18nModel<I18nPetInfoModel>
} }
} }
#region SavePetInfo
/// <summary> /// <summary>
/// 保存宠物信息 /// 保存宠物信息
/// </summary> /// </summary>
/// <param name="lps"></param> /// <param name="lps"></param>
/// <param name="pet"></param>
private void SavePetInfo(LPS lps) private void SavePetInfo(LPS lps)
{
SavePetBasicInfo(lps);
SavePetTouchHeadInfo(lps);
SavePetTouchBodyInfo(lps);
SavePetTouchRaisedInfo(lps);
SavePetRaisePointInfo(lps);
}
/// <summary>
/// 保存差异宠物信息
/// <para>
/// 用于本体存在同名宠物的情况下
/// </para>
/// </summary>
/// <param name="lps"></param>
/// <param name="mainPet">本体宠物</param>
private void SaveDifferentPetInfo(LPS lps, PetModel mainPet)
{
SavePetBasicInfo(lps);
if (TouchHeadRect != mainPet.TouchHeadRect)
SavePetTouchHeadInfo(lps);
if (TouchBodyRect != mainPet.TouchBodyRect)
SavePetTouchBodyInfo(lps);
if (TouchRaisedRect != mainPet.TouchRaisedRect)
SavePetTouchRaisedInfo(lps);
if (RaisePoint != mainPet.RaisePoint)
SavePetRaisePointInfo(lps);
}
private void SavePetBasicInfo(LPS lps)
{ {
lps.Add( lps.Add(
new Line("pet", Id.Value) new Line("pet", Id.Value)
@ -326,65 +326,82 @@ public class PetModel : I18nModel<I18nPetInfoModel>
new Sub("petname", PetNameId.Value) new Sub("petname", PetNameId.Value)
} }
); );
}
private void SavePetTouchHeadInfo(LPS lps)
{
lps.Add( lps.Add(
new Line("touchhead") new Line("touchhead")
{ {
new Sub("px", TouchHeadRect.Value.X.Value), new Sub("px", TouchHeadRect.Value.X),
new Sub("py", TouchHeadRect.Value.Y.Value), new Sub("py", TouchHeadRect.Value.Y),
new Sub("sw", TouchHeadRect.Value.Width.Value), new Sub("sw", TouchHeadRect.Value.Width),
new Sub("sh", TouchHeadRect.Value.Height.Value), new Sub("sh", TouchHeadRect.Value.Height),
}
);
lps.Add(
new Line("touchbody")
{
new Sub("px", TouchBodyRect.Value.X.Value),
new Sub("py", TouchBodyRect.Value.Y.Value),
new Sub("sw", TouchBodyRect.Value.Width.Value),
new Sub("sh", TouchBodyRect.Value.Height.Value),
}
);
lps.Add(
new Line("touchraised")
{
new Sub("happy_px", TouchRaisedRect.Value.Happy.Value.X.Value),
new Sub("happy_py", TouchRaisedRect.Value.Happy.Value.Y.Value),
new Sub("happy_sw", TouchRaisedRect.Value.Happy.Value.Width.Value),
new Sub("happy_sh", TouchRaisedRect.Value.Happy.Value.Height.Value),
//
new Sub("nomal_px", TouchRaisedRect.Value.Nomal.Value.X.Value),
new Sub("nomal_py", TouchRaisedRect.Value.Nomal.Value.Y.Value),
new Sub("nomal_sw", TouchRaisedRect.Value.Nomal.Value.Width.Value),
new Sub("nomal_sh", TouchRaisedRect.Value.Nomal.Value.Height.Value),
//
new Sub("poorcondition_px", TouchRaisedRect.Value.PoorCondition.Value.X.Value),
new Sub("poorcondition_py", TouchRaisedRect.Value.PoorCondition.Value.Y.Value),
new Sub("poorcondition_sw", TouchRaisedRect.Value.PoorCondition.Value.Width.Value),
new Sub("poorcondition_sh", TouchRaisedRect.Value.PoorCondition.Value.Height.Value),
//
new Sub("ill_px", TouchRaisedRect.Value.Ill.Value.X.Value),
new Sub("ill_py", TouchRaisedRect.Value.Ill.Value.Y.Value),
new Sub("ill_sw", TouchRaisedRect.Value.Ill.Value.Width.Value),
new Sub("ill_sh", TouchRaisedRect.Value.Ill.Value.Height.Value),
}
);
lps.Add(
new Line("raisepoint")
{
new Sub("happy_x", RaisePoint.Value.Happy.Value.X.Value),
new Sub("happy_y", RaisePoint.Value.Happy.Value.Y.Value),
//
new Sub("nomal_x", RaisePoint.Value.Nomal.Value.X.Value),
new Sub("nomal_y", RaisePoint.Value.Nomal.Value.Y.Value),
//
new Sub("poorcondition_x", RaisePoint.Value.PoorCondition.Value.X.Value),
new Sub("poorcondition_y", RaisePoint.Value.PoorCondition.Value.Y.Value),
//
new Sub("ill_x", RaisePoint.Value.Ill.Value.X.Value),
new Sub("ill_y", RaisePoint.Value.Ill.Value.Y.Value),
} }
); );
} }
private void SavePetTouchBodyInfo(LPS lps)
{
lps.Add(
new Line("touchbody")
{
new Sub("px", TouchBodyRect.Value.X),
new Sub("py", TouchBodyRect.Value.Y),
new Sub("sw", TouchBodyRect.Value.Width),
new Sub("sh", TouchBodyRect.Value.Height),
}
);
}
private void SavePetTouchRaisedInfo(LPS lps)
{
lps.Add(
new Line("touchraised")
{
new Sub("happy_px", TouchRaisedRect.Value.Happy.X),
new Sub("happy_py", TouchRaisedRect.Value.Happy.Y),
new Sub("happy_sw", TouchRaisedRect.Value.Happy.Width),
new Sub("happy_sh", TouchRaisedRect.Value.Happy.Height),
//
new Sub("nomal_px", TouchRaisedRect.Value.Nomal.X),
new Sub("nomal_py", TouchRaisedRect.Value.Nomal.Y),
new Sub("nomal_sw", TouchRaisedRect.Value.Nomal.Width),
new Sub("nomal_sh", TouchRaisedRect.Value.Nomal.Height),
//
new Sub("poorcondition_px", TouchRaisedRect.Value.PoorCondition.X),
new Sub("poorcondition_py", TouchRaisedRect.Value.PoorCondition.Y),
new Sub("poorcondition_sw", TouchRaisedRect.Value.PoorCondition.Width),
new Sub("poorcondition_sh", TouchRaisedRect.Value.PoorCondition.Height),
//
new Sub("ill_px", TouchRaisedRect.Value.Ill.X),
new Sub("ill_py", TouchRaisedRect.Value.Ill.Y),
new Sub("ill_sw", TouchRaisedRect.Value.Ill.Width),
new Sub("ill_sh", TouchRaisedRect.Value.Ill.Height),
}
);
}
private void SavePetRaisePointInfo(LPS lps)
{
lps.Add(
new Line("raisepoint")
{
new Sub("happy_x", RaisePoint.Value.Happy.X),
new Sub("happy_y", RaisePoint.Value.Happy.Y),
//
new Sub("nomal_x", RaisePoint.Value.Nomal.X),
new Sub("nomal_y", RaisePoint.Value.Nomal.Y),
//
new Sub("poorcondition_x", RaisePoint.Value.PoorCondition.X),
new Sub("poorcondition_y", RaisePoint.Value.PoorCondition.Y),
//
new Sub("ill_x", RaisePoint.Value.Ill.X),
new Sub("ill_y", RaisePoint.Value.Ill.Y),
}
);
}
#endregion
#endregion #endregion
} }
@ -405,13 +422,41 @@ public class I18nPetInfoModel
} }
public class ObservableMultiStateRect public class ObservableMultiStateRect
: ObservableClass<ObservableMultiStateRect>,
IEquatable<ObservableMultiStateRect>
{ {
public ObservableValue<ObservableRect<double>> Happy { get; } = new(new()); private ObservableRect<double> _happy;
public ObservableValue<ObservableRect<double>> Nomal { get; } = new(new()); public ObservableRect<double> Happy
public ObservableValue<ObservableRect<double>> PoorCondition { get; } = new(new()); {
public ObservableValue<ObservableRect<double>> Ill { get; } = new(new()); get => _happy;
set => SetProperty(ref _happy, value);
}
private ObservableRect<double> _nomal;
public ObservableRect<double> Nomal
{
get => _nomal;
set => SetProperty(ref _nomal, value);
}
private ObservableRect<double> _poorCondition;
public ObservableRect<double> PoorCondition
{
get => _poorCondition;
set => SetProperty(ref _poorCondition, value);
}
private ObservableRect<double> _ill;
public ObservableRect<double> Ill
{
get => _ill;
set => SetProperty(ref _ill, value);
}
public ObservableMultiStateRect() { } public ObservableMultiStateRect()
{
Happy = new();
Nomal = new();
PoorCondition = new();
Ill = new();
}
public ObservableMultiStateRect( public ObservableMultiStateRect(
ObservableRect<double> happy, ObservableRect<double> happy,
@ -420,31 +465,101 @@ public class ObservableMultiStateRect
ObservableRect<double> ill ObservableRect<double> ill
) )
{ {
Happy.Value = happy; Happy = happy;
Nomal.Value = nomal; Nomal = nomal;
PoorCondition.Value = poorCondition; PoorCondition = poorCondition;
Ill.Value = ill; Ill = ill;
} }
public ObservableMultiStateRect Copy() public ObservableMultiStateRect Copy()
{ {
var result = new ObservableMultiStateRect(); return new()
result.Happy.Value = Happy.Value.Copy(); {
result.Nomal.Value = Nomal.Value.Copy(); Happy = Happy.Copy(),
result.PoorCondition.Value = PoorCondition.Value.Copy(); Nomal = Nomal.Copy(),
result.Ill.Value = Ill.Value.Copy(); PoorCondition = PoorCondition.Copy(),
return result; Ill = Ill.Copy(),
};
} }
#region Other
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(Happy, Nomal, PoorCondition, Ill);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableMultiStateRect temp
&& EqualityComparer<ObservableRect<double>>.Default.Equals(Happy, temp.Happy)
&& EqualityComparer<ObservableRect<double>>.Default.Equals(Nomal, temp.Nomal)
&& EqualityComparer<ObservableRect<double>>.Default.Equals(
PoorCondition,
temp.PoorCondition
)
&& EqualityComparer<ObservableRect<double>>.Default.Equals(Ill, temp.Ill);
}
/// <inheritdoc/>
public bool Equals(ObservableMultiStateRect? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservableMultiStateRect a, ObservableMultiStateRect b)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableMultiStateRect a, ObservableMultiStateRect b)
{
return Equals(a, b) is not true;
}
#endregion
} }
public class ObservableMultiStatePoint public class ObservableMultiStatePoint
: ObservableClass<ObservableMultiStatePoint>,
IEquatable<ObservableMultiStatePoint>
{ {
public ObservableValue<ObservablePoint<double>> Happy { get; } = new(new()); private ObservablePoint<double> _happy;
public ObservableValue<ObservablePoint<double>> Nomal { get; } = new(new()); public ObservablePoint<double> Happy
public ObservableValue<ObservablePoint<double>> PoorCondition { get; } = new(new()); {
public ObservableValue<ObservablePoint<double>> Ill { get; } = new(new()); get => _happy;
set => SetProperty(ref _happy, value);
}
private ObservablePoint<double> _nomal;
public ObservablePoint<double> Nomal
{
get => _nomal;
set => SetProperty(ref _nomal, value);
}
private ObservablePoint<double> _poorCondition;
public ObservablePoint<double> PoorCondition
{
get => _poorCondition;
set => SetProperty(ref _poorCondition, value);
}
private ObservablePoint<double> _ill;
public ObservablePoint<double> Ill
{
get => _ill;
set => SetProperty(ref _ill, value);
}
public ObservableMultiStatePoint() { } public ObservableMultiStatePoint()
{
Happy = new();
Nomal = new();
PoorCondition = new();
Ill = new();
}
public ObservableMultiStatePoint( public ObservableMultiStatePoint(
ObservablePoint<double> happy, ObservablePoint<double> happy,
@ -453,19 +568,61 @@ public class ObservableMultiStatePoint
ObservablePoint<double> ill ObservablePoint<double> ill
) )
{ {
Happy.Value = happy; Happy = happy;
Nomal.Value = nomal; Nomal = nomal;
PoorCondition.Value = poorCondition; PoorCondition = poorCondition;
Ill.Value = ill; Ill = ill;
} }
public ObservableMultiStatePoint Copy() public ObservableMultiStatePoint Copy()
{ {
var result = new ObservableMultiStatePoint(); return new()
result.Happy.Value = Happy.Value.Copy(); {
result.Nomal.Value = Nomal.Value.Copy(); Happy = Happy.Copy(),
result.PoorCondition.Value = PoorCondition.Value.Copy(); Nomal = Nomal.Copy(),
result.Ill.Value = Ill.Value.Copy(); PoorCondition = PoorCondition.Copy(),
return result; Ill = Ill.Copy(),
};
} }
#region Other
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(Happy, Nomal, PoorCondition, Ill);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableMultiStatePoint temp
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Happy, temp.Happy)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Nomal, temp.Nomal)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(
PoorCondition,
temp.PoorCondition
)
&& EqualityComparer<ObservablePoint<double>>.Default.Equals(Ill, temp.Ill);
}
/// <inheritdoc/>
public bool Equals(ObservableMultiStatePoint? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservableMultiStatePoint a, ObservableMultiStatePoint b)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableMultiStatePoint a, ObservableMultiStatePoint b)
{
return Equals(a, b) is not true;
}
#endregion
} }

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -130,14 +130,14 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
Mode.EnumValue.Value = text.Mode; Mode.EnumValue.Value = text.Mode;
Tags.Value = text.Tags is null ? string.Empty : string.Join(", ", text.Tags); Tags.Value = text.Tags is null ? string.Empty : string.Join(", ", text.Tags);
ToTags.Value = text.ToTags is null ? string.Empty : string.Join(", ", text.ToTags); ToTags.Value = text.ToTags is null ? string.Empty : string.Join(", ", text.ToTags);
Like.SetValue(text.LikeMin, text.LikeMax); Like = new(text.LikeMin, text.LikeMax);
Health.SetValue(text.HealthMin, text.HealthMax); Health = new(text.HealthMin, text.HealthMax);
Level.SetValue(text.LevelMin, text.LevelMax); Level = new(text.LevelMin, text.LevelMax);
Money.SetValue(text.MoneyMin, text.MoneyMax); Money = new(text.MoneyMin, text.MoneyMax);
Food.SetValue(text.FoodMin, text.FoodMax); Food = new(text.FoodMin, text.FoodMax);
Drink.SetValue(text.DrinkMin, text.DrinkMax); Drink = new(text.DrinkMin, text.DrinkMax);
Feel.SetValue(text.FeelMin, text.FeelMax); Feel = new(text.FeelMin, text.FeelMax);
Strength.SetValue(text.StrengthMin, text.StrengthMax); Strength = new(text.StrengthMin, text.StrengthMax);
} }
private readonly static char[] rs_splitChar = { ',', ' ' }; private readonly static char[] rs_splitChar = { ',', ' ' };
@ -151,22 +151,22 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
Mode = Mode.EnumValue.Value, Mode = Mode.EnumValue.Value,
Tags = new(Tags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)), Tags = new(Tags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
ToTags = new(ToTags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)), ToTags = new(ToTags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
LikeMax = Like.Max.Value, LikeMax = Like.Max,
LikeMin = Like.Min.Value, LikeMin = Like.Min,
HealthMin = Health.Min.Value, HealthMin = Health.Min,
HealthMax = Health.Max.Value, HealthMax = Health.Max,
LevelMin = Level.Min.Value, LevelMin = Level.Min,
LevelMax = Level.Max.Value, LevelMax = Level.Max,
MoneyMin = Money.Min.Value, MoneyMin = Money.Min,
MoneyMax = Money.Max.Value, MoneyMax = Money.Max,
FoodMin = Food.Min.Value, FoodMin = Food.Min,
FoodMax = Food.Max.Value, FoodMax = Food.Max,
DrinkMin = Drink.Min.Value, DrinkMin = Drink.Min,
DrinkMax = Drink.Max.Value, DrinkMax = Drink.Max,
FeelMin = Feel.Min.Value, FeelMin = Feel.Min,
FeelMax = Feel.Max.Value, FeelMax = Feel.Max,
StrengthMin = Strength.Min.Value, StrengthMin = Strength.Min,
StrengthMax = Strength.Max.Value, StrengthMax = Strength.Max,
}; };
} }
} }

View File

@ -1,31 +1,31 @@
using HKW.HKWUtils.Observable; //using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models; //namespace VPet.ModMaker.Models;
public class ObservablePoint<T> //public class ObservablePoint<T>
{ //{
public ObservableValue<T> X { get; } = new(); // public ObservableValue<T> X { get; } = new();
public ObservableValue<T> Y { get; } = new(); // public ObservableValue<T> Y { get; } = new();
public ObservablePoint() { } // public ObservablePoint() { }
public ObservablePoint(T x, T y) // public ObservablePoint(T x, T y)
{ // {
X.Value = x; // X.Value = x;
Y.Value = y; // Y.Value = y;
} // }
public void SetValue(T x, T y) // public void SetValue(T x, T y)
{ // {
X.Value = x; // X.Value = x;
Y.Value = y; // Y.Value = y;
} // }
public ObservablePoint<T> Copy() // public ObservablePoint<T> Copy()
{ // {
var result = new ObservablePoint<T>(); // var result = new ObservablePoint<T>();
result.X.Value = X.Value; // result.X.Value = X.Value;
result.Y.Value = Y.Value; // result.Y.Value = Y.Value;
return result; // return result;
} // }
} //}

View File

@ -1,62 +1,62 @@
using HKW.HKWUtils.Observable; //using HKW.HKWUtils.Observable;
namespace HKW.Models; //namespace HKW.Models;
/// <summary> ///// <summary>
/// 可观察的范围 ///// 可观察的范围
/// </summary> ///// </summary>
/// <typeparam name="T">类型</typeparam> ///// <typeparam name="T">类型</typeparam>
public class ObservableRange<T> //public class ObservableRange<T>
{ //{
/// <summary> // /// <summary>
/// 最小值 // /// 最小值
/// </summary> // /// </summary>
public ObservableValue<T> Min { get; } = new(); // public ObservableValue<T> Min { get; } = new();
/// <summary> // /// <summary>
/// 最大值 // /// 最大值
/// </summary> // /// </summary>
public ObservableValue<T> Max { get; } = new(); // public ObservableValue<T> Max { get; } = new();
/// <summary> // /// <summary>
/// 信息 // /// 信息
/// </summary> // /// </summary>
public ObservableValue<string> Info { get; } = new(); // public ObservableValue<string> Info { get; } = new();
public ObservableRange() // public ObservableRange()
{ // {
Min.ValueChanged += ValueChanged; // Min.ValueChanged += ValueChanged;
Max.ValueChanged += ValueChanged; // Max.ValueChanged += ValueChanged;
} // }
public ObservableRange(T min, T max) // public ObservableRange(T min, T max)
: this() // : this()
{ // {
SetValue(min, max); // SetValue(min, max);
} // }
private void ValueChanged(ObservableValue<T> sender, ValueChangedEventArgs<T> e) // private void ValueChanged(ObservableValue<T> sender, ValueChangedEventArgs<T> e)
{ // {
Info.Value = $"({Min.Value}, {Max.Value})"; // Info.Value = $"({Min.Value}, {Max.Value})";
} // }
/// <summary> // /// <summary>
/// 设置值 // /// 设置值
/// </summary> // /// </summary>
/// <param name="min">最小值</param> // /// <param name="min">最小值</param>
/// <param name="max">最大值</param> // /// <param name="max">最大值</param>
public void SetValue(T min, T max) // public void SetValue(T min, T max)
{ // {
Min.Value = min; // Min.Value = min;
Max.Value = max; // Max.Value = max;
} // }
/// <summary> // /// <summary>
/// 复制 // /// 复制
/// </summary> // /// </summary>
/// <returns></returns> // /// <returns></returns>
public ObservableRange<T> Copy() // public ObservableRange<T> Copy()
{ // {
return new(Min.Value, Max.Value); // return new(Min.Value, Max.Value);
} // }
} //}

View File

@ -1,39 +1,41 @@
using HKW.HKWUtils.Observable; //using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models; //namespace VPet.ModMaker.Models;
public class ObservableRect<T> //public class ObservableRect<T>
{ //{
public ObservableValue<T> X { get; } = new(); // public ObservableValue<T> X { get; } = new();
public ObservableValue<T> Y { get; } = new(); // public ObservableValue<T> Y { get; } = new();
public ObservableValue<T> Width { get; } = new(); // public ObservableValue<T> Width { get; } = new();
public ObservableValue<T> Height { get; } = new(); // public ObservableValue<T> Height { get; } = new();
public ObservableRect() { } // public bool Changed { get; set; } = true;
public ObservableRect(T x, T y, T width, T hetght) // public ObservableRect() { }
{
X.Value = x;
Y.Value = y;
Width.Value = width;
Height.Value = hetght;
}
public void SetValue(T x, T y, T width, T hetght) // public ObservableRect(T x, T y, T width, T hetght)
{ // {
X.Value = x; // X.Value = x;
Y.Value = y; // Y.Value = y;
Width.Value = width; // Width.Value = width;
Height.Value = hetght; // Height.Value = hetght;
} // }
public ObservableRect<T> Copy() // public void SetValue(T x, T y, T width, T hetght)
{ // {
var result = new ObservableRect<T>(); // X.Value = x;
result.X.Value = X.Value; // Y.Value = y;
result.Y.Value = Y.Value; // Width.Value = width;
result.Width.Value = Width.Value; // Height.Value = hetght;
result.Height.Value = Height.Value; // }
return result;
} // public ObservableRect<T> Copy()
} // {
// var result = new ObservableRect<T>();
// result.X.Value = X.Value;
// result.Y.Value = Y.Value;
// result.Width.Value = Width.Value;
// result.Height.Value = Height.Value;
// return result;
// }
//}

View File

@ -0,0 +1,12 @@
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 通知属性改变后接口
/// </summary>
public interface INotifyPropertyChangedX<TSender>
{
/// <summary>
/// 通知属性改变后事件
/// </summary>
public event PropertyChangedXEventHandler<TSender>? PropertyChangedX;
}

View File

@ -0,0 +1,12 @@
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 通知属性改变前接口
/// </summary>
public interface INotifyPropertyChangingX<TSender>
{
/// <summary>
/// 属性改变前事件
/// </summary>
public event PropertyChangingXEventHandler<TSender>? PropertyChangingX;
}

View File

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 可观察对象
/// <para>示例:<code><![CDATA[
/// public class ObservableClassExample : ObservableClass<ObservableClassExample>
/// {
/// int _value = 0;
/// public int Value
/// {
/// get => _value;
/// set => SetProperty(ref _value, value);
/// }
/// }]]></code></para>
/// </summary>
public abstract class ObservableClass<TObject>
: INotifyPropertyChanging,
INotifyPropertyChanged,
INotifyPropertyChangingX<TObject>,
INotifyPropertyChangedX<TObject>
where TObject : ObservableClass<TObject>
{
#region OnPropertyChange
/// <summary>
/// 设置属性值
/// </summary>
/// <param name="value">值</param>
/// <param name="newValue">新值</param>
/// <param name="propertyName">属性名称</param>
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool SetProperty<TValue>(
ref TValue value,
TValue newValue,
[CallerMemberName] string propertyName = null!
)
{
if (EqualityComparer<TValue>.Default.Equals(value, newValue) is true)
return false;
var oldValue = value;
if (OnPropertyChanging(oldValue, newValue, propertyName))
return false;
value = newValue;
OnPropertyChanged(oldValue, newValue, propertyName);
return true;
}
/// <summary>
/// 属性改变前
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <param name="propertyName">属性名称</param>
/// <returns>取消为 <see langword="true"/> 否则为 <see langword="false"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool OnPropertyChanging(
object? oldValue,
object? newValue,
[CallerMemberName] string propertyName = null!
)
{
PropertyChanging?.Invoke(this, new(propertyName));
if (PropertyChangingX is null)
return false;
var e = new PropertyChangingXEventArgs(propertyName, oldValue, newValue);
PropertyChangingX?.Invoke((TObject)this, e);
if (e.Cancel)
PropertyChanged?.Invoke(this, new(propertyName));
return e.Cancel;
}
/// <summary>
/// 属性改变后
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <param name="propertyName">属性名称</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual void OnPropertyChanged(
object? oldValue,
object? newValue,
[CallerMemberName] string propertyName = null!
)
{
PropertyChanged?.Invoke(this, new(propertyName));
PropertyChangedX?.Invoke((TObject)this, new(propertyName, oldValue, newValue));
}
#endregion
#region Event
/// <inheritdoc/>
public event PropertyChangingEventHandler? PropertyChanging;
/// <inheritdoc/>
public event PropertyChangedEventHandler? PropertyChanged;
/// <inheritdoc/>
public event PropertyChangingXEventHandler<TObject>? PropertyChangingX;
/// <inheritdoc/>
public event PropertyChangedXEventHandler<TObject>? PropertyChangedX;
#endregion
}

View File

@ -0,0 +1,33 @@
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 属性改变后事件参数
/// </summary>
public class PropertyChangedXEventArgs : EventArgs
{
/// <summary>
/// 属性名
/// </summary>
public string PropertyName { get; }
/// <summary>
/// 旧值
/// </summary>
public object? OldValue { get; }
/// <summary>
/// 新值
/// </summary>
public object? NewValue { get; }
/// <inheritdoc/>
/// <param name="propertyName">属性名</param>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public PropertyChangedXEventArgs(string propertyName, object? oldValue, object? newValue)
{
PropertyName = propertyName;
OldValue = oldValue;
NewValue = newValue;
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 属性改变后事件
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">参数</param>
public delegate void PropertyChangedXEventHandler<TSender>(
TSender sender,
PropertyChangedXEventArgs e
);

View File

@ -0,0 +1,35 @@
using System.ComponentModel;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 属性改变前事件参数
/// </summary>
public class PropertyChangingXEventArgs : CancelEventArgs
{
/// <summary>
/// 属性名
/// </summary>
public string PropertyName { get; }
/// <summary>
/// 旧值
/// </summary>
public object? OldValue { get; }
/// <summary>
/// 新值
/// </summary>
public object? NewValue { get; }
/// <inheritdoc/>
/// <param name="propertyName">属性名</param>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public PropertyChangingXEventArgs(string propertyName, object? oldValue, object? newValue)
{
PropertyName = propertyName;
OldValue = oldValue;
NewValue = newValue;
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 属性改变前事件
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">参数</param>
public delegate void PropertyChangingXEventHandler<TSender>(
TSender sender,
PropertyChangingXEventArgs e
);

View File

@ -7,10 +7,10 @@ namespace HKW.HKWUtils.Observable;
/// <summary> /// <summary>
/// 异步执行命令事件 /// 异步执行命令事件
/// </summary> /// </summary>
public delegate Task AsyncExecuteEventHandler(); public delegate Task ExecuteAsyncEventHandler();
/// <summary> /// <summary>
/// 异步执行命令事件 /// 异步执行命令事件
/// </summary> /// </summary>
/// <param name="parameter">值</param> /// <param name="parameter">值</param>
public delegate Task AsyncExecuteEventHandler<T>(T parameter); public delegate Task ExecuteAsyncEventHandler<T>(T parameter);

View File

@ -10,41 +10,43 @@ namespace HKW.HKWUtils.Observable;
/// <summary> /// <summary>
/// 可观察命令 /// 可观察命令
/// </summary> /// </summary>
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {CanExecuteProperty.Value}\\}")] [DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
public class ObservableCommand : ICommand public class ObservableCommand : ObservableClass<ObservableCommand>, ICommand
{ {
bool _isCanExecute = true;
/// <summary> /// <summary>
/// 能执行的属性 /// 能执行的属性
/// </summary> /// </summary>
public ObservableValue<bool> CanExecuteProperty { get; } = new(true); public bool IsCanExecute
{
get => _isCanExecute;
set => SetProperty(ref _isCanExecute, value);
}
bool _currentCanExecute = true;
/// <summary> /// <summary>
/// 当前可执行状态 /// 当前可执行状态
/// <para>
/// 在执行异步事件时会强制为 <see langword="false"/>, 但异步结束后会恢复为 <see cref="IsCanExecute"/> 的值
/// </para>
/// </summary> /// </summary>
public ObservableValue<bool> CurrentCanExecute { get; } = new(true); public bool CurrentCanExecute
{
get => _currentCanExecute;
private set => SetProperty(ref _currentCanExecute, value);
}
/// <inheritdoc/> /// <inheritdoc/>
public ObservableCommand() public ObservableCommand()
{ {
CanExecuteProperty.PropertyChanged += InvokeCanExecuteChanged; PropertyChanged += OnCanExecuteChanged;
CurrentCanExecute.PropertyChanged += InvokeCanExecuteChanged;
CurrentCanExecute.ValueChanging += CurrentCanExecute_ValueChanging;
} }
private void CurrentCanExecute_ValueChanging( private void OnCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
ObservableValue<bool> sender,
ValueChangingEventArgs<bool> e
)
{ {
if (e.NewValue is true && CanExecuteProperty.Value is false) CanExecuteChanged?.Invoke(this, new());
e.Cancel = true;
else
e.Cancel = false;
}
private void InvokeCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
{
CanExecuteChanged?.Invoke(sender, e);
} }
#region ICommand #region ICommand
@ -55,7 +57,7 @@ public class ObservableCommand : ICommand
/// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns> /// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public bool CanExecute(object? parameter) public bool CanExecute(object? parameter)
{ {
return CurrentCanExecute.Value && CanExecuteProperty.Value; return CurrentCanExecute && IsCanExecute;
} }
/// <summary> /// <summary>
@ -64,71 +66,36 @@ public class ObservableCommand : ICommand
/// <param name="parameter">参数</param> /// <param name="parameter">参数</param>
public async void Execute(object? parameter) public async void Execute(object? parameter)
{ {
if (IsCanExecute is not true)
return;
ExecuteCommand?.Invoke(); ExecuteCommand?.Invoke();
await ExecuteAsync(); await ExecuteAsync();
} }
/// <summary> /// <summary>
/// 执行异步方法, 会在等待中关闭按钮的可执行性, 完成后恢复 /// 执行异步方法, 会在等待中修改 <see cref="CurrentCanExecute"/>, 完成后恢复
/// <para>
/// 若要在执行此方法时触发 <see cref="ExecuteCommand"/> 事件, 请将 <paramref name="runAlone"/> 设置为 <see langword="true"/>
/// </para>
/// </summary> /// </summary>
/// <returns>等待</returns> /// <param name="runAlone">设置为 <see langword="true"/> 时触发 <see cref="ExecuteCommand"/> 事件</param>
private async Task ExecuteAsync() /// <returns>任务</returns>
public async Task ExecuteAsync(bool runAlone = false)
{ {
if (AsyncExecuteCommand is null) if (IsCanExecute is not true)
return; return;
CurrentCanExecute.Value = false; if (runAlone)
ExecuteCommand?.Invoke();
if (ExecuteAsyncCommand is null)
return;
CurrentCanExecute = false;
foreach ( foreach (
var asyncEvent in AsyncExecuteCommand var asyncEvent in ExecuteAsyncCommand
.GetInvocationList() .GetInvocationList()
.Cast<AsyncExecuteEventHandler>() .Cast<ExecuteAsyncEventHandler>()
) )
await asyncEvent.Invoke(); await asyncEvent.Invoke();
CurrentCanExecute.Value = true; CurrentCanExecute = true;
}
#endregion
#region NotifyReceiver
/// <summary>
/// 添加通知属性改变后接收器
/// <para>
/// 添加的接口触发后会执行 <see cref="NotifyCanExecuteReceived"/>
/// </para>
/// <para>示例:
/// <code><![CDATA[
/// ObservableValue<string> value = new();
/// ObservableCommand command = new();
/// command.AddNotifyReceiver(value);
/// command.NotifyCanExecuteReceived += (ref bool canExecute) =>
/// {
/// canExecute = false; // trigger this
/// };
/// value.EnumValue = "A"; // execute this
/// // result: value.EnumValue == "A" , command.CanExecuteProperty == false
/// ]]>
/// </code></para>
/// </summary>
/// <param name="notifies">通知属性改变后接口</param>
public void AddNotifyReceiver(params INotifyPropertyChanged[] notifies)
{
foreach (var notify in notifies)
notify.PropertyChanged += Notify_PropertyChanged;
}
/// <summary>
/// 删除通知属性改变后接收器
/// </summary>
/// <param name="notifies">通知属性改变后接口</param>
public void RemoveNotifyReceiver(params INotifyPropertyChanged[] notifies)
{
foreach (var notify in notifies)
notify.PropertyChanged -= Notify_PropertyChanged;
}
private void Notify_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
var args = new CancelEventArgs();
NotifyCanExecuteReceived?.Invoke(this, args);
CanExecuteProperty.Value = args.Cancel;
} }
#endregion #endregion
@ -146,11 +113,6 @@ public class ObservableCommand : ICommand
/// <summary> /// <summary>
/// 异步执行事件 /// 异步执行事件
/// </summary> /// </summary>
public event AsyncExecuteEventHandler? AsyncExecuteCommand; public event ExecuteAsyncEventHandler? ExecuteAsyncCommand;
/// <summary>
/// 可执行通知接收器事件
/// </summary>
public event NotifyReceivedEventHandler? NotifyCanExecuteReceived;
#endregion #endregion
} }

View File

@ -8,110 +8,112 @@ using System.Windows.Input;
namespace HKW.HKWUtils.Observable; namespace HKW.HKWUtils.Observable;
/// <summary> /// <summary>
/// 参数的可观察命令 /// 具有参数的可观察命令
/// </summary> /// </summary>
/// <typeparam name="T">参数类型</typeparam> [DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {CanExecuteProperty.Value}\\}")] public class ObservableCommand<T> : ObservableClass<ObservableCommand>, ICommand
public class ObservableCommand<T> : ICommand
where T : notnull
{ {
/// <inheritdoc cref="ObservableCommand.CanExecuteProperty"/> bool _isCanExecute = true;
public ObservableValue<bool> CanExecuteProperty { get; } = new(true);
/// <summary>
/// 能执行的属性
/// </summary>
public bool IsCanExecute
{
get => _isCanExecute;
set => SetProperty(ref _isCanExecute, value);
}
bool _currentCanExecute = true;
/// <summary> /// <summary>
/// 当前可执行状态 /// 当前可执行状态
/// <para>
/// 在执行异步事件时会强制为 <see langword="false"/>, 但异步结束后会恢复为 <see cref="IsCanExecute"/> 的值
/// </para>
/// </summary> /// </summary>
public ObservableValue<bool> CurrentCanExecute { get; } = new(true); public bool CurrentCanExecute
{
get => _currentCanExecute;
private set => SetProperty(ref _currentCanExecute, value);
}
/// <inheritdoc/> /// <inheritdoc/>
public ObservableCommand() public ObservableCommand()
{ {
CanExecuteProperty.PropertyChanged += InvokeCanExecuteChanged; PropertyChanged += OnCanExecuteChanged;
CurrentCanExecute.PropertyChanged += InvokeCanExecuteChanged;
CurrentCanExecute.ValueChanging += CurrentCanExecute_ValueChanging;
} }
private void CurrentCanExecute_ValueChanging( private void OnCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
ObservableValue<bool> sender,
ValueChangingEventArgs<bool> e
)
{ {
if (e.NewValue is true && CanExecuteProperty.Value is false) CanExecuteChanged?.Invoke(this, new());
e.Cancel = true;
else
e.Cancel = false;
}
private void InvokeCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
{
CanExecuteChanged?.Invoke(sender, e);
} }
#region ICommand #region ICommand
/// <inheritdoc cref="ObservableCommand.CanExecute(object?)"/> /// <summary>
/// 能否被执行
/// </summary>
/// <param name="parameter">参数</param>
/// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public bool CanExecute(object? parameter) public bool CanExecute(object? parameter)
{ {
return CurrentCanExecute.Value && CanExecuteProperty.Value; return CurrentCanExecute && IsCanExecute;
} }
/// <inheritdoc cref="ObservableCommand.Execute(object?)"/> /// <summary>
/// 执行方法
/// </summary>
/// <param name="parameter">参数</param>
public async void Execute(object? parameter) public async void Execute(object? parameter)
{ {
if (IsCanExecute is not true)
return;
ExecuteCommand?.Invoke((T)parameter!); ExecuteCommand?.Invoke((T)parameter!);
await ExecuteAsync((T)parameter!); await ExecuteAsync((T)parameter!);
} }
/// <inheritdoc cref="ObservableCommand.ExecuteAsync"/> /// <summary>
/// 执行异步方法, 会在等待中修改 <see cref="CurrentCanExecute"/>, 完成后恢复
/// <para>
/// 若要在执行此方法时触发 <see cref="ExecuteCommand"/> 事件, 请将 <paramref name="runAlone"/> 设置为 <see langword="true"/>
/// </para>
/// </summary>
/// <param name="parameter">参数</param> /// <param name="parameter">参数</param>
private async Task ExecuteAsync(T parameter) /// <param name="runAlone">设置为 <see langword="true"/> 时触发 <see cref="ExecuteCommand"/> 事件</param>
/// <returns>任务</returns>
public async Task ExecuteAsync(T parameter, bool runAlone = false)
{ {
if (AsyncExecuteCommand is null) if (IsCanExecute is not true)
return; return;
CurrentCanExecute.Value = false; if (runAlone)
ExecuteCommand?.Invoke(parameter);
if (ExecuteAsyncCommand is null)
return;
CurrentCanExecute = false;
foreach ( foreach (
var asyncEvent in AsyncExecuteCommand var asyncEvent in ExecuteAsyncCommand
.GetInvocationList() .GetInvocationList()
.Cast<AsyncExecuteEventHandler<T>>() .Cast<ExecuteAsyncEventHandler<T>>()
) )
await asyncEvent.Invoke(parameter); await asyncEvent.Invoke(parameter);
CurrentCanExecute.Value = true; CurrentCanExecute = true;
}
#endregion
#region NotifyReceiver
/// <inheritdoc cref="ObservableCommand.AddNotifyReceiver(INotifyPropertyChanged[])"/>
public void AddNotifyReceiver(params INotifyPropertyChanged[] notifies)
{
foreach (var notify in notifies)
notify.PropertyChanged += Notify_PropertyChanged;
}
/// <inheritdoc cref="ObservableCommand.RemoveNotifyReceiver(INotifyPropertyChanged[])"/>
public void RemoveNotifyReceiver(params INotifyPropertyChanged[] notifies)
{
foreach (var notify in notifies)
notify.PropertyChanged -= Notify_PropertyChanged;
}
private void Notify_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
var args = new CancelEventArgs();
NotifyCanExecuteReceived?.Invoke(this, args);
CanExecuteProperty.Value = args.Cancel;
} }
#endregion #endregion
#region Event #region Event
/// <inheritdoc cref="ObservableCommand.CanExecuteChanged"/> /// <summary>
/// 能否执行属性改变后事件
/// </summary>
public event EventHandler? CanExecuteChanged; public event EventHandler? CanExecuteChanged;
/// <inheritdoc cref="ObservableCommand.ExecuteCommand"/> /// <summary>
/// 执行事件
/// </summary>
public event ExecuteEventHandler<T>? ExecuteCommand; public event ExecuteEventHandler<T>? ExecuteCommand;
/// <inheritdoc cref="ObservableCommand.AsyncExecuteCommand"/> /// <summary>
public event AsyncExecuteEventHandler<T>? AsyncExecuteCommand; /// 异步执行事件
/// </summary>
/// <inheritdoc cref="ObservableCommand.NotifyCanExecuteReceived"/> public event ExecuteAsyncEventHandler<T>? ExecuteAsyncCommand;
public event NotifyReceivedEventHandler? NotifyCanExecuteReceived;
#endregion #endregion
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace HKW.HKWUtils.Observable; namespace HKW.HKWUtils.Observable;
@ -169,55 +170,36 @@ public class ObservableValue<T>
} }
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals(object? obj) public override int GetHashCode()
{ {
return Equals(obj as ObservableValue<T>); return Value?.GetHashCode() ?? 0;
} }
/// <inheritdoc/> /// <inheritdoc/>
public override int GetHashCode() public override bool Equals(object? obj)
{ {
return Guid.GetHashCode(); return obj is ObservableValue<T> value
&& EqualityComparer<T>.Default.Equals(Value, value.Value);
} }
/// <inheritdoc/> /// <inheritdoc/>
public bool Equals(ObservableValue<T>? other) public bool Equals(ObservableValue<T>? other)
{ {
return Guid.Equals(other?.Guid) is true; return other is ObservableValue<T> value
&& EqualityComparer<T>.Default.Equals(Value, value.Value);
} }
/// <summary> /// <inheritdoc/>
/// 值相等 public static bool operator ==(ObservableValue<T> a, ObservableValue<T> b)
/// </summary>
/// <param name="other">其它可观察值</param>
/// <returns>相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public bool ValueEquals(ObservableValue<T> other)
{ {
return Value?.Equals(other.Value) is true; return EqualityComparer<T>.Default.Equals(a.Value, b.Value);
} }
/// <summary> /// <inheritdoc/>
/// 判断 <see cref="Value"/> 相等 public static bool operator !=(ObservableValue<T> a, ObservableValue<T> b)
/// </summary>
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator ==(ObservableValue<T> value1, ObservableValue<T> value2)
{ {
return value1.Value?.Equals(value2.Value) is true; return (a == b) is not true;
} }
/// <summary>
/// 判断 <see cref="Value"/> 不相等
/// </summary>
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>不相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator !=(ObservableValue<T> value1, ObservableValue<T> value2)
{
return value1.Value?.Equals(value2.Value) is not true;
}
#endregion #endregion
#region Event #region Event

9
VPet.ModMaker/Usings.cs Normal file
View File

@ -0,0 +1,9 @@
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks;
global using global::HKW.HKWUtils;
global using global::HKW.HKWUtils.Observable;

View File

@ -12,10 +12,9 @@ using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core; using VPet_Simulator.Core;
namespace HKW.Models; namespace HKW.HKWUtils;
/// <summary> /// <summary>
/// 拓展 /// 拓展
@ -45,10 +44,9 @@ public static class Extensions
/// <param name="source">图像资源</param> /// <param name="source">图像资源</param>
public static void CloseStream(this ImageSource source) public static void CloseStream(this ImageSource source)
{ {
if (source is BitmapImage image) if (source is not BitmapImage image)
{ return;
image.StreamSource?.Close(); image.StreamSource?.Close();
}
} }
/// <summary> /// <summary>
@ -140,16 +138,6 @@ public static class Extensions
return true; return true;
} }
/// <summary>
/// 是含有名称的动画
/// </summary>
/// <param name="graphType"></param>
/// <returns></returns>
public static bool IsHasNameAnime(this GraphInfo.GraphType graphType)
{
return AnimeTypeModel.HasNameAnimes.Contains(graphType);
}
/// <summary> /// <summary>
/// 流内容对比 /// 流内容对比
/// </summary> /// </summary>

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWUtils;
/// <summary>
/// 哈希值
/// </summary>
public class HashCode
{
/// <summary>
/// 默认种子
/// </summary>
public const int DefaultSeed = 114514;
/// <summary>
/// 默认系数
/// </summary>
public const int DefaultFactor = 1919810;
/// <summary>
/// 组合哈希值
/// </summary>
/// <param name="values">值</param>
/// <returns>组合的哈希值</returns>
public static int Combine(params object[] values)
{
return CustomHash(DefaultSeed, DefaultFactor, values.Select(v => v.GetHashCode()));
}
/// <summary>
/// 组合哈希值
/// </summary>
/// <param name="seed">种子</param>
/// <param name="factor">系数</param>
/// <param name="values">值</param>
/// <returns>组合的哈希值</returns>
public static int Combine(int seed, int factor, params object[] values)
{
return CustomHash(seed, factor, values.Select(v => v.GetHashCode()));
}
/// <summary>
/// 自定义组合哈希
/// </summary>
/// <param name="seed">种子</param>
/// <param name="factor">系数</param>
/// <param name="collection">哈希集合</param>
/// <returns>组合的哈希</returns>
public static int CustomHash(int seed, int factor, IEnumerable<int> collection)
{
int hash = seed;
foreach (int i in collection)
hash = unchecked((hash * factor) + i);
return hash;
}
/// <summary>
/// 自定义组合哈希
/// </summary>
/// <param name="seed">种子</param>
/// <param name="factor">系数</param>
/// <param name="values">哈希集合</param>
/// <returns>组合的哈希</returns>
public static int CustomHash(int seed, int factor, params int[] values)
{
return CustomHash(seed, factor, collection: values);
}
}

View File

@ -0,0 +1,81 @@
using HKW.HKWUtils.Observable;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace HKW.HKWUtils;
/// <summary>
/// 可观察的枚举标签模型
/// </summary>
/// <typeparam name="T">枚举类型</typeparam>
public class ObservableEnumFlags<T> : ObservableClass<ObservableEnumFlags<T>>
where T : Enum
{
private T _EnumValue;
public T EnumValue
{
get => _EnumValue;
set => SetProperty(ref _EnumValue, value);
}
/// <summary>
/// 添加枚举命令
/// </summary>
public ObservableCommand<T> AddCommand { get; } = new();
/// <summary>
/// 删除枚举命令
/// </summary>
public ObservableCommand<T> RemoveCommand { get; } = new();
/// <summary>
/// 枚举类型
/// </summary>
public Type EnumType = typeof(T);
/// <summary>
/// 枚举基类
/// </summary>
public Type UnderlyingType { get; } = Enum.GetUnderlyingType(typeof(T));
public ObservableEnumFlags()
{
if (Attribute.IsDefined(EnumType, typeof(FlagsAttribute)) is false)
throw new Exception($"此枚举类型未使用特性 [{nameof(FlagsAttribute)}]");
AddCommand.ExecuteCommand += AddCommand_Execute;
RemoveCommand.ExecuteCommand += RemoveCommand_Execute;
}
public ObservableEnumFlags(T value)
: this()
{
EnumValue = value;
}
private void AddCommand_Execute(T v)
{
if (UnderlyingType == typeof(int))
{
EnumValue = (T)
Enum.Parse(EnumType, (Convert.ToInt32(EnumValue) | Convert.ToInt32(v)).ToString());
}
else
throw new NotImplementedException($"Value type: {UnderlyingType}");
}
private void RemoveCommand_Execute(T v)
{
if (UnderlyingType == typeof(int))
{
EnumValue = (T)
Enum.Parse(EnumType, (Convert.ToInt32(EnumValue) & ~Convert.ToInt32(v)).ToString());
}
else
throw new NotImplementedException($"Value type: {UnderlyingType}");
}
}

View File

@ -0,0 +1,79 @@
using HKW.HKWUtils.Observable;
namespace HKW.HKWUtils;
/// <summary>
/// 可观察地点
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class ObservablePoint<T>
: ObservableClass<ObservablePoint<T>>,
IEquatable<ObservablePoint<T>>
{
private T _x;
public T X
{
get => _x;
set => SetProperty(ref _x, value);
}
private T _y;
public T Y
{
get => _y;
set => SetProperty(ref _y, value);
}
public ObservablePoint() { }
public ObservablePoint(T x, T y)
{
X = x;
Y = y;
}
/// <summary>
/// 复制一个新的对象
/// </summary>
/// <returns>新对象</returns>
public ObservablePoint<T> Copy()
{
return new(X, Y);
}
#region Other
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(X, Y);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservablePoint<T> temp
&& EqualityComparer<T>.Default.Equals(X, temp.X)
&& EqualityComparer<T>.Default.Equals(Y, temp.Y);
}
/// <inheritdoc/>
public bool Equals(ObservablePoint<T>? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservablePoint<T> a, ObservablePoint<T> b)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservablePoint<T> a, ObservablePoint<T> b)
{
return Equals(a, b) is not true;
}
#endregion
}

View File

@ -0,0 +1,82 @@
using HKW.HKWUtils;
using HKW.HKWUtils.Observable;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace HKW.HKWUtils;
/// <summary>
/// 可观察的范围
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class ObservableRange<T>
: ObservableClass<ObservableRange<T>>,
IEquatable<ObservableRange<T>>
{
private T _min;
public T Min
{
get => _min;
set => SetProperty(ref _min, value);
}
private T _max;
public T Max
{
get => _max;
set => SetProperty(ref _max, value);
}
public ObservableRange() { }
public ObservableRange(T min, T max)
{
_min = min;
_max = max;
}
/// <summary>
/// 复制一个新的对象
/// </summary>
/// <returns>新对象</returns>
public ObservableRange<T> Copy()
{
return new(Min, Max);
}
#region Other
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(Min, Max);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableRange<T> temp
&& EqualityComparer<T>.Default.Equals(Min, temp.Min)
&& EqualityComparer<T>.Default.Equals(Max, temp.Max);
}
/// <inheritdoc/>
public bool Equals(ObservableRange<T>? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservableRange<T> a, ObservableRange<T> b)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableRange<T> a, ObservableRange<T> b)
{
return Equals(a, b) is not true;
}
#endregion
}

View File

@ -0,0 +1,91 @@
using HKW.HKWUtils.Observable;
namespace HKW.HKWUtils;
public class ObservableRect<T> : ObservableClass<ObservableRect<T>>, IEquatable<ObservableRect<T>>
{
private T _x;
public T X
{
get => _x;
set => SetProperty(ref _x, value);
}
private T _y;
public T Y
{
get => _y;
set => SetProperty(ref _y, value);
}
private T _width;
public T Width
{
get => _width;
set => SetProperty(ref _width, value);
}
private T _heigth;
public T Height
{
get => _heigth;
set => SetProperty(ref _heigth, value);
}
public ObservableRect() { }
public ObservableRect(T x, T y, T width, T hetght)
{
X = x;
Y = y;
Width = width;
Height = hetght;
}
/// <summary>
/// 复制一个新的对象
/// </summary>
/// <returns>新对象</returns>
public ObservableRect<T> Copy()
{
return new(X, Y, Width, Height);
}
#region Other
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(X, Y, Width, Height);
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableRect<T> temp
&& EqualityComparer<T>.Default.Equals(X, temp.X)
&& EqualityComparer<T>.Default.Equals(Y, temp.Y)
&& EqualityComparer<T>.Default.Equals(Width, temp.Width)
&& EqualityComparer<T>.Default.Equals(Height, temp.Height);
}
/// <inheritdoc/>
public bool Equals(ObservableRect<T>? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservableRect<T> a, ObservableRect<T> b)
{
return Equals(a, b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableRect<T> a, ObservableRect<T> b)
{
return Equals(a, b) is not true;
}
#endregion
}

View File

@ -5,9 +5,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using VPet.ModMaker;
namespace HKW.Models; namespace HKW.HKWUtils;
/// <summary> /// <summary>
/// 工具 /// 工具

View File

@ -98,6 +98,7 @@
<Compile Include="App.xaml.cs"> <Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Usings.cs" />
<Compile Include="Converters\BrushToMediaColorConverter.cs" /> <Compile Include="Converters\BrushToMediaColorConverter.cs" />
<Compile Include="Converters\CalculatorConverter.cs" /> <Compile Include="Converters\CalculatorConverter.cs" />
<Compile Include="Converters\EqualsConverter.cs" /> <Compile Include="Converters\EqualsConverter.cs" />
@ -110,12 +111,37 @@
<Compile Include="Converters\RatioMarginConverter.cs" /> <Compile Include="Converters\RatioMarginConverter.cs" />
<Compile Include="Converters\MaxConverter.cs" /> <Compile Include="Converters\MaxConverter.cs" />
<Compile Include="Converters\MarginConverter.cs" /> <Compile Include="Converters\MarginConverter.cs" />
<Compile Include="SimpleObservable\ObservableClass\INotifyPropertyChangedX.cs" />
<Compile Include="SimpleObservable\ObservableClass\INotifyPropertyChangingX.cs" />
<Compile Include="SimpleObservable\ObservableClass\ObservableClass.cs" />
<Compile Include="SimpleObservable\ObservableClass\PropertyChangedXEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableClass\PropertyChangedXEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableClass\PropertyChangingXEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableClass\PropertyChangingXEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ExecuteAsyncEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ExecuteEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\NotifyReceivedEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommand.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommandT.cs" />
<Compile Include="SimpleObservable\ObservableValue\NotifySenderPropertyChangedHandler.cs" />
<Compile Include="SimpleObservable\ObservableValue\ObservableValue.cs" />
<Compile Include="SimpleObservable\ObservableValue\ObservableValueGroup.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangedEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangedEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangingEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangingEventHandler.cs" />
<Compile Include="Utils\ObservableEnumFlags.cs" />
<Compile Include="Utils\Expansions.cs" />
<Compile Include="Utils\HashCode.cs" />
<Compile Include="Utils\ObservableRange.cs" />
<Compile Include="Utils\ObservablePoint.cs" />
<Compile Include="Utils\ObservableRect.cs" />
<Compile Include="Utils\Utils.cs" />
<Compile Include="Models\EnumFlagsVM.cs" /> <Compile Include="Models\EnumFlagsVM.cs" />
<Compile Include="Models\I18nData.cs" /> <Compile Include="Models\I18nData.cs" />
<Compile Include="Models\ModModel\AnimeModel.cs" /> <Compile Include="Models\ModModel\AnimeModel.cs" />
<Compile Include="Models\ModModel\AnimeTypeModel.cs" /> <Compile Include="Models\ModModel\AnimeTypeModel.cs" />
<Compile Include="Models\ModModel\ClickTextModel.cs" /> <Compile Include="Models\ModModel\ClickTextModel.cs" />
<Compile Include="Models\Expansions.cs" />
<Compile Include="Models\ModModel\FoodAnimeModel.cs" /> <Compile Include="Models\ModModel\FoodAnimeModel.cs" />
<Compile Include="Models\ModModel\FoodAnimeTypeModel.cs" /> <Compile Include="Models\ModModel\FoodAnimeTypeModel.cs" />
<Compile Include="Models\ModModel\FoodLocationModel.cs" /> <Compile Include="Models\ModModel\FoodLocationModel.cs" />
@ -136,18 +162,6 @@
<Compile Include="Models\ModModel\WorkModel.cs" /> <Compile Include="Models\ModModel\WorkModel.cs" />
<Compile Include="Resources\NativeResources.cs" /> <Compile Include="Resources\NativeResources.cs" />
<Compile Include="NativeStyles.cs" /> <Compile Include="NativeStyles.cs" />
<Compile Include="SimpleObservable\ObservableCommand\AsyncExecuteEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ExecuteEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\NotifyReceivedEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommand.cs" />
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommandT.cs" />
<Compile Include="SimpleObservable\ObservableValue\NotifySenderPropertyChangedHandler.cs" />
<Compile Include="SimpleObservable\ObservableValue\ObservableValue.cs" />
<Compile Include="SimpleObservable\ObservableValue\ObservableValueGroup.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangedEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangedEventHandler.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangingEventArgs.cs" />
<Compile Include="SimpleObservable\ObservableValue\ValueChangingEventHandler.cs" />
<Compile Include="ViewModels\ModEdit\AddCultureWindowVM.cs" /> <Compile Include="ViewModels\ModEdit\AddCultureWindowVM.cs" />
<Compile Include="ViewModels\ModEdit\AnimeEdit\FoodAnimeEditWindowVM.cs" /> <Compile Include="ViewModels\ModEdit\AnimeEdit\FoodAnimeEditWindowVM.cs" />
<Compile Include="ViewModels\ModEdit\AnimeEdit\AnimeEditWindowVM.cs" /> <Compile Include="ViewModels\ModEdit\AnimeEdit\AnimeEditWindowVM.cs" />
@ -217,7 +231,6 @@
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<Compile Include="Models\Utils.cs" />
<Compile Include="Views\ModEdit\FoodEdit\FoodEditWindow.xaml.cs"> <Compile Include="Views\ModEdit\FoodEdit\FoodEditWindow.xaml.cs">
<DependentUpon>FoodEditWindow.xaml</DependentUpon> <DependentUpon>FoodEditWindow.xaml</DependentUpon>
</Compile> </Compile>

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
@ -123,7 +123,7 @@ public class AnimeEditWindowVM
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged; CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.AsyncExecuteCommand += PlayCommand_AsyncExecuteEvent; PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent; StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteEvent; AddAnimeCommand.ExecuteCommand += AddAnimeCommand_ExecuteEvent;
RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteEvent; RemoveAnimeCommand.ExecuteCommand += RemoveAnimeCommand_ExecuteEvent;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Panuon.WPF.UI; using Panuon.WPF.UI;
using System; using System;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
@ -24,7 +24,6 @@ public class FoodAnimeEditWindowVM
/// </summary> /// </summary>
public PetModel CurrentPet { get; set; } public PetModel CurrentPet { get; set; }
// TODO: 使用内部资源
/// <summary> /// <summary>
/// 默认食物图片 /// 默认食物图片
/// </summary> /// </summary>
@ -211,7 +210,7 @@ public class FoodAnimeEditWindowVM
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged; CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.AsyncExecuteCommand += PlayCommand_AsyncExecuteEvent; PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent; StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
ReplaceFoodImageCommand.ExecuteCommand += ChangeFoodImageCommand_ExecuteEvent; ReplaceFoodImageCommand.ExecuteCommand += ChangeFoodImageCommand_ExecuteEvent;
ResetFoodImageCommand.ExecuteCommand += ResetFoodImageCommand_ExecuteEvent; ResetFoodImageCommand.ExecuteCommand += ResetFoodImageCommand_ExecuteEvent;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -296,7 +296,7 @@ public class I18nEditWindowVM
{ {
foreach (var pet in model.Pets) foreach (var pet in model.Pets)
{ {
if (pet.IsSimplePetModel) if (pet.FromMain.Value)
continue; continue;
AddData(pet.Id, pet, (m) => m.Name); AddData(pet.Id, pet, (m) => m.Name);
AddData(pet.PetNameId, pet, (m) => m.PetName); AddData(pet.PetNameId, pet, (m) => m.PetName);

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -18,7 +18,6 @@ using Panuon.WPF.UI;
using VPet.ModMaker.Views.ModEdit.I18nEdit; using VPet.ModMaker.Views.ModEdit.I18nEdit;
using System.Globalization; using System.Globalization;
using Ookii.Dialogs.Wpf; using Ookii.Dialogs.Wpf;
using HKW.Models;
namespace VPet.ModMaker.ViewModels.ModEdit; namespace VPet.ModMaker.ViewModels.ModEdit;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -66,11 +66,12 @@ public class PetPageVM
public void Edit(PetModel model) public void Edit(PetModel model)
{ {
if (model.IsSimplePetModel) if (
{ model.FromMain.Value
MessageBox.Show("这是本体自带的宠物, 无法编辑".Translate()); && MessageBox.Show("这是本体自带的宠物, 确定要编辑吗".Translate(), "", MessageBoxButton.YesNo)
is not MessageBoxResult.Yes
)
return; return;
}
var window = new PetEditWindow(); var window = new PetEditWindow();
var vm = window.ViewModel; var vm = window.ViewModel;
vm.OldPet = model; vm.OldPet = model;
@ -86,7 +87,7 @@ public class PetPageVM
private void Remove(PetModel model) private void Remove(PetModel model)
{ {
if (model.IsSimplePetModel) if (model.FromMain.Value)
{ {
MessageBox.Show("这是本体自带的宠物, 无法删除".Translate()); MessageBox.Show("这是本体自带的宠物, 无法删除".Translate());
return; return;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,4 @@
using HKW.Models; using LinePutScript.Localization.WPF;
using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -39,7 +39,6 @@
x:Name="ComboBox_Pet" x:Name="ComboBox_Pet"
Grid.Column="1" Grid.Column="1"
pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}" pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}"
DisplayMemberPath="Id.Value"
ItemsSource="{Binding Pets}" ItemsSource="{Binding Pets}"
SelectedItem="{Binding CurrentPet.Value}" SelectedItem="{Binding CurrentPet.Value}"
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
@ -48,6 +47,14 @@
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" /> <Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" />
</Style> </Style>
</ComboBox.ItemContainerStyle> </ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id.Value}" />
<TextBlock IsEnabled="{Binding FromMain, Converter={StaticResource FalseToCollapsedConverter}}" Text="{ll:Str {} (来自本体)}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox> </ComboBox>
</Grid> </Grid>
<Grid Grid.Row="1"> <Grid Grid.Row="1">

View File

@ -348,7 +348,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Value="{Binding Rect.Width.Value}" /> Value="{Binding Rect.Width}" />
<Grid Grid.Row="4" Grid.ColumnSpan="2"> <Grid Grid.Row="4" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition /> <ColumnDefinition />
@ -360,7 +360,7 @@
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="X:" /> <Label Content="X:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Rect.X.Value}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Rect.X}" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -368,7 +368,7 @@
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="Y:" /> <Label Content="Y:" />
<pu:NumberInput Grid.Column="1" Value="{Binding Rect.Y.Value}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Rect.Y}" />
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
@ -380,7 +380,6 @@
</Expander> </Expander>
</DataTemplate> </DataTemplate>
</ResourceDictionary> </ResourceDictionary>
</Window.Resources> </Window.Resources>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -433,7 +432,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="CurrentFoodLocationModel.Value.Rect.Width.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -442,8 +441,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.X.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.Y.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -481,7 +480,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="CurrentFoodLocationModel.Value.Rect.Width.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.Width" />
<Binding Source="1" /> <Binding Source="1" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -490,8 +489,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Source="1" /> <Binding Source="1" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.X.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.Y.Value" /> <Binding Path="CurrentFoodLocationModel.Value.Rect.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>

View File

@ -1,5 +1,4 @@
using HKW.Models; using LinePutScript.Localization.WPF;
using LinePutScript.Localization.WPF;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,5 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using HKW.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;

View File

@ -39,7 +39,6 @@
x:Name="ComboBox_Pet" x:Name="ComboBox_Pet"
Grid.Column="1" Grid.Column="1"
pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}" pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}"
DisplayMemberPath="Id.Value"
ItemsSource="{Binding Pets}" ItemsSource="{Binding Pets}"
SelectedItem="{Binding CurrentPet.Value}" SelectedItem="{Binding CurrentPet.Value}"
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
@ -48,6 +47,14 @@
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" /> <Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" />
</Style> </Style>
</ComboBox.ItemContainerStyle> </ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id.Value}" />
<TextBlock IsEnabled="{Binding FromMain.Value, Converter={StaticResource FalseToCollapsedConverter}}" Text="{ll:Str {} (来自本体)}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox> </ComboBox>
</Grid> </Grid>
<Grid Grid.Row="1"> <Grid Grid.Row="1">

View File

@ -72,7 +72,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchHeadRect.Value.Width.Value" /> <Binding Path="Pet.Value.TouchHeadRect.Value.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -80,7 +80,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchHeadRect.Value.Height.Value" /> <Binding Path="Pet.Value.TouchHeadRect.Value.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -89,8 +89,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchHeadRect.Value.X.Value" /> <Binding Path="Pet.Value.TouchHeadRect.Value.X" />
<Binding Path="Pet.Value.TouchHeadRect.Value.Y.Value" /> <Binding Path="Pet.Value.TouchHeadRect.Value.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -103,7 +103,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchBodyRect.Value.Width.Value" /> <Binding Path="Pet.Value.TouchBodyRect.Value.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -111,7 +111,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchBodyRect.Value.Height.Value" /> <Binding Path="Pet.Value.TouchBodyRect.Value.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -120,8 +120,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchBodyRect.Value.X.Value" /> <Binding Path="Pet.Value.TouchBodyRect.Value.X" />
<Binding Path="Pet.Value.TouchBodyRect.Value.Y.Value" /> <Binding Path="Pet.Value.TouchBodyRect.Value.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -134,7 +134,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Value.Width.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -142,7 +142,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Value.Height.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -151,8 +151,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Value.X.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.X" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Value.Y.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Happy.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -165,7 +165,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Value.Width.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -173,7 +173,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Value.Height.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -182,8 +182,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Value.X.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.X" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Value.Y.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Nomal.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -196,7 +196,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.Width.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -204,7 +204,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.Height.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -213,8 +213,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.X.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.X" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.Y.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.PoorCondition.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -227,7 +227,7 @@
<Setter Property="Width"> <Setter Property="Width">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Value.Width.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Width" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -235,7 +235,7 @@
<Setter Property="Height"> <Setter Property="Height">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*"> <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Value.Height.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Height" />
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
@ -244,8 +244,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Value.X.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.X" />
<Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Value.Y.Value" /> <Binding Path="Pet.Value.TouchRaisedRect.Value.Ill.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -264,8 +264,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.RaisePoint.Value.Happy.Value.X.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Happy.X" />
<Binding Path="Pet.Value.RaisePoint.Value.Happy.Value.Y.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Happy.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -284,8 +284,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.RaisePoint.Value.Nomal.Value.X.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Nomal.X" />
<Binding Path="Pet.Value.RaisePoint.Value.Nomal.Value.Y.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Nomal.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -304,8 +304,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.RaisePoint.Value.PoorCondition.Value.X.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.PoorCondition.X" />
<Binding Path="Pet.Value.RaisePoint.Value.PoorCondition.Value.Y.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.PoorCondition.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -324,8 +324,8 @@
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}"> <MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" /> <Binding Path="LengthRatio.Value" />
<Binding Path="Pet.Value.RaisePoint.Value.Ill.Value.X.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Ill.X" />
<Binding Path="Pet.Value.RaisePoint.Value.Ill.Value.Y.Value" /> <Binding Path="Pet.Value.RaisePoint.Value.Ill.Y" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -414,12 +414,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.Value.TouchHeadRect.Value.X.Value}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchHeadRect.Value.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.Value.TouchHeadRect.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchHeadRect.Value.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -427,7 +427,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchHeadRect.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchHeadRect.Value.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -436,7 +436,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchHeadRect.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchHeadRect.Value.Height, Mode=TwoWay}" />
</Grid> </Grid>
</Grid> </Grid>
<Grid> <Grid>
@ -461,12 +461,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.Value.TouchBodyRect.Value.X.Value}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchBodyRect.Value.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.Value.TouchBodyRect.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchBodyRect.Value.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -474,7 +474,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchBodyRect.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchBodyRect.Value.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -483,7 +483,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchBodyRect.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchBodyRect.Value.Height, Mode=TwoWay}" />
</Grid> </Grid>
</Grid> </Grid>
<Expander Header="{ll:Str 提起范围}"> <Expander Header="{ll:Str 提起范围}">
@ -516,12 +516,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.Value.TouchRaisedRect.Value.Happy.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchRaisedRect.Value.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.Value.TouchRaisedRect.Value.Happy.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchRaisedRect.Value.Happy.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -529,7 +529,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Happy.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Happy.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -538,7 +538,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Happy.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Happy.Height, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_TouchRaisedRect_NomalState" x:Name="ToggleButton_TouchRaisedRect_NomalState"
@ -562,12 +562,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.Value.TouchRaisedRect.Value.Nomal.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchRaisedRect.Value.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.Value.TouchRaisedRect.Value.Nomal.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchRaisedRect.Value.Nomal.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -575,7 +575,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Nomal.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Nomal.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -584,7 +584,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Nomal.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Nomal.Height, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_TouchRaisedRect_PoorConditionState" x:Name="ToggleButton_TouchRaisedRect_PoorConditionState"
@ -608,12 +608,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.Value.TouchRaisedRect.Value.PoorCondition.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchRaisedRect.Value.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.Value.TouchRaisedRect.Value.PoorCondition.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchRaisedRect.Value.PoorCondition.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -621,7 +621,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.PoorCondition.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -630,7 +630,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchRaisedRect.Value.PoorCondition.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.PoorCondition.Height, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_TouchRaisedRect_IllState" x:Name="ToggleButton_TouchRaisedRect_IllState"
@ -654,12 +654,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.Value.TouchRaisedRect.Value.Ill.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.TouchRaisedRect.Value.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.Value.TouchRaisedRect.Value.Ill.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.TouchRaisedRect.Value.Ill.Y, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Background="{x:Null}" Background="{x:Null}"
@ -667,7 +667,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Ill.Value.Width.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Ill.Width, Mode=TwoWay}" />
<Label <Label
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"
@ -676,7 +676,7 @@
<pu:NumberInput <pu:NumberInput
Grid.Row="1" Grid.Row="1"
Grid.Column="3" Grid.Column="3"
Value="{Binding Pet.Value.TouchRaisedRect.Value.Ill.Value.Height.Value, Mode=TwoWay}" /> Value="{Binding Pet.Value.TouchRaisedRect.Value.Ill.Height, Mode=TwoWay}" />
</Grid> </Grid>
</Grid> </Grid>
</Expander> </Expander>
@ -709,12 +709,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.Value.RaisePoint.Value.Happy.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.RaisePoint.Value.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.Value.RaisePoint.Value.Happy.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.RaisePoint.Value.Happy.Y, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_RaisePoint_Nomal" x:Name="ToggleButton_RaisePoint_Nomal"
@ -737,12 +737,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.Value.RaisePoint.Value.Nomal.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.RaisePoint.Value.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.Value.RaisePoint.Value.Nomal.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.RaisePoint.Value.Nomal.Y, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_RaisePoint_PoorCondition" x:Name="ToggleButton_RaisePoint_PoorCondition"
@ -765,12 +765,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.Value.RaisePoint.Value.PoorCondition.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.RaisePoint.Value.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.Value.RaisePoint.Value.PoorCondition.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.RaisePoint.Value.PoorCondition.Y, Mode=TwoWay}" />
</Grid> </Grid>
<ToggleButton <ToggleButton
x:Name="ToggleButton_RaisePoint_Ill" x:Name="ToggleButton_RaisePoint_Ill"
@ -793,12 +793,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.Value.RaisePoint.Value.Ill.Value.X.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="1" Value="{Binding Pet.Value.RaisePoint.Value.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.Value.RaisePoint.Value.Ill.Value.Y.Value, Mode=TwoWay}" /> <pu:NumberInput Grid.Column="3" Value="{Binding Pet.Value.RaisePoint.Value.Ill.Y, Mode=TwoWay}" />
</Grid> </Grid>
</Grid> </Grid>
</Expander> </Expander>

View File

@ -43,7 +43,6 @@
Grid.Column="1" Grid.Column="1"
MinWidth="150" MinWidth="150"
pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}" pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}"
DisplayMemberPath="Id.Value"
ItemsSource="{Binding Pets}" ItemsSource="{Binding Pets}"
SelectedItem="{Binding CurrentPet.Value}" SelectedItem="{Binding CurrentPet.Value}"
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
@ -52,6 +51,14 @@
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" /> <Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" />
</Style> </Style>
</ComboBox.ItemContainerStyle> </ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id.Value}" />
<TextBlock IsEnabled="{Binding FromMain.Value, Converter={StaticResource FalseToCollapsedConverter}}" Text="{ll:Str {} (来自本体)}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox> </ComboBox>
</Grid> </Grid>
<Grid Grid.Row="1"> <Grid Grid.Row="1">