重构一部分

This commit is contained in:
Hakoyu 2024-03-25 22:43:01 +08:00
parent 293066e940
commit ce416a004c
121 changed files with 3736 additions and 4423 deletions

View File

@ -1,18 +1,17 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:VPet.ModMaker.Converters">
<c:MarginConverter x:Key="MarginConverter" />
<c:RatioMarginConverter x:Key="RatioMarginConverter" />
<c:CalculatorConverter x:Key="CalculatorConverter" />
<c:StringFormatConverter x:Key="StringFormatConverter" />
<c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" />
<c:MaxConverter x:Key="MaxConverter" />
<c:FalseToHiddenConverter x:Key="FalseToHiddenConverter" />
<c:FalseToCollapsedConverter x:Key="FalseToCollapsedConverter" />
<c:EqualsConverter x:Key="EqualsConverter" />
<c:NotEqualsConverter x:Key="NotEqualsConverter" />
<c:NullToFalseConverter x:Key="NullToFalseConverter" />
<c:AllTrueToCollapsedConverter x:Key="AllTrueToCollapsedConverter" />
<c:BoolInverter x:Key="BoolInverter" />
xmlns:c="https://hkw.com/wpf">
<c:MarginMultiConverter x:Key="MarginConverter" />
<c:MarginMultiConverter x:Key="RatioMarginConverter" HasRatio="True" />
<c:CalculatorMultiConverter x:Key="CalculatorConverter" />
<c:StringFormatMultiConverter x:Key="StringFormatConverter" />
<c:SolidColorBrushToMediaColorConverter x:Key="BrushToMediaColorConverter" />
<!--<c:MaxConverter x:Key="MaxConverter" />-->
<c:BoolToVisibilityConverter x:Key="FalseToCollapsedConverter" />
<c:EqualsMultiConverter x:Key="EqualsConverter" />
<c:EqualsMultiConverter x:Key="NotEqualsConverter" IsInverted="True" />
<c:NullToBoolConverter x:Key="NullToFalseConverter" />
<c:AllBoolToVisibilityMultiConverter x:Key="AllTrueToCollapsedConverter" />
<c:BoolInverteConverter x:Key="BoolInverter" />
</ResourceDictionary>

View File

@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 全部为真时设置隐藏转换器
/// </summary>
public class AllTrueToCollapsedConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 0)
throw new ArgumentException("No values", nameof(values));
return values.All(i => i is true) ? Visibility.Collapsed : Visibility.Visible;
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,28 +0,0 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 任意为假时设置显示转换器
/// </summary>
public class AnyFalseToVisibleConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 0)
throw new ArgumentException("No values", nameof(values));
return values.Any(i => i is not true) ? Visibility.Visible : Visibility.Collapsed;
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class BoolInverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not bool b)
throw new ArgumentException("Value type not bool", nameof(value));
return !b;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
namespace VPet.ModMaker.Converters;
public class BrushToMediaColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not SolidColorBrush brush)
throw new ArgumentException("Not SolidColorBrush", nameof(value));
return brush.Color;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not Color color)
throw new ArgumentException("Not media color", nameof(value));
return new SolidColorBrush(color);
}
}

View File

@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 计算器转换器
/// <para>示例:
/// <code><![CDATA[
/// <MultiBinding Converter="{StaticResource CalculatorConverter}">
/// <Binding Path="Num1" />
/// <Binding Source="+" />
/// <Binding Path="Num2" />
/// <Binding Source="-" />
/// <Binding Path="Num3" />
/// <Binding Source="*" />
/// <Binding Path="Num4" />
/// <Binding Source="/" />
/// <Binding Path="Num5" />
/// </MultiBinding>
/// //
/// <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="+-*/">
/// <Binding Path="Num1" />
/// <Binding Path="Num2" />
/// <Binding Path="Num3" />
/// <Binding Path="Num4" />
/// <Binding Path="Num5" />
/// </MultiBinding>
/// ]]></code></para>
/// </summary>
/// <exception cref="Exception">绑定的数量不正确</exception>
public class CalculatorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Any(i => i == DependencyProperty.UnsetValue))
return 0.0;
if (values.Length == 1)
return values[0];
double result = System.Convert.ToDouble(values[0]);
if (parameter is string operators)
{
if (operators.Length != values.Length - 1)
throw new Exception("Parameter error: operator must be one more than parameter");
for (int i = 1; i < values.Length - 1; i++)
result = Operation(result, operators[i - 1], System.Convert.ToDouble(values[i]));
result = Operation(result, operators.Last(), System.Convert.ToDouble(values.Last()));
}
else
{
if (System.Convert.ToBoolean(values.Length & 1) is false)
throw new Exception("Parameter error: Incorrect quantity");
bool isNumber = false;
char currentOperator = '0';
for (int i = 1; i < values.Length - 1; i++)
{
if (isNumber is false)
{
currentOperator = ((string)values[i])[0];
isNumber = true;
}
else
{
var value = System.Convert.ToDouble(values[i]);
result = Operation(result, currentOperator, value);
isNumber = false;
}
}
result = Operation(result, currentOperator, System.Convert.ToDouble(values.Last()));
}
return result;
}
public static double Operation(double value1, char operatorChar, double value2)
{
return operatorChar switch
{
'+' => value1 + value2,
'-' => value1 - value2,
'*' => value1 * value2,
'/' => value1 / value2,
'%' => value1 % value2,
_ => throw new NotImplementedException(),
};
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class EqualsConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
if (values.Length != 2)
throw new NotImplementedException("Values length must be 2");
return values[0].Equals(values[1]);
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,21 +0,0 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class FalseToCollapsedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool.TryParse(value.ToString(), out var result) && result)
? Visibility.Visible
: Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is Visibility visibility && visibility == Visibility.Collapsed;
}
}

View File

@ -1,26 +0,0 @@
using Panuon.WPF;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class FalseToHiddenConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool.TryParse(value.ToString(), out var result) && result)
? Visibility.Visible
: Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is Visibility visibility && visibility == Visibility.Hidden;
}
}

View File

@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 边距转换器
/// <para>示例:
/// <code><![CDATA[
/// <MultiBinding Converter="{StaticResource MarginConverter}">
/// <Binding Path="Left" />
/// <Binding Path="Top" />
/// <Binding Path="Right" />
/// <Binding Path="Bottom" />
/// </MultiBinding>
/// ]]></code></para>
/// </summary>
public class MarginConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
if (values.Length == 0)
{
return new Thickness();
}
else if (values.Length == 1)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[0]),
Top = default,
Right = default,
Bottom = default
};
}
else if (values.Length == 2)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[0]),
Top = System.Convert.ToDouble(values[1]),
Right = default,
Bottom = default
};
}
else if (values.Length == 3)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[0]),
Top = System.Convert.ToDouble(values[1]),
Right = System.Convert.ToDouble(values[2]),
Bottom = default
};
}
else if (values.Length == 4)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[0]),
Top = System.Convert.ToDouble(values[1]),
Right = System.Convert.ToDouble(values[2]),
Bottom = System.Convert.ToDouble(values[3])
};
}
else
throw new NotImplementedException();
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class MaxConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
return values.Max(i => (double)i);
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
namespace VPet.ModMaker.Converters;
public class MediaColorToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not Color color)
throw new ArgumentException("Not media color", nameof(value));
return new SolidColorBrush(color);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not SolidColorBrush brush)
throw new ArgumentException("Not SolidColorBrush", nameof(value));
return brush.Color;
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class NotEqualsConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
if (values.Length != 2)
throw new NotImplementedException("Values length must be 2");
return !values[0].Equals(values[1]);
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,18 +0,0 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
public class NullToFalseConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@ -1,96 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 边距转换器
/// <para>示例:
/// <code><![CDATA[
/// <MultiBinding Converter="{StaticResource RatioMarginConverter}">
/// <Binding Path="Left" />
/// <Binding Path="Top" />
/// <Binding Path="Right" />
/// <Binding Path="Bottom" />
/// </MultiBinding>
/// ]]></code></para>
/// </summary>
public class RatioMarginConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
if (values.Any(i => i == DependencyProperty.UnsetValue))
return new Thickness();
if (values.Length == 0)
{
return new Thickness();
}
else if (values.Length == 1)
{
return new Thickness();
}
var ratio = System.Convert.ToDouble(values[0]);
if (values.Length == 2)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[1]) * ratio,
Top = default,
Right = default,
Bottom = default
};
}
else if (values.Length == 3)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[1]) * ratio,
Top = System.Convert.ToDouble(values[2]) * ratio,
Right = default,
Bottom = default
};
}
else if (values.Length == 4)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[1]) * ratio,
Top = System.Convert.ToDouble(values[2]) * ratio,
Right = System.Convert.ToDouble(values[3]) * ratio,
Bottom = default
};
}
else if (values.Length == 5)
{
return new Thickness()
{
Left = System.Convert.ToDouble(values[1]) * ratio,
Top = System.Convert.ToDouble(values[2]) * ratio,
Right = System.Convert.ToDouble(values[3]) * ratio,
Bottom = System.Convert.ToDouble(values[4]) * ratio
};
}
else
throw new NotImplementedException();
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace VPet.ModMaker.Converters;
/// <summary>
/// 边距转换器
/// <para>示例:
/// <code><![CDATA[
/// <MultiBinding Converter="{StaticResource MarginConverter}">
/// <Binding Path="StringFormat" />
/// <Binding Path="Value1" />
/// <Binding Path="Value2" />
/// </MultiBinding>
/// OR
/// <MultiBinding Converter="{StaticResource MarginConverter}" ConverterParameter="{}{0}{1}">
/// <Binding Path="Value1" />
/// <Binding Path="Value2" />
/// </MultiBinding>
/// ]]></code></para>
/// </summary>
public class StringFormatConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture
)
{
var formatStr = (string)parameter;
if (string.IsNullOrWhiteSpace(formatStr))
{
formatStr = (string)values[0];
return string.Format(formatStr, values.Skip(1).ToArray());
}
else
{
return string.Format(formatStr, values);
}
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture
)
{
throw new NotImplementedException();
}
}

View File

@ -1,81 +0,0 @@
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 VPet.ModMaker.Models;
/// <summary>
/// 可观察的枚举标签模型
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableEnumFlags<T>
where T : Enum
{
/// <summary>
/// 枚举值
/// </summary>
public ObservableValue<T> EnumValue { get; } = new();
/// <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("此枚举类型未使用特性 [Flags]");
AddCommand.ExecuteCommand += AddCommand_ExecuteEvent;
RemoveCommand.ExecuteCommand += RemoveCommand_ExecuteEvent;
}
public ObservableEnumFlags(T value)
: this()
{
EnumValue.Value = value;
}
private void AddCommand_ExecuteEvent(T value)
{
if (UnderlyingType == typeof(int))
{
EnumValue.Value = (T)
Enum.Parse(
EnumType,
(Convert.ToInt32(EnumValue.Value) | Convert.ToInt32(value)).ToString()
);
}
}
private void RemoveCommand_ExecuteEvent(T value)
{
if (UnderlyingType == typeof(int))
{
EnumValue.Value = (T)
Enum.Parse(
EnumType,
(Convert.ToInt32(EnumValue.Value) & ~Convert.ToInt32(value)).ToString()
);
}
}
}

View File

@ -1,24 +1,33 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
/// <summary>
/// I18n数据
/// </summary>
[DebuggerDisplay("{Id}, Count = {Datas.Count}")]
public class I18nData
[DebuggerDisplay("{ID}, Count = {Datas.Count}")]
public class I18nData : ObservableObjectX<I18nData>
{
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
/// <summary>
/// 基于 <see cref="I18nHelper.Current.CultureNames"/> 的索引的数据列表

View File

@ -1,11 +1,12 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
@ -13,7 +14,7 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// I18n助手
/// </summary>
public class I18nHelper
public class I18nHelper : ObservableObjectX<I18nHelper>
{
/// <summary>
/// 当前数据
@ -23,7 +24,16 @@ public class I18nHelper
/// <summary>
/// 当前文化名称
/// </summary>
public ObservableValue<string> CultureName { get; } = new();
#region CultureName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _cultureName;
public string CultureName
{
get => _cultureName;
set => SetProperty(ref _cultureName, value);
}
#endregion
/// <summary>
/// 文化列表

View File

@ -1,9 +1,10 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
@ -11,13 +12,22 @@ namespace VPet.ModMaker.Models;
/// I18n模型
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class I18nModel<T>
public class I18nModel<T> : ObservableObjectX<I18nModel<T>>
where T : class, new()
{
/// <summary>
/// 当前I18n数据
/// </summary>
public ObservableValue<T> CurrentI18nData { get; } = new();
#region CurrentI18nData
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private T _currentI18nData;
public T CurrentI18nData
{
get => _currentI18nData;
set => SetProperty(ref _currentI18nData, value);
}
#endregion
/// <summary>
/// 所有I18n数据
@ -26,7 +36,8 @@ public class I18nModel<T>
public I18nModel()
{
I18nHelper.Current.CultureName.ValueChanged += CultureChanged;
//TODO
//I18nHelper.Current.CultureName.ValueChanged += CultureChanged;
I18nHelper.Current.AddCulture += AddCulture;
I18nHelper.Current.RemoveCulture += RemoveCulture;
I18nHelper.Current.ReplaceCulture += ReplaceCulture;
@ -36,7 +47,7 @@ public class I18nModel<T>
{
I18nDatas.Add(item, new());
}
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
/// <summary>
@ -47,9 +58,9 @@ public class I18nModel<T>
private void CultureChanged(ObservableValue<string> sender, ValueChangedEventArgs<string> e)
{
if (e.NewValue is null)
CurrentI18nData.Value = null;
CurrentI18nData = null;
else if (I18nDatas.TryGetValue(e.NewValue, out var result))
CurrentI18nData.Value = result;
CurrentI18nData = result;
}
/// <summary>

View File

@ -1,9 +1,9 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
@ -11,20 +11,20 @@ namespace VPet.ModMaker.Models;
/// I18n模型
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class I18nModelBase<T> : ObservableClass<I18nModelBase<T>>
public class I18nModelBase<T> : ObservableObjectX<I18nModelBase<T>>
where T : class, new()
{
/// <summary>
/// 当前I18n数据
/// </summary>
private T _CurrentI18nData = new();
#region CurrentI18nData
private T _currentI18nData = new();
public T CurrentI18nData
{
get => _CurrentI18nData;
set => SetProperty(ref _CurrentI18nData, value);
get => _currentI18nData;
set => SetProperty(ref _currentI18nData, value);
}
#endregion
/// <summary>
/// 所有I18n数据
/// </summary>
@ -32,7 +32,8 @@ public class I18nModelBase<T> : ObservableClass<I18nModelBase<T>>
public I18nModelBase()
{
I18nHelper.Current.CultureName.ValueChanged += CultureChanged;
//TODO
//I18nHelper.Current.CultureName.ValueChanged += CultureChanged;
I18nHelper.Current.AddCulture += AddCulture;
I18nHelper.Current.RemoveCulture += RemoveCulture;
I18nHelper.Current.ReplaceCulture += ReplaceCulture;
@ -40,7 +41,7 @@ public class I18nModelBase<T> : ObservableClass<I18nModelBase<T>>
return;
foreach (var item in I18nHelper.Current.CultureNames)
I18nDatas.Add(item, new());
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
/// <summary>

View File

@ -129,9 +129,9 @@ public class ModLoader
foreach (var sub in line)
{
if (sub.Name == Name)
i18nData.Name.Value = sub.Info;
i18nData.Name = sub.Info;
else if (sub.Name == Intro)
i18nData.Description.Value = sub.Info;
i18nData.Description = sub.Info;
}
I18nDatas.Add(line.Info, i18nData);
}

View File

@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using HKW.HKWUtils.Observable;
@ -9,17 +10,35 @@ namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 动画模型
/// </summary>
public class AnimeModel
public class AnimeModel : ObservableObjectX<AnimeModel>
{
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region AnimeType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GraphInfo.AnimatType _animeType;
/// <summary>
/// 动画类型
/// </summary>
public ObservableValue<GraphInfo.AnimatType> AnimeType { get; } = new();
public GraphInfo.AnimatType AnimeType
{
get => _animeType;
set => SetProperty(ref _animeType, value);
}
#endregion
/// <summary>
/// 图像列表
@ -34,7 +53,7 @@ public class AnimeModel
foreach (var file in Directory.EnumerateFiles(imagesPath))
{
var info = Path.GetFileNameWithoutExtension(file).Split(NativeUtils.Separator);
Id.Value = info[0];
Id = info[0];
var duration = info.Last();
var imageModel = new ImageModel(
NativeUtils.LoadImageToMemoryStream(file),
@ -51,8 +70,8 @@ public class AnimeModel
public AnimeModel Copy()
{
var model = new AnimeModel();
model.Id.Value = Id.Value;
model.AnimeType.Value = AnimeType.Value;
model.Id = Id;
model.AnimeType = AnimeType;
foreach (var image in Images)
model.Images.Add(image.Copy());
return model;

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -13,7 +14,7 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.Models.ModModel;
public class AnimeTypeModel
public class AnimeTypeModel : ObservableObjectX<AnimeTypeModel>
{
/// <summary>
/// 动作类型
@ -65,20 +66,47 @@ public class AnimeTypeModel
GraphInfo.GraphType.Say
};
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
/// <summary>
/// 名称
/// </summary>
public ObservableValue<string> Name { get; } = new();
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region GraphType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GraphInfo.GraphType _GraphType;
/// <summary>
/// 动作类型
/// </summary>
public ObservableValue<GraphInfo.GraphType> GraphType { get; } = new();
public GraphInfo.GraphType GraphType
{
get => _GraphType;
set => SetProperty(ref _GraphType, value);
}
#endregion
/// <summary>
/// 开心动画
@ -101,19 +129,19 @@ public class AnimeTypeModel
public ObservableCollection<AnimeModel> IllAnimes { get; } = new();
public AnimeTypeModel()
{
Name.ValueChanged += (_, _) =>
{
Id.Value = $"{GraphType.Value}_{Name.Value}";
};
{ //TODO
//Name.ValueChanged += (_, _) =>
//{
// Id.Value = $"{GraphType.Value}_{Name.Value}";
//};
}
public AnimeTypeModel(AnimeTypeModel model)
: this()
{
Id.Value = model.Id.Value;
Name.Value = model.Name.Value;
GraphType.Value = model.GraphType.Value;
Id = model.Id;
Name = model.Name;
GraphType = model.GraphType;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
foreach (var anime in model.NomalAnimes)
@ -165,13 +193,13 @@ public class AnimeTypeModel
public AnimeTypeModel(GraphInfo.GraphType graphType, string path)
{
Name.Value = Path.GetFileName(path);
Name = Path.GetFileName(path);
// 为带有名字的类型设置Id
if (graphType.IsHasNameAnime())
Id.Value = $"{graphType}_{Name.Value}";
Id = $"{graphType}_{Name}";
else
Id.Value = graphType.ToString();
GraphType.Value = graphType;
Id = graphType.ToString();
GraphType = graphType;
if (
graphType
is GraphInfo.GraphType.Default
@ -370,7 +398,7 @@ public class AnimeTypeModel
{
// 如果没有文件夹 则载入全部文件
var animeModel = new AnimeModel(path);
animeModel.AnimeType.Value = animatType;
animeModel.AnimeType = animatType;
collection.Add(animeModel);
}
else
@ -379,7 +407,7 @@ public class AnimeTypeModel
foreach (var imagesDir in Directory.EnumerateDirectories(path))
{
var animeModel = new AnimeModel(imagesDir);
animeModel.AnimeType.Value = animatType;
animeModel.AnimeType = animatType;
collection.Add(animeModel);
}
}
@ -393,21 +421,21 @@ public class AnimeTypeModel
public void Save(string path)
{
if (
GraphType.Value
GraphType
is GraphInfo.GraphType.Default
or GraphInfo.GraphType.Shutdown
or GraphInfo.GraphType.StartUP
)
SaveDefault(path, this);
else if (
GraphType.Value
GraphType
is GraphInfo.GraphType.Touch_Head
or GraphInfo.GraphType.Touch_Body
or GraphInfo.GraphType.Sleep
)
SaveMultiType(path, this);
else if (
GraphType.Value
GraphType
is GraphInfo.GraphType.Switch_Up
or GraphInfo.GraphType.Switch_Down
or GraphInfo.GraphType.Switch_Thirsty
@ -415,16 +443,14 @@ public class AnimeTypeModel
)
SaveSwitch(path, this);
else if (
GraphType.Value
is GraphInfo.GraphType.Raised_Dynamic
or GraphInfo.GraphType.Raised_Static
GraphType is GraphInfo.GraphType.Raised_Dynamic or GraphInfo.GraphType.Raised_Static
)
SaveRaised(path, this);
else if (GraphType.Value is GraphInfo.GraphType.StateONE or GraphInfo.GraphType.StateTWO)
else if (GraphType is GraphInfo.GraphType.StateONE or GraphInfo.GraphType.StateTWO)
SaveState(path, this);
else if (GraphType.Value is GraphInfo.GraphType.Common)
else if (GraphType is GraphInfo.GraphType.Common)
SaveCommon(path, this);
else if (GraphType.Value.IsHasNameAnime())
else if (GraphType.IsHasNameAnime())
SaveHasNameAnime(path, this);
}
@ -435,9 +461,9 @@ public class AnimeTypeModel
/// <param name="animeTypeModel">动画模型</param>
void SaveHasNameAnime(string path, AnimeTypeModel animeTypeModel)
{
var animeTypePath = Path.Combine(path, animeTypeModel.GraphType.Value.ToString());
var animeTypePath = Path.Combine(path, animeTypeModel.GraphType.ToString());
Directory.CreateDirectory(animeTypePath);
var animePath = Path.Combine(animeTypePath, animeTypeModel.Name.Value);
var animePath = Path.Combine(animeTypePath, animeTypeModel.Name);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
@ -449,7 +475,7 @@ public class AnimeTypeModel
/// <param name="animeTypeModel">模型</param>
void SaveCommon(string path, AnimeTypeModel animeTypeModel)
{
var animePath = Path.Combine(path, animeTypeModel.Name.Value);
var animePath = Path.Combine(path, animeTypeModel.Name);
Directory.CreateDirectory(animePath);
SaveWithModeType(animePath, animeTypeModel);
}
@ -475,9 +501,9 @@ public class AnimeTypeModel
{
var animePath = Path.Combine(path, "Raise");
Directory.CreateDirectory(animePath);
if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Dynamic)
if (animeTypeModel.GraphType is GraphInfo.GraphType.Raised_Dynamic)
SaveDefault(animePath, animeTypeModel);
else if (animeTypeModel.GraphType.Value is GraphInfo.GraphType.Raised_Static)
else if (animeTypeModel.GraphType is GraphInfo.GraphType.Raised_Static)
SaveMultiType(animePath, animeTypeModel);
}
@ -554,21 +580,21 @@ public class AnimeTypeModel
var countC = 0;
foreach (var anime in animes)
{
if (anime.AnimeType.Value is GraphInfo.AnimatType.A_Start)
if (anime.AnimeType is GraphInfo.AnimatType.A_Start)
{
var animatTypePath = Path.Combine(animePath, "A");
Directory.CreateDirectory(animatTypePath);
SaveImages(Path.Combine(animatTypePath, countA.ToString()), anime);
countA++;
}
else if (anime.AnimeType.Value is GraphInfo.AnimatType.B_Loop)
else if (anime.AnimeType is GraphInfo.AnimatType.B_Loop)
{
var animatTypePath = Path.Combine(animePath, "B");
Directory.CreateDirectory(animatTypePath);
SaveImages(Path.Combine(animatTypePath, countB.ToString()), anime);
countB++;
}
else if (anime.AnimeType.Value is GraphInfo.AnimatType.C_End)
else if (anime.AnimeType is GraphInfo.AnimatType.C_End)
{
var animatTypePath = Path.Combine(animePath, "C");
Directory.CreateDirectory(animatTypePath);
@ -624,11 +650,8 @@ public class AnimeTypeModel
Directory.CreateDirectory(imagesPath);
foreach (var image in model.Images.EnumerateIndex())
{
image.Value.Image.Value.SaveToPng(
Path.Combine(
imagesPath,
$"{model.Id.Value}_{image.Index:000}_{image.Value.Duration.Value}.png"
)
image.Value.Image.SaveToPng(
Path.Combine(imagesPath, $"{model.Id}_{image.Index:000}_{image.Value.Duration}.png")
);
}
}

View File

@ -1,13 +1,13 @@
using HKW.HKWUtils;
using HKW.HKWUtils.Observable;
using LinePutScript.Converter;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils;
using HKW.HKWUtils.Observable;
using LinePutScript.Converter;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.Models;
@ -38,20 +38,38 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
.Cast<VPet_Simulator.Core.Main.WorkingState>()
);
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Working
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _working = string.Empty;
/// <summary>
/// 指定工作
/// </summary>
public ObservableValue<string> Working { get; } = new();
public string Working
{
get => _working;
set => SetProperty(ref _working, value);
}
#endregion
/// <summary>
/// 宠物状态
/// </summary>
public ObservableEnumFlags<ClickText.ModeType> Mode { get; } =
public ObservableEnumCommand<ClickText.ModeType> Mode { get; } =
new(
ClickText.ModeType.Happy
| ClickText.ModeType.Nomal
@ -59,15 +77,24 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
| ClickText.ModeType.Ill
);
#region WorkingState
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private VPet_Simulator.Core.Main.WorkingState _WorkingState;
/// <summary>
/// 行动状态
/// </summary>
public ObservableValue<VPet_Simulator.Core.Main.WorkingState> WorkingState { get; } = new();
public VPet_Simulator.Core.Main.WorkingState WorkingState
{
get => _WorkingState;
set => SetProperty(ref _WorkingState, value);
}
#endregion
/// <summary>
/// 日期区间
/// </summary>
public ObservableEnumFlags<ClickText.DayTime> DayTime { get; } =
public ObservableEnumCommand<ClickText.DayTime> DayTime { get; } =
new(
ClickText.DayTime.Morning
| ClickText.DayTime.Afternoon
@ -120,32 +147,32 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
public ClickTextModel(ClickTextModel clickText)
: this()
{
Id.Value = clickText.Id.Value;
Mode.EnumValue.Value = clickText.Mode.EnumValue.Value;
Working.Value = clickText.Working.Value;
WorkingState.Value = clickText.WorkingState.Value;
DayTime.EnumValue.Value = clickText.DayTime.EnumValue.Value;
Like = clickText.Like.Copy();
Health = clickText.Health.Copy();
Level = clickText.Level.Copy();
Money = clickText.Money.Copy();
Food = clickText.Food.Copy();
Drink = clickText.Drink.Copy();
Feel = clickText.Feel.Copy();
Strength = clickText.Strength.Copy();
Id = clickText.Id;
Mode.Value = clickText.Mode.Value;
Working = clickText.Working;
WorkingState = clickText.WorkingState;
DayTime.Value = clickText.DayTime.Value;
Like = clickText.Like.Clone();
Health = clickText.Health.Clone();
Level = clickText.Level.Clone();
Money = clickText.Money.Clone();
Food = clickText.Food.Clone();
Drink = clickText.Drink.Clone();
Feel = clickText.Feel.Clone();
Strength = clickText.Strength.Clone();
foreach (var item in clickText.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public ClickTextModel(ClickText clickText)
: this()
{
Id.Value = clickText.Text;
Mode.EnumValue.Value = clickText.Mode;
Working.Value = clickText.Working;
WorkingState.Value = clickText.State;
DayTime.EnumValue.Value = clickText.DaiTime;
Id = clickText.Text;
Mode.Value = clickText.Mode;
Working = clickText.Working;
WorkingState = clickText.State;
DayTime.Value = clickText.DaiTime;
Like = new(clickText.LikeMin, clickText.LikeMax);
Health = new(clickText.HealthMin, clickText.HealthMax);
Level = new(clickText.LevelMin, clickText.LevelMax);
@ -160,11 +187,11 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
{
return new()
{
Text = Id.Value,
Mode = Mode.EnumValue.Value,
Working = Working.Value,
State = WorkingState.Value,
DaiTime = DayTime.EnumValue.Value,
Text = Id,
Mode = Mode.Value,
Working = Working,
State = WorkingState,
DaiTime = DayTime.Value,
LikeMax = Like.Max,
LikeMin = Like.Min,
HealthMin = Health.Min,
@ -185,14 +212,23 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
}
}
public class I18nClickTextModel
public class I18nClickTextModel : ObservableObjectX<I18nClickTextModel>
{
public ObservableValue<string> Text { get; } = new();
#region Text
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _text = string.Empty;
public string Text
{
get => _text;
set => SetProperty(ref _text, value);
}
#endregion
public I18nClickTextModel Copy()
{
var result = new I18nClickTextModel();
result.Text.Value = Text.Value;
result.Text = Text;
return result;
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
@ -12,12 +13,18 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeModel
public class FoodAnimeModel : ObservableObjectX<FoodAnimeModel>
{
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _Id;
public string Id
{
get => _Id;
set => SetProperty(ref _Id, value);
}
#endregion
public ObservableValue<ModeType> Mode { get; }
@ -46,7 +53,7 @@ public class FoodAnimeModel
//var index = int.Parse(item.Name.Substring(1));
var infos = item.Info.Split(',');
var foodLocationInfo = new FoodLocationModel();
foodLocationInfo.Duration.Value = int.Parse(infos[0]);
foodLocationInfo.Duration = int.Parse(infos[0]);
if (infos.Length > 1)
{
foodLocationInfo.Rect = new(
@ -57,9 +64,9 @@ public class FoodAnimeModel
);
}
if (infos.Length > 4)
foodLocationInfo.Rotate.Value = double.Parse(infos[4]);
foodLocationInfo.Rotate = double.Parse(infos[4]);
if (infos.Length > 5)
foodLocationInfo.Opacity.Value = double.Parse(infos[5]);
foodLocationInfo.Opacity = double.Parse(infos[5]);
FoodLocations.Add(foodLocationInfo);
}
}
@ -71,7 +78,7 @@ public class FoodAnimeModel
public FoodAnimeModel Copy()
{
var model = new FoodAnimeModel();
model.Id.Value = Id.Value;
model.Id = Id;
foreach (var image in FrontImages)
model.FrontImages.Add(image.Copy());
foreach (var image in BackImages)
@ -92,10 +99,3 @@ public class FoodAnimeModel
image.Close();
}
}
public class FoodImagesPath
{
public ObservableValue<ModeType> Mode { get; } = new();
public ObservableValue<int> Index { get; } = new();
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -14,7 +15,7 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.Models.ModModel;
public class FoodAnimeTypeModel
public class FoodAnimeTypeModel : ObservableObjectX<FoodAnimeModel>
{
/// <summary>
/// 动作类型
@ -37,15 +38,30 @@ public class FoodAnimeTypeModel
/// </summary>
public const string BackLayName = "back_lay";
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
/// <summary>
/// 名称
/// </summary>
public ObservableValue<string> Name { get; } = new();
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
/// <summary>
/// 开心动画
@ -68,11 +84,11 @@ public class FoodAnimeTypeModel
public ObservableCollection<FoodAnimeModel> IllAnimes { get; } = new();
public FoodAnimeTypeModel()
{
Name.ValueChanged += (_, _) =>
{
Id.Value = $"{GraphType}_{Name.Value}";
};
{ //TODO
//Name.ValueChanged += (_, _) =>
//{
// Id.Value = $"{GraphType}_{Name.Value}";
//};
}
public void Close()
@ -98,7 +114,7 @@ public class FoodAnimeTypeModel
public FoodAnimeTypeModel(string path)
: this()
{
Name.Value = Path.GetFileName(path);
Name = Path.GetFileName(path);
var infoFiles = Directory.EnumerateFiles(
path,
ModMakerInfo.InfoFile,
@ -108,15 +124,15 @@ public class FoodAnimeTypeModel
throw new Exception("信息文件不存在".Translate());
foreach (var file in infoFiles)
{
ParseInfoFile(Path.GetDirectoryName(file), file);
ParseInfoFile(Path.GetDirectoryName(file)!, file);
}
}
public FoodAnimeTypeModel(FoodAnimeTypeModel model)
: this()
{
Id.Value = model.Id.Value;
Name.Value = model.Name.Value;
Id = model.Id;
Name = model.Name;
foreach (var anime in model.HappyAnimes)
HappyAnimes.Add(anime.Copy());
foreach (var anime in model.NomalAnimes)
@ -253,7 +269,7 @@ public class FoodAnimeTypeModel
/// <param name="path">路径</param>
public void Save(string path)
{
var animePath = Path.Combine(path, Name.Value);
var animePath = Path.Combine(path, Name);
if (
Directory.Exists(animePath)
&& HappyAnimes.Count == 0
@ -293,8 +309,8 @@ public class FoodAnimeTypeModel
var indexPath = Path.Combine(modeAnimePath, anime.Index.ToString());
Directory.CreateDirectory(indexPath);
var infoFile = Path.Combine(indexPath, ModMakerInfo.InfoFile);
var frontLayName = $"{Name.Value.ToLower()}_{FrontLayName}_{anime.Index}";
var backLayName = $"{Name.Value.ToLower()}_{BackLayName}_{anime.Index}";
var frontLayName = $"{Name.ToLower()}_{FrontLayName}_{anime.Index}";
var backLayName = $"{Name.ToLower()}_{BackLayName}_{anime.Index}";
SaveInfoFile(infoFile, frontLayName, backLayName, anime.Value, mode);
SaveImages(anime.Value, indexPath);
}
@ -315,19 +331,19 @@ public class FoodAnimeTypeModel
Directory.CreateDirectory(backLayPath);
foreach (var frontImage in anime.FrontImages.EnumerateIndex())
{
frontImage.Value.Image.Value.SaveToPng(
frontImage.Value.Image.SaveToPng(
Path.Combine(
frontLayPath,
$"{anime.Id.Value}_{frontImage.Index:000}_{frontImage.Value.Duration.Value}.png"
$"{anime.Id}_{frontImage.Index:000}_{frontImage.Value.Duration}.png"
)
);
}
foreach (var backImage in anime.BackImages.EnumerateIndex())
{
backImage.Value.Image.Value.SaveToPng(
backImage.Value.Image.SaveToPng(
Path.Combine(
backLayPath,
$"{anime.Id.Value}_{backImage.Index:000}_{backImage.Value.Duration.Value}.png"
$"{anime.Id}_{backImage.Index:000}_{backImage.Value.Duration}.png"
)
);
}
@ -356,10 +372,10 @@ public class FoodAnimeTypeModel
new Sub("graph", nameof(GraphInfo.GraphType.Common))
},
};
var line = new Line(nameof(FoodAnimation), Name.Value.ToLower())
var line = new Line(nameof(FoodAnimation), Name.ToLower())
{
new Sub("mode", mode.ToString()),
new Sub("graph", Name.Value)
new Sub("graph", Name)
};
foreach (var foodLocation in anime.FoodLocations.EnumerateIndex())
{

View File

@ -1,36 +1,64 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 食物图像模型
/// </summary>
public class FoodLocationModel
public class FoodLocationModel : ObservableObjectX<FoodLocationModel>
{
#region Duration
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _duration;
/// <summary>
/// 持续时间
/// </summary>
public ObservableValue<int> Duration { get; } = new(100);
public int Duration
{
get => _duration;
set => SetProperty(ref _duration, value);
}
#endregion
/// <summary>
/// 范围
/// </summary>
public ObservableRect<double> Rect { get; set; } = new();
public ObservableRectangleLocation<double> Rect { get; set; } = new();
/// <summary>
/// 旋转角度
/// </summary>
public ObservableValue<double> Rotate { get; } = new();
#region Rotate
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _rotate;
public double Rotate
{
get => _rotate;
set => SetProperty(ref _rotate, value);
}
#endregion
/// <summary>
/// 透明度
/// </summary>
public ObservableValue<double> Opacity { get; } = new(100);
#region Opacity
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _opacity;
public double Opacity
{
get => _opacity;
set => SetProperty(ref _opacity, value);
}
#endregion
public FoodLocationModel()
{
@ -43,15 +71,15 @@ public class FoodLocationModel
public FoodLocationModel Copy()
{
var model = new FoodLocationModel();
model.Duration.Value = Duration.Value;
model.Duration = Duration;
model.Rect = new(Rect.X, Rect.Y, Rect.Width, Rect.Height);
model.Rotate.Value = Rotate.Value;
model.Opacity.Value = Opacity.Value;
model.Rotate = Rotate;
model.Opacity = Opacity;
return model;
}
public override string ToString()
{
return $"{Duration.Value}, {Rect.X}, {Rect.Y}, {Rect.Width}, {Rotate.Value}, {Opacity.Value}";
return $"{Duration}, {Rect.X}, {Rect.Y}, {Rect.Width}, {Rotate}, {Opacity}";
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -24,189 +25,334 @@ public class FoodModel : I18nModel<I18nFoodModel>
public static ObservableCollection<Food.FoodType> FoodTypes { get; } =
new(Enum.GetValues(typeof(Food.FoodType)).Cast<Food.FoodType>());
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region DescriptionId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId = string.Empty;
/// <summary>
/// 详情Id
/// </summary>
public ObservableValue<string> DescriptionId { get; } = new();
public string DescriptionId
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
}
#endregion
#region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph = string.Empty;
/// <summary>
/// 指定动画
/// </summary>
public ObservableValue<string> Graph { get; } = new("eat");
public string Graph
{
get => _graph;
set => SetProperty(ref _graph, value);
}
#endregion
#region Type
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Food.FoodType _type;
/// <summary>
/// 类型
/// </summary>
public ObservableValue<Food.FoodType> Type { get; } = new();
public Food.FoodType Type
{
get => _type;
set => SetProperty(ref _type, value);
}
#endregion
/// <summary>
/// 体力
/// </summary>
public ObservableValue<double> Strength { get; } = new();
#region Strength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Strength;
public double Strength
{
get => _Strength;
set => SetProperty(ref _Strength, value);
}
#endregion
/// <summary>
/// 饱食度
/// </summary>
public ObservableValue<double> StrengthFood { get; } = new();
#region StrengthFood
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _StrengthFood;
public double StrengthFood
{
get => _StrengthFood;
set => SetProperty(ref _StrengthFood, value);
}
#endregion
/// <summary>
/// 口渴度
/// </summary>
public ObservableValue<double> StrengthDrink { get; } = new();
#region StrengthDrink
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _StrengthDrink;
public double StrengthDrink
{
get => _StrengthDrink;
set => SetProperty(ref _StrengthDrink, value);
}
#endregion
/// <summary>
/// 心情
/// </summary>
public ObservableValue<double> Feeling { get; } = new();
#region Feeling
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Feeling;
public double Feeling
{
get => _Feeling;
set => SetProperty(ref _Feeling, value);
}
#endregion
/// <summary>
/// 健康度
/// </summary>
public ObservableValue<double> Health { get; } = new();
#region Health
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Health;
public double Health
{
get => _Health;
set => SetProperty(ref _Health, value);
}
#endregion
/// <summary>
/// 好感度
/// </summary>
public ObservableValue<double> Likability { get; } = new();
#region Likability
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Likability;
public double Likability
{
get => _Likability;
set => SetProperty(ref _Likability, value);
}
#endregion
/// <summary>
/// 价格
/// </summary>
public ObservableValue<double> Price { get; } = new();
#region Price
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Price;
public double Price
{
get => _Price;
set => SetProperty(ref _Price, value);
}
#endregion
/// <summary>
/// 经验
/// </summary>
public ObservableValue<int> Exp { get; } = new();
#region Exp
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _Exp;
public int Exp
{
get => _Exp;
set => SetProperty(ref _Exp, value);
}
#endregion
/// <summary>
/// 图片
/// </summary>
public ObservableValue<BitmapImage> Image { get; } = new();
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _Image;
public ObservableValue<double> ReferencePrice { get; } = new();
public BitmapImage Image
{
get => _Image;
set => SetProperty(ref _Image, value);
}
#endregion
#region ReferencePrice
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _ReferencePrice;
public double ReferencePrice
{
get => _ReferencePrice;
set => SetProperty(ref _ReferencePrice, value);
}
#endregion
private readonly Food _food = new();
public FoodModel()
{
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
Id.ValueChanged += (s, e) =>
{
DescriptionId.Value = $"{e.NewValue}_{nameof(DescriptionId)}";
};
ReferencePrice.AddNotifySender(
Strength,
StrengthFood,
StrengthDrink,
Feeling,
Health,
Likability,
Exp
);
ReferencePrice.SenderPropertyChanged += (s, _) =>
{
s.Value = Math.Floor(SetValueToFood(_food).RealPrice);
};
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
//TODO
//Id.ValueChanged += (s, e) =>
//{
// DescriptionId.Value = $"{e.NewValue}_{nameof(DescriptionId)}";
//};
//ReferencePrice.AddNotifySender(
// Strength,
// StrengthFood,
// StrengthDrink,
// Feeling,
// Health,
// Likability,
// Exp
//);
//ReferencePrice.SenderPropertyChanged += (s, _) =>
//{
// s.Value = Math.Floor(SetValueToFood(_food).RealPrice);
//};
}
public FoodModel(FoodModel model)
: this()
{
Id.Value = model.Id.Value;
DescriptionId.Value = model.DescriptionId.Value;
Graph.Value = model.Graph.Value;
Type.Value = model.Type.Value;
Strength.Value = model.Strength.Value;
StrengthFood.Value = model.StrengthFood.Value;
StrengthDrink.Value = model.StrengthDrink.Value;
Feeling.Value = model.Feeling.Value;
Health.Value = model.Health.Value;
Likability.Value = model.Likability.Value;
Price.Value = model.Price.Value;
Exp.Value = model.Exp.Value;
Image.Value = model.Image.Value.Copy();
Id = model.Id;
DescriptionId = model.DescriptionId;
Graph = model.Graph;
Type = model.Type;
Strength = model.Strength;
StrengthFood = model.StrengthFood;
StrengthDrink = model.StrengthDrink;
Feeling = model.Feeling;
Health = model.Health;
Likability = model.Likability;
Price = model.Price;
Exp = model.Exp;
Image = model.Image.Copy();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public FoodModel(Food food)
: this()
{
Id.Value = food.Name;
DescriptionId.Value = food.Desc;
Graph.Value = food.Graph;
Type.Value = food.Type;
Strength.Value = food.Strength;
StrengthDrink.Value = food.StrengthDrink;
StrengthFood.Value = food.StrengthFood;
Feeling.Value = food.Feeling;
Health.Value = food.Health;
Likability.Value = food.Likability;
Price.Value = food.Price;
Exp.Value = food.Exp;
Id = food.Name;
DescriptionId = food.Desc;
Graph = food.Graph;
Type = food.Type;
Strength = food.Strength;
StrengthDrink = food.StrengthDrink;
StrengthFood = food.StrengthFood;
Feeling = food.Feeling;
Health = food.Health;
Likability = food.Likability;
Price = food.Price;
Exp = food.Exp;
if (File.Exists(food.Image))
Image.Value = NativeUtils.LoadImageToMemoryStream(food.Image);
Image = NativeUtils.LoadImageToMemoryStream(food.Image);
}
public Food ToFood()
{
return new Food()
{
Name = Id.Value,
Desc = DescriptionId.Value,
Graph = Graph.Value,
Type = Type.Value,
Strength = Strength.Value,
StrengthFood = StrengthFood.Value,
StrengthDrink = StrengthDrink.Value,
Feeling = Feeling.Value,
Health = Health.Value,
Likability = Likability.Value,
Price = Price.Value,
Exp = Exp.Value,
Name = Id,
Desc = DescriptionId,
Graph = Graph,
Type = Type,
Strength = Strength,
StrengthFood = StrengthFood,
StrengthDrink = StrengthDrink,
Feeling = Feeling,
Health = Health,
Likability = Likability,
Price = Price,
Exp = Exp,
};
}
public Food SetValueToFood(Food food)
{
food.Strength = Strength.Value;
food.StrengthFood = StrengthFood.Value;
food.StrengthDrink = StrengthDrink.Value;
food.Feeling = Feeling.Value;
food.Health = Health.Value;
food.Likability = Likability.Value;
food.Exp = Exp.Value;
food.Strength = Strength;
food.StrengthFood = StrengthFood;
food.StrengthDrink = StrengthDrink;
food.Feeling = Feeling;
food.Health = Health;
food.Likability = Likability;
food.Exp = Exp;
return food;
}
public void RefreshId()
{
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
}
public void Close()
{
Image.Value?.StreamSource?.Close();
Image.CloseStream();
}
}
public class I18nFoodModel
public class I18nFoodModel : ObservableObjectX<I18nFoodModel>
{
public ObservableValue<string> Name { get; } = new();
public ObservableValue<string> Description { get; } = new();
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty;
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
public I18nFoodModel Copy()
{
var result = new I18nFoodModel();
result.Name.Value = Name.Value;
result.Description.Value = Description.Value;
result.Name = Name;
result.Description = Description;
return result;
}
}

View File

@ -1,44 +1,62 @@
using HKW.HKWUtils;
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using HKW.HKWUtils;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models.ModModel;
/// <summary>
/// 图像模型
/// </summary>
public class ImageModel
public class ImageModel : ObservableObjectX<ImageModel>
{
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
/// <summary>
/// 图像
/// </summary>
public ObservableValue<BitmapImage> Image { get; } = new();
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#region Duration
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _duration;
/// <summary>
/// 持续时间
/// </summary>
public ObservableValue<int> Duration { get; } = new(100);
public int Duration
{
get => _duration;
set => SetProperty(ref _duration, value);
}
#endregion
public ImageModel(BitmapImage image, int duration = 100)
{
Image.Value = image;
Duration.Value = duration;
Image = image;
Duration = duration;
}
public ImageModel Copy()
{
var model = new ImageModel(Image.Value.Copy(), Duration.Value);
var model = new ImageModel(Image.Copy(), Duration);
return model;
}
public void Close()
{
Image.Value?.CloseStream();
Image?.CloseStream();
}
}

View File

@ -1,11 +1,12 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using HKW.HKWUtils.Observable;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.Models;
@ -33,48 +34,85 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
public static ObservableCollection<LowText.StrengthType> StrengthTypes { get; } =
new(Enum.GetValues(typeof(LowText.StrengthType)).Cast<LowText.StrengthType>());
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Mode
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowText.ModeType _mode;
/// <summary>
/// 状态
/// </summary>
public ObservableValue<LowText.ModeType> Mode { get; } = new();
public LowText.ModeType Mode
{
get => _mode;
set => SetProperty(ref _mode, value);
}
#endregion
#region Strength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowText.StrengthType _strength;
/// <summary>
/// 体力
/// </summary>
public ObservableValue<LowText.StrengthType> Strength { get; } = new();
public LowText.StrengthType Strength
{
get => _strength;
set => SetProperty(ref _strength, value);
}
#endregion
#region Like
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowText.LikeType _like;
/// <summary>
/// 好感度
/// </summary>
public ObservableValue<LowText.LikeType> Like { get; } = new();
public LowText.LikeType Like
{
get => _like;
set => SetProperty(ref _like, value);
}
#endregion
public LowTextModel() { }
public LowTextModel(LowTextModel lowText)
: this()
{
Id.Value = lowText.Id.Value;
Mode.Value = lowText.Mode.Value;
Strength.Value = lowText.Strength.Value;
Like.Value = lowText.Like.Value;
Id = lowText.Id;
Mode = lowText.Mode;
Strength = lowText.Strength;
Like = lowText.Like;
foreach (var item in lowText.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public LowTextModel(LowText lowText)
: this()
{
Id.Value = lowText.Text;
Mode.Value = lowText.Mode;
Strength.Value = lowText.Strength;
Like.Value = lowText.Like;
Id = lowText.Text;
Mode = lowText.Mode;
Strength = lowText.Strength;
Like = lowText.Like;
}
public void Close() { }
@ -83,22 +121,31 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
{
return new()
{
Text = Id.Value,
Mode = Mode.Value,
Strength = Strength.Value,
Like = Like.Value,
Text = Id,
Mode = Mode,
Strength = Strength,
Like = Like,
};
}
}
public class I18nLowTextModel
public class I18nLowTextModel : ObservableObjectX<I18nLowTextModel>
{
public ObservableValue<string> Text { get; } = new();
#region Text
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _text = string.Empty;
public string Text
{
get => _text;
set => SetProperty(ref _text, value);
}
#endregion
public I18nLowTextModel Copy()
{
var result = new I18nLowTextModel();
result.Text.Value = Text.Value;
result.Text = Text;
return result;
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -25,15 +26,33 @@ namespace VPet.ModMaker.Models;
/// </summary>
public class ModInfoModel : I18nModel<I18nModInfoModel>
{
#region AutoSetFoodPrice
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _autoSetFoodPrice;
/// <summary>
/// 自动设置食物推荐价格
/// </summary>
public ObservableValue<bool> AutoSetFoodPrice { get; } = new();
public bool AutoSetFoodPrice
{
get => _autoSetFoodPrice;
set => SetProperty(ref _autoSetFoodPrice, value);
}
#endregion
#region ShowMainPet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _showMainPet;
/// <summary>
/// 不显示本体宠物
/// </summary>
public ObservableValue<bool> ShowMainPet { get; } = new(true);
public bool ShowMainPet
{
get => _showMainPet;
set => SetProperty(ref _showMainPet, value);
}
#endregion
#region ModInfo
/// <summary>
@ -51,40 +70,103 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public static ModInfoModel Current { get; set; } = new();
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region DescriptionId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId = string.Empty;
/// <summary>
/// 描述Id
/// </summary>
public ObservableValue<string> DescriptionId { get; } = new();
public string DescriptionId
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
}
#endregion
/// <summary>
/// 作者
/// </summary>
public ObservableValue<string> Author { get; } = new();
#region Author
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _author = string.Empty;
public string Author
{
get => _author;
set => SetProperty(ref _author, value);
}
#endregion
/// <summary>
/// 支持的游戏版本
/// </summary>
public ObservableValue<int> GameVersion { get; } = new(ModMakerInfo.GameVersion);
#region GameVersion
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _gameVersion;
public int GameVersion
{
get => _gameVersion;
set => SetProperty(ref _gameVersion, value);
}
#endregion
/// <summary>
/// 模组版本
/// </summary>
public ObservableValue<int> ModVersion { get; } = new(100);
#region ModVersion
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _modVersion;
public int ModVersion
{
get => _modVersion;
set => SetProperty(ref _modVersion, value);
}
#endregion
/// <summary>
/// 封面
/// </summary>
public ObservableValue<BitmapImage> Image { get; } = new();
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
/// <summary>
/// 源路径
/// </summary>
public ObservableValue<string> SourcePath { get; } = new();
#region SourcePath
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _sourcePath = string.Empty;
public string SourcePath
{
get => _sourcePath;
set => SetProperty(ref _sourcePath, value);
}
#endregion
#endregion
@ -117,7 +199,16 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <summary>
/// 宠物实际数量
/// </summary>
public ObservableValue<int> PetDisplayedCount { get; } = new();
#region PetDisplayedCount
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _petDisplayedCount;
public int PetDisplayedCount
{
get => _petDisplayedCount;
set => SetProperty(ref _petDisplayedCount, value);
}
#endregion
/// <summary>
/// 其它I18n数据
@ -131,13 +222,14 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
#endregion
public ModInfoModel()
{
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
Id.ValueChanged += (o, n) =>
{
DescriptionId.Value = $"{n}_{nameof(DescriptionId)}";
};
Pets.CollectionChanged += Pets_CollectionChanged;
ShowMainPet.ValueChanged += ShowMainPet_ValueChanged;
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
//TODO
//Id.ValueChanged += (o, n) =>
//{
// DescriptionId.Value = $"{n}_{nameof(DescriptionId)}";
//};
//Pets.CollectionChanged += Pets_CollectionChanged;
//ShowMainPet.ValueChanged += ShowMainPet_ValueChanged;
}
private void ShowMainPet_ValueChanged(
@ -150,26 +242,26 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
private void Pets_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (ShowMainPet.Value)
PetDisplayedCount.Value = Pets.Count;
if (ShowMainPet)
PetDisplayedCount = Pets.Count;
else
PetDisplayedCount.Value = Pets.Count - Pets.Count(m => m.FromMain.Value);
PetDisplayedCount = Pets.Count - Pets.Count(m => m.FromMain);
}
public ModInfoModel(ModLoader loader)
: this()
{
SourcePath.Value = loader.ModPath.FullName;
Id.Value = loader.Name;
DescriptionId.Value = loader.Intro;
Author.Value = loader.Author;
GameVersion.Value = loader.GameVer;
ModVersion.Value = loader.Ver;
SourcePath = loader.ModPath.FullName;
Id = loader.Name;
DescriptionId = loader.Intro;
Author = loader.Author;
GameVersion = loader.GameVer;
ModVersion = loader.Ver;
ItemID = loader.ItemID;
AuthorID = loader.AuthorID;
var imagePath = Path.Combine(loader.ModPath.FullName, "icon.png");
if (File.Exists(imagePath))
Image.Value = NativeUtils.LoadImageToMemoryStream(imagePath);
Image = NativeUtils.LoadImageToMemoryStream(imagePath);
foreach (var food in loader.Foods)
Foods.Add(new(food));
foreach (var clickText in loader.ClickTexts)
@ -184,29 +276,29 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
var petModel = new PetModel(pet);
// 如果检测到本体存在同名宠物
if (ModMakerInfo.MainPets.TryGetValue(petModel.Id.Value, out var mainPet))
if (ModMakerInfo.MainPets.TryGetValue(petModel.ID, out var mainPet))
{
// 若宠物的值为默认值并且本体同名宠物不为默认值, 则把本体宠物的值作为模组宠物的默认值
if (
petModel.TouchHeadRect == PetModel.Default.TouchHeadRect
&& petModel.TouchHeadRect != mainPet.TouchHeadRect
)
petModel.TouchHeadRect.Value = mainPet.TouchHeadRect.Value;
petModel.TouchHeadRect = mainPet.TouchHeadRect;
if (
petModel.TouchBodyRect == PetModel.Default.TouchBodyRect
&& petModel.TouchBodyRect != mainPet.TouchBodyRect
)
petModel.TouchBodyRect.Value = mainPet.TouchBodyRect.Value;
petModel.TouchBodyRect = mainPet.TouchBodyRect;
if (
petModel.TouchRaisedRect == PetModel.Default.TouchRaisedRect
&& petModel.TouchRaisedRect != mainPet.TouchRaisedRect
)
petModel.TouchRaisedRect.Value = mainPet.TouchRaisedRect.Value;
petModel.TouchRaisedRect = mainPet.TouchRaisedRect;
if (
petModel.RaisePoint == PetModel.Default.RaisePoint
&& petModel.RaisePoint != mainPet.RaisePoint
)
petModel.RaisePoint.Value = mainPet.RaisePoint.Value;
petModel.RaisePoint = mainPet.RaisePoint;
}
Pets.Add(petModel);
foreach (var p in pet.path)
@ -220,7 +312,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
foreach (var pet in ModMakerInfo.MainPets)
{
// 确保Id不重复
if (Pets.All(i => i.Id.Value != pet.Key))
if (Pets.All(i => i.ID != pet.Key))
Pets.Insert(0, pet.Value);
}
@ -236,7 +328,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
public void RefreshId()
{
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
DescriptionId = $"{Id}_{nameof(DescriptionId)}";
}
#region Load
@ -341,7 +433,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
if (I18nHelper.Current.CultureNames.Count == 0)
return;
I18nHelper.Current.CultureName.Value = I18nHelper.Current.CultureNames.First();
I18nHelper.Current.CultureName = I18nHelper.Current.CultureNames.First();
foreach (var i18nData in OtherI18nDatas)
{
LoadFoodI18nData(i18nData.Key, i18nData.Value);
@ -358,10 +450,10 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
if (food.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(food.Id.Value, out var name))
data.Name.Value = name;
if (i18nData.TryGetValue(food.DescriptionId.Value, out var description))
data.Description.Value = description;
if (i18nData.TryGetValue(food.Id, out var name))
data.Name = name;
if (i18nData.TryGetValue(food.DescriptionId, out var description))
data.Description = description;
}
}
@ -371,8 +463,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
if (lowText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(lowText.Id.Value, out var text))
data.Text.Value = text;
if (i18nData.TryGetValue(lowText.Id, out var text))
data.Text = text;
}
}
@ -382,8 +474,8 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
if (clickText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(clickText.Id.Value, out var text))
data.Text.Value = text;
if (i18nData.TryGetValue(clickText.Id, out var text))
data.Text = text;
}
}
@ -393,10 +485,10 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
if (selectText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(selectText.Id.Value, out var text))
data.Text.Value = text;
if (i18nData.TryGetValue(selectText.ChooseId.Value, out var choose))
data.Choose.Value = choose;
if (i18nData.TryGetValue(selectText.Id, out var text))
data.Text = text;
if (i18nData.TryGetValue(selectText.ChooseId, out var choose))
data.Choose = choose;
}
}
@ -406,18 +498,18 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
{
if (pet.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(pet.Id.Value, out var name))
data.Name.Value = name;
if (i18nData.TryGetValue(pet.PetNameId.Value, out var petName))
data.PetName.Value = petName;
if (i18nData.TryGetValue(pet.DescriptionId.Value, out var description))
data.Description.Value = description;
if (i18nData.TryGetValue(pet.ID, out var name))
data.Name = name;
if (i18nData.TryGetValue(pet.PetNameId, out var petName))
data.PetName = petName;
if (i18nData.TryGetValue(pet.DescriptionId, out var description))
data.Description = description;
foreach (var work in pet.Works)
{
if (work.I18nDatas.TryGetValue(key, out var workData) is false)
continue;
if (i18nData.TryGetValue(work.Id.Value, out var workName))
workData.Name.Value = workName;
if (i18nData.TryGetValue(work.Id, out var workName))
workData.Name = workName;
}
}
}
@ -438,7 +530,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public void Save()
{
SaveTo(SourcePath.Value);
SaveTo(SourcePath);
}
/// <summary>
@ -475,13 +567,13 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
var lps = new LPS()
{
new Line("vupmod", Id.Value)
new Line("vupmod", Id)
{
new Sub("author", Author.Value),
new Sub("gamever", GameVersion.Value),
new Sub("ver", ModVersion.Value)
new Sub("author", Author),
new Sub("gamever", GameVersion),
new Sub("ver", ModVersion)
},
new Line("intro", DescriptionId.Value),
new Line("intro", DescriptionId),
new Line("authorid", AuthorID.ToString()),
new Line("itemid", ItemID.ToString()),
new Line("cachedate", DateTime.Now.Date.ToString("s"))
@ -491,12 +583,12 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(
new Line("lang", cultureName)
{
new Sub(Id.Value, I18nDatas[cultureName].Name.Value),
new Sub(DescriptionId.Value, I18nDatas[cultureName].Description.Value),
new Sub(Id, I18nDatas[cultureName].Name),
new Sub(DescriptionId, I18nDatas[cultureName].Description),
}
);
}
Image.Value?.SaveToPng(Path.Combine(path, "icon.png"));
Image?.SaveToPng(Path.Combine(path, "icon.png"));
File.WriteAllText(modInfoFile, lps.ToString());
}
@ -543,13 +635,9 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(LPSConvert.SerializeObjectToLine<Line>(food.ToFood(), "food"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(food.Id, food.I18nDatas[cultureName].Name);
SaveI18nDatas[cultureName]
.TryAdd(food.Id.Value, food.I18nDatas[cultureName].Name.Value);
SaveI18nDatas[cultureName]
.TryAdd(
food.DescriptionId.Value,
food.I18nDatas[cultureName].Description.Value
);
.TryAdd(food.DescriptionId, food.I18nDatas[cultureName].Description);
}
}
File.WriteAllText(foodFile, lps.ToString());
@ -591,10 +679,9 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToSelectText(), "SelectText"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(text.Id, text.I18nDatas[cultureName].Text);
SaveI18nDatas[cultureName]
.TryAdd(text.Id.Value, text.I18nDatas[cultureName].Text.Value);
SaveI18nDatas[cultureName]
.TryAdd(text.ChooseId.Value, text.I18nDatas[cultureName].Choose.Value);
.TryAdd(text.ChooseId, text.I18nDatas[cultureName].Choose);
}
}
File.WriteAllText(textFile, lps.ToString());
@ -616,8 +703,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToLowText(), "lowfoodtext"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName]
.TryAdd(text.Id.Value, text.I18nDatas[cultureName].Text.Value);
SaveI18nDatas[cultureName].TryAdd(text.Id, text.I18nDatas[cultureName].Text);
}
}
File.WriteAllText(textFile, lps.ToString());
@ -639,8 +725,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToClickText(), "clicktext"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName]
.TryAdd(text.Id.Value, text.I18nDatas[cultureName].Text.Value);
SaveI18nDatas[cultureName].TryAdd(text.Id, text.I18nDatas[cultureName].Text);
}
}
File.WriteAllText(textFile, lps.ToString());
@ -683,7 +768,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
Directory.CreateDirectory(foodPath);
foreach (var food in Foods)
{
food.Image.Value.SaveToPng(Path.Combine(foodPath, food.Id.Value));
food.Image.SaveToPng(Path.Combine(foodPath, food.Id));
}
}
}
@ -693,7 +778,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
public void Close()
{
Image.Value.CloseStream();
Image.CloseStream();
foreach (var food in Foods)
food.Close();
foreach (var pet in Pets)
@ -715,20 +800,39 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
var cultureFile = Path.Combine(culturePath, $"{cultureName}.lps");
File.Create(cultureFile).Close();
var lps = new LPS();
foreach (var data in I18nEditWindow.Current.ViewModel.AllI18nDatas)
lps.Add(
new Line(
data.Key,
data.Value.Datas[I18nHelper.Current.CultureNames.IndexOf(cultureName)].Value
)
);
//TODO
//foreach (var data in I18nEditWindow.Current.ViewModel.AllI18nDatas)
// lps.Add(
// new Line(
// data.Key,
// data.Value.Datas[I18nHelper.Current.CultureNames.IndexOf(cultureName)].Value
// )
// );
File.WriteAllText(cultureFile, lps.ToString());
}
}
}
public class I18nModInfoModel
public class I18nModInfoModel : ObservableObjectX<I18nModInfoModel>
{
public ObservableValue<string> Name { get; set; } = new();
public ObservableValue<string> Description { get; set; } = new();
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty;
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
}

View File

@ -1,10 +1,11 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet_Simulator.Core;
namespace VPet.ModMaker.Models;
@ -12,7 +13,7 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// 移动模型
/// </summary>
public class MoveModel
public class MoveModel : ObservableObjectX<MoveModel>
{
/// <summary>
/// 移动类型
@ -29,93 +30,224 @@ public class MoveModel
public static ObservableCollection<GraphHelper.Move.ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(GraphHelper.Move.ModeType)).Cast<GraphHelper.Move.ModeType>());
//public ObservableValue<string> Id { get; } = new();
//#region Id
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
//private string _Id;
//public string Id { get => _Id; set => SetProperty(ref _Id, value); }
//#endregion
#region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph;
/// <summary>
/// 指定动画
/// </summary>
public ObservableValue<string> Graph { get; } = new();
public string Graph
{
get => _graph;
set => SetProperty(ref _graph, value);
}
#endregion
#region Distance
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _distance;
/// <summary>
/// 移动距离
/// </summary>
public ObservableValue<int> Distance { get; } = new(5);
public int Distance
{
get => _distance;
set => SetProperty(ref _distance, value);
}
#endregion
#region Interval
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _interval;
/// <summary>
/// 间隔
/// </summary>
public ObservableValue<int> Interval { get; } = new(125);
public int Interval
{
get => _interval;
set => SetProperty(ref _interval, value);
}
#endregion
#region LocateLength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _locateLength;
/// <summary>
/// 定位长度
/// </summary>
public ObservableValue<int> LocateLength { get; } = new();
public int LocateLength
{
get => _locateLength;
set => SetProperty(ref _locateLength, value);
}
#endregion
#region SpeedX
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _speedX;
/// <summary>
/// X速度
/// </summary>
public ObservableValue<int> SpeedX { get; } = new();
public int SpeedX
{
get => _speedX;
set => SetProperty(ref _speedX, value);
}
#endregion
#region SpeedY
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _speedY;
/// <summary>
/// Y速度
/// </summary>
public ObservableValue<int> SpeedY { get; } = new();
public int SpeedY
{
get => _speedY;
set => SetProperty(ref _speedY, value);
}
#endregion
#region CheckLeft
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _checkLeft;
/// <summary>
/// 左侧检测距离
/// </summary>
public ObservableValue<int> CheckLeft { get; } = new(100);
public int CheckLeft
{
get => _checkLeft;
set => SetProperty(ref _checkLeft, value);
}
#endregion
#region CheckRight
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _checkRight;
/// <summary>
/// 右侧检测距离
/// </summary>
public ObservableValue<int> CheckRight { get; } = new(100);
public int CheckRight
{
get => _checkRight;
set => SetProperty(ref _checkRight, value);
}
#endregion
#region CheckTop
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _checkTop;
/// <summary>
/// 上方检测距离
/// </summary>
public ObservableValue<int> CheckTop { get; } = new(100);
public int CheckTop
{
get => _checkTop;
set => SetProperty(ref _checkTop, value);
}
#endregion
#region CheckBottom
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _checkBottom;
/// <summary>
/// 下方检测距离
/// </summary>
public ObservableValue<int> CheckBottom { get; } = new(100);
public int CheckBottom
{
get => _checkBottom;
set => SetProperty(ref _checkBottom, value);
}
#endregion
#region TriggerLeft
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _triggerLeft;
/// <summary>
/// 左侧触发距离
/// </summary>
public ObservableValue<int> TriggerLeft { get; } = new(100);
public int TriggerLeft
{
get => _triggerLeft;
set => SetProperty(ref _triggerLeft, value);
}
#endregion
#region TriggerRight
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _triggerRight;
/// <summary>
/// 右侧触发距离
/// </summary>
public ObservableValue<int> TriggerRight { get; } = new(100);
public int TriggerRight
{
get => _triggerRight;
set => SetProperty(ref _triggerRight, value);
}
#endregion
#region TriggerTop
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _triggerTop;
/// <summary>
/// 上方触发距离
/// </summary>
public ObservableValue<int> TriggerTop { get; } = new(100);
public int TriggerTop
{
get => _triggerTop;
set => SetProperty(ref _triggerTop, value);
}
#endregion
#region TriggerBottom
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _triggerBottom;
/// <summary>
/// 下方触发距离
/// </summary>
public ObservableValue<int> TriggerBottom { get; } = new(100);
public int TriggerBottom
{
get => _triggerBottom;
set => SetProperty(ref _triggerBottom, value);
}
#endregion
/// <summary>
/// 定位类型
/// </summary>
public ObservableEnumFlags<GraphHelper.Move.DirectionType> LocateType { get; } =
public ObservableEnumCommand<GraphHelper.Move.DirectionType> LocateType { get; } =
new(GraphHelper.Move.DirectionType.None);
/// <summary>
/// 触发类型
/// </summary>
public ObservableEnumFlags<GraphHelper.Move.DirectionType> TriggerType { get; } =
public ObservableEnumCommand<GraphHelper.Move.DirectionType> TriggerType { get; } =
new(GraphHelper.Move.DirectionType.None);
/// <summary>
/// 模式
/// </summary>
public ObservableEnumFlags<GraphHelper.Move.ModeType> ModeType { get; } =
public ObservableEnumCommand<GraphHelper.Move.ModeType> ModeType { get; } =
new(
GraphHelper.Move.ModeType.Happy
| GraphHelper.Move.ModeType.Nomal
@ -129,69 +261,69 @@ public class MoveModel
: this()
{
//Id.EnumValue = model.Id.EnumValue;
Graph.Value = model.Graph.Value;
Distance.Value = model.Distance.Value;
Interval.Value = model.Interval.Value;
CheckLeft.Value = model.CheckLeft.Value;
CheckRight.Value = model.CheckRight.Value;
CheckTop.Value = model.CheckTop.Value;
CheckBottom.Value = model.CheckBottom.Value;
SpeedX.Value = model.SpeedX.Value;
SpeedY.Value = model.SpeedY.Value;
LocateLength.Value = model.LocateLength.Value;
TriggerLeft.Value = model.TriggerLeft.Value;
TriggerRight.Value = model.TriggerRight.Value;
TriggerTop.Value = model.TriggerTop.Value;
TriggerBottom.Value = model.TriggerBottom.Value;
LocateType.EnumValue.Value = model.LocateType.EnumValue.Value;
TriggerType.EnumValue.Value = model.TriggerType.EnumValue.Value;
ModeType.EnumValue.Value = model.ModeType.EnumValue.Value;
Graph = model.Graph;
Distance = model.Distance;
Interval = model.Interval;
CheckLeft = model.CheckLeft;
CheckRight = model.CheckRight;
CheckTop = model.CheckTop;
CheckBottom = model.CheckBottom;
SpeedX = model.SpeedX;
SpeedY = model.SpeedY;
LocateLength = model.LocateLength;
TriggerLeft = model.TriggerLeft;
TriggerRight = model.TriggerRight;
TriggerTop = model.TriggerTop;
TriggerBottom = model.TriggerBottom;
LocateType.Value = model.LocateType.Value;
TriggerType.Value = model.TriggerType.Value;
ModeType.Value = model.ModeType.Value;
}
public MoveModel(GraphHelper.Move move)
: this()
{
//Id.EnumValue = move.Id.EnumValue;
Graph.Value = move.Graph;
Distance.Value = move.Distance;
Interval.Value = move.Interval;
CheckLeft.Value = move.CheckLeft;
CheckRight.Value = move.CheckRight;
CheckTop.Value = move.CheckTop;
CheckBottom.Value = move.CheckBottom;
SpeedX.Value = move.SpeedX;
SpeedY.Value = move.SpeedY;
LocateLength.Value = move.LocateLength;
TriggerLeft.Value = move.TriggerLeft;
TriggerRight.Value = move.TriggerRight;
TriggerTop.Value = move.TriggerTop;
TriggerBottom.Value = move.TriggerBottom;
LocateType.EnumValue.Value = move.LocateType;
TriggerType.EnumValue.Value = move.TriggerType;
ModeType.EnumValue.Value = move.Mode;
Graph = move.Graph;
Distance = move.Distance;
Interval = move.Interval;
CheckLeft = move.CheckLeft;
CheckRight = move.CheckRight;
CheckTop = move.CheckTop;
CheckBottom = move.CheckBottom;
SpeedX = move.SpeedX;
SpeedY = move.SpeedY;
LocateLength = move.LocateLength;
TriggerLeft = move.TriggerLeft;
TriggerRight = move.TriggerRight;
TriggerTop = move.TriggerTop;
TriggerBottom = move.TriggerBottom;
LocateType.Value = move.LocateType;
TriggerType.Value = move.TriggerType;
ModeType.Value = move.Mode;
}
public GraphHelper.Move ToMove()
{
return new()
{
Graph = Graph.Value,
Distance = Distance.Value,
Interval = Interval.Value,
CheckLeft = CheckLeft.Value,
CheckRight = CheckRight.Value,
CheckTop = CheckTop.Value,
CheckBottom = CheckBottom.Value,
SpeedX = SpeedX.Value,
SpeedY = SpeedY.Value,
LocateLength = LocateLength.Value,
TriggerLeft = TriggerLeft.Value,
TriggerRight = TriggerRight.Value,
TriggerTop = TriggerTop.Value,
TriggerBottom = TriggerBottom.Value,
LocateType = LocateType.EnumValue.Value,
TriggerType = TriggerType.EnumValue.Value,
Mode = ModeType.EnumValue.Value,
Graph = Graph,
Distance = Distance,
Interval = Interval,
CheckLeft = CheckLeft,
CheckRight = CheckRight,
CheckTop = CheckTop,
CheckBottom = CheckBottom,
SpeedX = SpeedX,
SpeedY = SpeedY,
LocateLength = LocateLength,
TriggerLeft = TriggerLeft,
TriggerRight = TriggerRight,
TriggerTop = TriggerTop,
TriggerBottom = TriggerBottom,
LocateType = LocateType.Value,
TriggerType = TriggerType.Value,
Mode = ModeType.Value,
};
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -24,56 +25,123 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
public static PetModel Default { get; } = new();
#region FromMain
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _fromMain;
/// <summary>
/// 来自本体
/// </summary>
public ObservableValue<bool> FromMain { get; } = new(false);
public bool FromMain
{
get => _fromMain;
set => SetProperty(ref _fromMain, value);
}
#endregion
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region PetNameId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _petNameId;
/// <summary>
/// 名称Id
/// </summary>
public ObservableValue<string> PetNameId { get; } = new();
public string PetNameId
{
get => _petNameId;
set => SetProperty(ref _petNameId, value);
}
#endregion
#region DescriptionId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId;
/// <summary>
/// 描述Id
/// </summary>
public ObservableValue<string> DescriptionId { get; } = new();
public string DescriptionId
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
}
#endregion
#region TouchHeadRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchHeadRect = new(159, 16, 189, 178);
/// <summary>
/// 头部点击区域
/// </summary>
public ObservableValue<ObservableRect<double>> TouchHeadRect { get; } =
new(new(159, 16, 189, 178));
public ObservableRectangleLocation<double> TouchHeadRect
{
get => _touchHeadRect;
set => SetProperty(ref _touchHeadRect, value);
}
#endregion
#region TouchBodyRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _touchBodyRect = new(166, 206, 163, 136);
/// <summary>
/// 身体区域
/// </summary>
public ObservableValue<ObservableRect<double>> TouchBodyRect { get; } =
new(new(166, 206, 163, 136));
public ObservableRectangleLocation<double> TouchBodyRect
{
get => _touchBodyRect;
set => SetProperty(ref _touchBodyRect, value);
}
#endregion
/// <summary>
/// 提起区域
/// </summary>
public ObservableValue<ObservableMultiStateRect> TouchRaisedRect { get; } =
#region TouchRaisedRect
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStateRect _touchRaisedRect =
new(
new(
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 200, 500, 300)
)
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 50, 500, 200),
new(0, 200, 500, 300)
);
public ObservableMultiStateRect TouchRaisedRect
{
get => _touchRaisedRect;
set => SetProperty(ref _touchRaisedRect, value);
}
#endregion
#region RaisePoint
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableMultiStatePoint _raisePoint =
new(new(290, 128), new(290, 128), new(290, 128), new(225, 115));
/// <summary>
/// 提起定位
/// </summary>
public ObservableValue<ObservableMultiStatePoint> RaisePoint { get; } =
new(new(new(290, 128), new(290, 128), new(290, 128), new(225, 115)));
public ObservableMultiStatePoint RaisePoint
{
get => _raisePoint;
set => SetProperty(ref _raisePoint, value);
}
#endregion
/// <summary>
/// 工作
@ -95,97 +163,107 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// </summary>
public ObservableCollection<FoodAnimeTypeModel> FoodAnimes { get; } = new();
public ObservableValue<int> AnimeCount { get; } = new();
#region AnimeCount
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _AnimeCount;
public int AnimeCount
{
get => _AnimeCount;
set => SetProperty(ref _AnimeCount, value);
}
#endregion
public PetModel()
{
PetNameId.Value = $"{Id.Value}_{nameof(PetNameId)}";
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
Id.ValueChanged += (s, e) =>
{
PetNameId.Value = $"{e.NewValue}_{nameof(PetNameId)}";
DescriptionId.Value = $"{e.NewValue}_{nameof(DescriptionId)}";
};
AnimeCount.AddNotifySender(Animes);
AnimeCount.AddNotifySender(FoodAnimes);
AnimeCount.SenderPropertyChanged += (s, _) =>
{
s.Value = Animes.Count + FoodAnimes.Count;
};
PetNameId = $"{ID}_{nameof(PetNameId)}";
DescriptionId = $"{ID}_{nameof(DescriptionId)}";
//TODO
//ID.ValueChanged += (s, e) =>
//{
// PetNameId = $"{e.NewValue}_{nameof(PetNameId)}";
// DescriptionId = $"{e.NewValue}_{nameof(DescriptionId)}";
//};
//AnimeCount.AddNotifySender(Animes);
//AnimeCount.AddNotifySender(FoodAnimes);
//AnimeCount.SenderPropertyChanged += (s, _) =>
//{
// s.Value = Animes.Count + FoodAnimes.Count;
//};
}
public PetModel(PetModel model)
: this()
{
Id.Value = model.Id.Value;
PetNameId.Value = model.PetNameId.Value;
TouchHeadRect.Value = model.TouchHeadRect.Value.Copy();
TouchBodyRect.Value = model.TouchBodyRect.Value.Copy();
TouchRaisedRect.Value = model.TouchRaisedRect.Value.Copy();
RaisePoint.Value = model.RaisePoint.Value.Copy();
ID = model.ID;
PetNameId = model.PetNameId;
TouchHeadRect = model.TouchHeadRect.Clone();
TouchBodyRect = model.TouchBodyRect.Clone();
TouchRaisedRect = model.TouchRaisedRect.Copy();
RaisePoint = model.RaisePoint.Copy();
foreach (var work in model.Works)
Works.Add(work);
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public PetModel(PetLoader loader, bool fromMain = false)
: this()
{
Id.Value = loader.Name;
PetNameId.Value = loader.PetName;
DescriptionId.Value = loader.Intor;
ID = loader.Name;
PetNameId = loader.PetName;
DescriptionId = loader.Intor;
TouchHeadRect.Value = new(
TouchHeadRect = new(
loader.Config.TouchHeadLocate.X,
loader.Config.TouchHeadLocate.Y,
loader.Config.TouchHeadSize.Width,
loader.Config.TouchHeadSize.Height
);
TouchBodyRect.Value = new(
TouchBodyRect = new(
loader.Config.TouchBodyLocate.X,
loader.Config.TouchBodyLocate.Y,
loader.Config.TouchBodySize.Width,
loader.Config.TouchBodySize.Height
);
TouchRaisedRect.Value.Happy = new(
TouchRaisedRect.Happy = new(
loader.Config.TouchRaisedLocate[0].X,
loader.Config.TouchRaisedLocate[0].Y,
loader.Config.TouchRaisedSize[0].Width,
loader.Config.TouchRaisedSize[0].Height
);
TouchRaisedRect.Value.Nomal = new(
TouchRaisedRect.Nomal = new(
loader.Config.TouchRaisedLocate[1].X,
loader.Config.TouchRaisedLocate[1].Y,
loader.Config.TouchRaisedSize[1].Width,
loader.Config.TouchRaisedSize[1].Height
);
TouchRaisedRect.Value.PoorCondition = new(
TouchRaisedRect.PoorCondition = new(
loader.Config.TouchRaisedLocate[2].X,
loader.Config.TouchRaisedLocate[2].Y,
loader.Config.TouchRaisedSize[2].Width,
loader.Config.TouchRaisedSize[2].Height
);
TouchRaisedRect.Value.Ill = new(
TouchRaisedRect.Ill = new(
loader.Config.TouchRaisedLocate[3].X,
loader.Config.TouchRaisedLocate[3].Y,
loader.Config.TouchRaisedSize[3].Width,
loader.Config.TouchRaisedSize[3].Height
);
RaisePoint.Value.Happy = new(loader.Config.RaisePoint[0].X, loader.Config.RaisePoint[0].Y);
RaisePoint.Value.Nomal = new(loader.Config.RaisePoint[1].X, loader.Config.RaisePoint[1].Y);
RaisePoint.Value.PoorCondition = new(
RaisePoint.Happy = new(loader.Config.RaisePoint[0].X, loader.Config.RaisePoint[0].Y);
RaisePoint.Nomal = new(loader.Config.RaisePoint[1].X, loader.Config.RaisePoint[1].Y);
RaisePoint.PoorCondition = new(
loader.Config.RaisePoint[2].X,
loader.Config.RaisePoint[2].Y
);
RaisePoint.Value.Ill = new(loader.Config.RaisePoint[3].X, loader.Config.RaisePoint[3].Y);
RaisePoint.Ill = new(loader.Config.RaisePoint[3].X, loader.Config.RaisePoint[3].Y);
// 如果这个宠物数据来自本体, 则不载入 Work 和 Move
if (FromMain.Value = fromMain)
if (FromMain = fromMain)
return;
foreach (var work in loader.Config.Works)
@ -196,8 +274,8 @@ public class PetModel : I18nModel<I18nPetInfoModel>
public void RefreshId()
{
PetNameId.Value = $"{Id.Value}_{nameof(PetNameId)}";
DescriptionId.Value = $"{Id.Value}_{nameof(DescriptionId)}";
PetNameId = $"{ID}_{nameof(PetNameId)}";
DescriptionId = $"{ID}_{nameof(DescriptionId)}";
}
public void Close()
@ -217,7 +295,7 @@ public class PetModel : I18nModel<I18nPetInfoModel>
public bool CanSave()
{
if (
FromMain.Value
FromMain
&& Works.Count == 0
&& Moves.Count == 0
&& Animes.Count == 0
@ -235,22 +313,20 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(Id.Value, I18nDatas[cultureName].Name.Value);
.TryAdd(PetNameId, I18nDatas[cultureName].PetName);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(PetNameId.Value, I18nDatas[cultureName].PetName.Value);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(DescriptionId.Value, I18nDatas[cultureName].Description.Value);
.TryAdd(DescriptionId, I18nDatas[cultureName].Description);
}
var petFile = Path.Combine(path, $"{Id.Value}.lps");
var petFile = Path.Combine(path, $"{ID}.lps");
if (File.Exists(petFile) is false)
File.Create(petFile).Close();
var lps = new LPS();
// 如果本体中存在相同的宠物, 则只保存差异信息
if (ModMakerInfo.MainPets.TryGetValue(Id.Value, out var mainPet))
if (ModMakerInfo.MainPets.TryGetValue(ID, out var mainPet))
SaveDifferentPetInfo(lps, mainPet);
else
SavePetInfo(lps);
@ -264,7 +340,7 @@ public class PetModel : I18nModel<I18nPetInfoModel>
private void SaveAnime(string path)
{
var petAnimePath = Path.Combine(path, Id.Value);
var petAnimePath = Path.Combine(path, ID);
foreach (var anime in Animes)
anime.Save(petAnimePath);
foreach (var anime in FoodAnimes)
@ -298,7 +374,7 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(work.Id.Value, work.I18nDatas[cultureName].Name.Value);
.TryAdd(work.Id, work.I18nDatas[cultureName].Name);
}
}
}
@ -345,11 +421,11 @@ public class PetModel : I18nModel<I18nPetInfoModel>
private void SavePetBasicInfo(LPS lps)
{
lps.Add(
new Line("pet", Id.Value)
new Line("pet", ID)
{
new Sub("intor", DescriptionId.Value),
new Sub("path", Id.Value),
new Sub("petname", PetNameId.Value)
new Sub("intor", DescriptionId),
new Sub("path", ID),
new Sub("petname", PetNameId)
}
);
}
@ -359,10 +435,10 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("touchhead")
{
new Sub("px", TouchHeadRect.Value.X),
new Sub("py", TouchHeadRect.Value.Y),
new Sub("sw", TouchHeadRect.Value.Width),
new Sub("sh", TouchHeadRect.Value.Height),
new Sub("px", TouchHeadRect.X),
new Sub("py", TouchHeadRect.Y),
new Sub("sw", TouchHeadRect.Width),
new Sub("sh", TouchHeadRect.Height),
}
);
}
@ -372,10 +448,10 @@ public class PetModel : I18nModel<I18nPetInfoModel>
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),
new Sub("px", TouchBodyRect.X),
new Sub("py", TouchBodyRect.Y),
new Sub("sw", TouchBodyRect.Width),
new Sub("sh", TouchBodyRect.Height),
}
);
}
@ -385,25 +461,25 @@ public class PetModel : I18nModel<I18nPetInfoModel>
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("happy_px", TouchRaisedRect.Happy.X),
new Sub("happy_py", TouchRaisedRect.Happy.Y),
new Sub("happy_sw", TouchRaisedRect.Happy.Width),
new Sub("happy_sh", TouchRaisedRect.Happy.Height),
//
new Sub("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("nomal_px", TouchRaisedRect.Nomal.X),
new Sub("nomal_py", TouchRaisedRect.Nomal.Y),
new Sub("nomal_sw", TouchRaisedRect.Nomal.Width),
new Sub("nomal_sh", TouchRaisedRect.Nomal.Height),
//
new Sub("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("poorcondition_px", TouchRaisedRect.PoorCondition.X),
new Sub("poorcondition_py", TouchRaisedRect.PoorCondition.Y),
new Sub("poorcondition_sw", TouchRaisedRect.PoorCondition.Width),
new Sub("poorcondition_sh", TouchRaisedRect.PoorCondition.Height),
//
new Sub("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),
new Sub("ill_px", TouchRaisedRect.Ill.X),
new Sub("ill_py", TouchRaisedRect.Ill.Y),
new Sub("ill_sw", TouchRaisedRect.Ill.Width),
new Sub("ill_sh", TouchRaisedRect.Ill.Height),
}
);
}
@ -413,17 +489,17 @@ public class PetModel : I18nModel<I18nPetInfoModel>
lps.Add(
new Line("raisepoint")
{
new Sub("happy_x", RaisePoint.Value.Happy.X),
new Sub("happy_y", RaisePoint.Value.Happy.Y),
new Sub("happy_x", RaisePoint.Happy.X),
new Sub("happy_y", RaisePoint.Happy.Y),
//
new Sub("nomal_x", RaisePoint.Value.Nomal.X),
new Sub("nomal_y", RaisePoint.Value.Nomal.Y),
new Sub("nomal_x", RaisePoint.Nomal.X),
new Sub("nomal_y", RaisePoint.Nomal.Y),
//
new Sub("poorcondition_x", RaisePoint.Value.PoorCondition.X),
new Sub("poorcondition_y", RaisePoint.Value.PoorCondition.Y),
new Sub("poorcondition_x", RaisePoint.PoorCondition.X),
new Sub("poorcondition_y", RaisePoint.PoorCondition.Y),
//
new Sub("ill_x", RaisePoint.Value.Ill.X),
new Sub("ill_y", RaisePoint.Value.Ill.Y),
new Sub("ill_x", RaisePoint.Ill.X),
new Sub("ill_y", RaisePoint.Ill.Y),
}
);
}
@ -431,50 +507,93 @@ public class PetModel : I18nModel<I18nPetInfoModel>
#endregion
}
public class I18nPetInfoModel
public class I18nPetInfoModel : ObservableObjectX<I18nPetInfoModel>
{
public ObservableValue<string> Name { get; } = new();
public ObservableValue<string> PetName { get; } = new();
public ObservableValue<string> Description { get; } = new();
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region PetName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _petName = string.Empty;
public string PetName
{
get => _petName;
set => SetProperty(ref _petName, value);
}
#endregion
#region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty;
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
public I18nPetInfoModel Copy()
{
var result = new I18nPetInfoModel();
result.Name.Value = Name.Value;
result.PetName.Value = PetName.Value;
result.Description.Value = Description.Value;
result.Name = Name;
result.PetName = PetName;
result.Description = Description;
return result;
}
}
public class ObservableMultiStateRect
: ObservableClass<ObservableMultiStateRect>,
: ObservableObjectX<ObservableMultiStateRect>,
IEquatable<ObservableMultiStateRect>
{
private ObservableRect<double> _happy;
public ObservableRect<double> Happy
#region Happy
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _happy;
public ObservableRectangleLocation<double> Happy
{
get => _happy;
set => SetProperty(ref _happy, value);
}
private ObservableRect<double> _nomal;
public ObservableRect<double> Nomal
#endregion
#region Nomal
private ObservableRectangleLocation<double> _nomal;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public ObservableRectangleLocation<double> Nomal
{
get => _nomal;
set => SetProperty(ref _nomal, value);
}
private ObservableRect<double> _poorCondition;
public ObservableRect<double> PoorCondition
#endregion
#region PoorCondition
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _poorCondition;
public ObservableRectangleLocation<double> PoorCondition
{
get => _poorCondition;
set => SetProperty(ref _poorCondition, value);
}
private ObservableRect<double> _ill;
public ObservableRect<double> Ill
#endregion
#region Ill
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableRectangleLocation<double> _ill;
public ObservableRectangleLocation<double> Ill
{
get => _ill;
set => SetProperty(ref _ill, value);
}
#endregion
public ObservableMultiStateRect()
{
@ -485,10 +604,10 @@ public class ObservableMultiStateRect
}
public ObservableMultiStateRect(
ObservableRect<double> happy,
ObservableRect<double> nomal,
ObservableRect<double> poorCondition,
ObservableRect<double> ill
ObservableRectangleLocation<double> happy,
ObservableRectangleLocation<double> nomal,
ObservableRectangleLocation<double> poorCondition,
ObservableRectangleLocation<double> ill
)
{
Happy = happy;
@ -501,10 +620,10 @@ public class ObservableMultiStateRect
{
return new()
{
Happy = Happy.Copy(),
Nomal = Nomal.Copy(),
PoorCondition = PoorCondition.Copy(),
Ill = Ill.Copy(),
Happy = Happy.Clone(),
Nomal = Nomal.Clone(),
PoorCondition = PoorCondition.Clone(),
Ill = Ill.Clone(),
};
}
@ -520,13 +639,19 @@ public class ObservableMultiStateRect
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(
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
Happy,
temp.Happy
)
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
Nomal,
temp.Nomal
)
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(
PoorCondition,
temp.PoorCondition
)
&& EqualityComparer<ObservableRect<double>>.Default.Equals(Ill, temp.Ill);
&& EqualityComparer<ObservableRectangleLocation<double>>.Default.Equals(Ill, temp.Ill);
}
/// <inheritdoc/>
@ -551,34 +676,48 @@ public class ObservableMultiStateRect
}
public class ObservableMultiStatePoint
: ObservableClass<ObservableMultiStatePoint>,
: ObservableObjectX<ObservableMultiStatePoint>,
IEquatable<ObservableMultiStatePoint>
{
#region Happy
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _happy;
public ObservablePoint<double> Happy
{
get => _happy;
set => SetProperty(ref _happy, value);
}
#endregion
#region Nomal
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _nomal;
public ObservablePoint<double> Nomal
{
get => _nomal;
set => SetProperty(ref _nomal, value);
}
#endregion
#region PoorCondition
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _poorCondition;
public ObservablePoint<double> PoorCondition
{
get => _poorCondition;
set => SetProperty(ref _poorCondition, value);
}
#endregion
#region Ill
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservablePoint<double> _ill;
public ObservablePoint<double> Ill
{
get => _ill;
set => SetProperty(ref _ill, value);
}
#endregion
public ObservableMultiStatePoint()
{
Happy = new();
@ -604,10 +743,10 @@ public class ObservableMultiStatePoint
{
return new()
{
Happy = Happy.Copy(),
Nomal = Nomal.Copy(),
PoorCondition = PoorCondition.Copy(),
Ill = Ill.Copy(),
Happy = Happy.Clone(),
Nomal = Nomal.Clone(),
PoorCondition = PoorCondition.Clone(),
Ill = Ill.Clone(),
};
}

View File

@ -1,11 +1,11 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet.ModMaker.Models;
using VPet_Simulator.Windows.Interface;
@ -21,30 +21,67 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
/// </summary>
public static ObservableCollection<ClickText.ModeType> ModeTypes => ClickTextModel.ModeTypes;
#region Tags
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _tags = string.Empty;
/// <summary>
/// 标签
/// </summary>
public ObservableValue<string> Tags { get; } = new();
public string Tags
{
get => _tags;
set => SetProperty(ref _tags, value);
}
#endregion
#region ToTags
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _toTags = string.Empty;
/// <summary>
/// 跳转标签
/// </summary>
public ObservableValue<string> ToTags { get; } = new();
public string ToTags
{
get => _toTags;
set => SetProperty(ref _toTags, value);
}
#endregion
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region ChooseId
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _chooseId = string.Empty;
/// <summary>
/// 选择Id
/// </summary>
public ObservableValue<string> ChooseId { get; } = new();
public string ChooseId
{
get => _chooseId;
set => SetProperty(ref _chooseId, value);
}
#endregion
/// <summary>
/// 宠物状态
/// </summary>
public ObservableEnumFlags<ClickText.ModeType> Mode { get; } =
public ObservableEnumCommand<ClickText.ModeType> Mode { get; } =
new(
ClickText.ModeType.Happy
| ClickText.ModeType.Nomal
@ -94,42 +131,43 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
public SelectTextModel()
{
ChooseId.Value = $"{Id.Value}_{nameof(ChooseId)}";
Id.ValueChanged += (s, e) =>
{
ChooseId.Value = $"{e.NewValue}_{nameof(ChooseId)}";
};
ChooseId = $"{Id}_{nameof(ChooseId)}";
//TODO
//Id.ValueChanged += (s, e) =>
//{
// ChooseId.Value = $"{e.NewValue}_{nameof(ChooseId)}";
//};
}
public SelectTextModel(SelectTextModel model)
: this()
{
Id.Value = model.Id.Value;
Mode.EnumValue.Value = model.Mode.EnumValue.Value;
Tags.Value = model.Tags.Value;
ToTags.Value = model.ToTags.Value;
Like = model.Like.Copy();
Health = model.Health.Copy();
Level = model.Level.Copy();
Money = model.Money.Copy();
Food = model.Food.Copy();
Drink = model.Drink.Copy();
Feel = model.Feel.Copy();
Strength = model.Strength.Copy();
Id = model.Id;
Mode.Value = model.Mode.Value;
Tags = model.Tags;
ToTags = model.ToTags;
Like = model.Like.Clone();
Health = model.Health.Clone();
Level = model.Level.Clone();
Money = model.Money.Clone();
Food = model.Food.Clone();
Drink = model.Drink.Clone();
Feel = model.Feel.Clone();
Strength = model.Strength.Clone();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public SelectTextModel(SelectText text)
: this()
{
Id.Value = text.Text;
ChooseId.Value = text.Choose ?? string.Empty;
Mode.EnumValue.Value = text.Mode;
Tags.Value = text.Tags is null ? string.Empty : string.Join(", ", text.Tags);
ToTags.Value = text.ToTags is null ? string.Empty : string.Join(", ", text.ToTags);
Id = text.Text;
ChooseId = text.Choose ?? string.Empty;
Mode.Value = text.Mode;
Tags = text.Tags is null ? string.Empty : string.Join(", ", text.Tags);
ToTags = text.ToTags is null ? string.Empty : string.Join(", ", text.ToTags);
Like = new(text.LikeMin, text.LikeMax);
Health = new(text.HealthMin, text.HealthMax);
Level = new(text.LevelMin, text.LevelMax);
@ -142,20 +180,20 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
public void RefreshId()
{
ChooseId.Value = $"{Id.Value}_{nameof(ChooseId)}";
ChooseId = $"{Id}_{nameof(ChooseId)}";
}
private readonly static char[] rs_splitChar = { ',', ' ' };
private static readonly char[] rs_splitChar = { ',', ' ' };
public SelectText ToSelectText()
{
return new()
{
Text = Id.Value,
Choose = ChooseId.Value,
Mode = Mode.EnumValue.Value,
Tags = new(Tags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
ToTags = new(ToTags.Value.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
Text = Id,
Choose = ChooseId,
Mode = Mode.Value,
Tags = new(Tags.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
ToTags = new(ToTags.Split(rs_splitChar, StringSplitOptions.RemoveEmptyEntries)),
LikeMax = Like.Max,
LikeMin = Like.Min,
HealthMin = Health.Min,
@ -176,16 +214,34 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
}
}
public class I18nSelectTextModel
public class I18nSelectTextModel : ObservableObjectX<I18nSelectTextModel>
{
public ObservableValue<string> Choose { get; } = new();
public ObservableValue<string> Text { get; } = new();
#region Choose
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _choose = string.Empty;
public string Choose
{
get => _choose;
set => SetProperty(ref _choose, value);
}
#endregion
#region Text
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _text = string.Empty;
public string Text
{
get => _text;
set => SetProperty(ref _text, value);
}
#endregion
public I18nSelectTextModel Copy()
{
var result = new I18nSelectTextModel();
result.Text.Value = Text.Value;
result.Choose.Value = Choose.Value;
result.Text = Text;
result.Choose = Choose;
return result;
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -24,237 +25,430 @@ public class WorkModel : I18nModel<I18nWorkModel>
.Cast<VPet_Simulator.Core.GraphHelper.Work.WorkType>()
);
#region Id
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id;
/// <summary>
/// Id
/// </summary>
public ObservableValue<string> Id { get; } = new();
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph;
/// <summary>
/// 指定动画
/// </summary>
public ObservableValue<string> Graph { get; } = new();
/// <summary>
/// 收获倍率
/// </summary>
//public ObservableValue<double> MoneyLevel { get; } = new();
public string Graph
{
get => _graph;
set => SetProperty(ref _graph, value);
}
#endregion
//#region MoneyLevel
//[DebuggerBrowsable(DebuggerBrowsableState.Never)]
//private double _moneyLevel;
///// <summary>
///// 收获倍率
///// </summary>
//public double MoneyLevel
//{
// get => _moneyLevel;
// set => SetProperty(ref _moneyLevel, value);
//}
//#endregion
#region MoneyBase
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _moneyBase;
/// <summary>
/// 收获基础
/// </summary>
public ObservableValue<double> MoneyBase { get; } = new();
public double MoneyBase
{
get => _moneyBase;
set => SetProperty(ref _moneyBase, value);
}
#endregion
#region StrengthFood
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _strengthFood;
/// <summary>
/// 饱食度消耗
/// </summary>
public ObservableValue<double> StrengthFood { get; } = new();
public double StrengthFood
{
get => _strengthFood;
set => SetProperty(ref _strengthFood, value);
}
#endregion
#region StrengthDrink
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _strengthDrink;
/// <summary>
/// 口渴度消耗
/// </summary>
public ObservableValue<double> StrengthDrink { get; } = new();
public double StrengthDrink
{
get => _strengthDrink;
set => SetProperty(ref _strengthDrink, value);
}
#endregion
#region Feeling
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _feeling;
/// <summary>
/// 心情消耗
/// </summary>
public ObservableValue<double> Feeling { get; } = new();
public double Feeling
{
get => _feeling;
set => SetProperty(ref _feeling, value);
}
#endregion
#region LevelLimit
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _levelLimit;
/// <summary>
/// 等级倍率
/// </summary>
public ObservableValue<int> LevelLimit { get; } = new();
public int LevelLimit
{
get => _levelLimit;
set => SetProperty(ref _levelLimit, value);
}
#endregion
#region Time
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int _time;
/// <summary>
/// 时间
/// </summary>
public ObservableValue<int> Time { get; } = new();
public int Time
{
get => _time;
set => SetProperty(ref _time, value);
}
#endregion
#region FinishBonus
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _finishBonus;
/// <summary>
/// 完成奖励倍率
/// </summary>
public ObservableValue<double> FinishBonus { get; } = new();
public double FinishBonus
{
get => _finishBonus;
set => SetProperty(ref _finishBonus, value);
}
#endregion
#region IsOverLoad
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _isOverLoad;
/// <summary>
/// 是否超模
/// </summary>
public ObservableValue<bool> IsOverLoad { get; } = new();
public bool IsOverLoad
{
get => _isOverLoad;
set => SetProperty(ref _isOverLoad, value);
}
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
/// <summary>
/// 图片
/// </summary>
public ObservableValue<BitmapImage> Image { get; } = new();
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#region WorkType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private VPet_Simulator.Core.GraphHelper.Work.WorkType _workType;
/// <summary>
/// 类型
/// 工作类型
/// </summary>
public ObservableValue<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkType { get; } =
new(VPet_Simulator.Core.GraphHelper.Work.WorkType.Work);
public VPet_Simulator.Core.GraphHelper.Work.WorkType WorkType
{
get => _workType;
set => SetProperty(ref _workType, value);
}
#endregion
#region BorderBrush
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _borderBrush =
new((Color)ColorConverter.ConvertFromString("#FF0290D5"));
/// <summary>
/// 边框颜色
/// </summary>
public ObservableValue<SolidColorBrush> BorderBrush { get; } =
new(new((Color)ColorConverter.ConvertFromString("#FF0290D5")));
public SolidColorBrush BorderBrush
{
get => _borderBrush;
set => SetProperty(ref _borderBrush, value);
}
#endregion
/// <summary>
/// 背景色
/// </summary>
public ObservableValue<SolidColorBrush> Background { get; } =
new(new((Color)ColorConverter.ConvertFromString("#FF81D4FA")));
#region Background
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _background = new((Color)ColorConverter.ConvertFromString("#FF81D4FA"));
public SolidColorBrush Background
{
get => _background;
set => SetProperty(ref _background, value);
}
#endregion
/// <summary>
/// 前景色
/// </summary>
public ObservableValue<SolidColorBrush> Foreground { get; } =
new(new((Color)ColorConverter.ConvertFromString("#FF0286C6")));
#region Foreground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _foreground = new((Color)ColorConverter.ConvertFromString("#FF0286C6"));
public SolidColorBrush Foreground
{
get => _foreground;
set => SetProperty(ref _foreground, value);
}
#endregion
/// <summary>
/// 按钮背景色
/// </summary>
public ObservableValue<SolidColorBrush> ButtonBackground { get; } =
new(new((Color)ColorConverter.ConvertFromString("#AA0286C6")));
#region ButtonBackground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _buttonBackground =
new((Color)ColorConverter.ConvertFromString("#AA0286C6"));
public SolidColorBrush ButtonBackground
{
get => _buttonBackground;
set => SetProperty(ref _buttonBackground, value);
}
#endregion
/// <summary>
/// 按钮前景色
/// </summary>
public ObservableValue<SolidColorBrush> ButtonForeground { get; } =
new(new((Color)ColorConverter.ConvertFromString("#FFFFFFFF")));
#region ButtonForeground
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SolidColorBrush _buttonForeground;
public SolidColorBrush ButtonForeground
{
get => _buttonForeground;
set => SetProperty(ref _buttonForeground, value);
}
#endregion
/// <summary>
/// X位置
/// </summary>
public ObservableValue<double> Left { get; } = new(100);
#region Left
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Left;
public double Left
{
get => _Left;
set => SetProperty(ref _Left, value);
}
#endregion
/// <summary>
/// Y位置
/// </summary>
public ObservableValue<double> Top { get; } = new(160);
#region Top
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Top;
public double Top
{
get => _Top;
set => SetProperty(ref _Top, value);
}
#endregion
/// <summary>
/// 宽度
/// </summary>
public ObservableValue<double> Width { get; } = new(300);
#region Width
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _Width;
public double Width
{
get => _Width;
set => SetProperty(ref _Width, value);
}
#endregion
public WorkModel()
{
IsOverLoad.AddNotifySender(
WorkType,
MoneyBase,
//MoneyLevel,
StrengthFood,
StrengthDrink,
Feeling,
LevelLimit,
FinishBonus
);
IsOverLoad.SenderPropertyChanged += (s, _) =>
{
s.Value = VPet_Simulator.Windows.Interface.ExtensionFunction.IsOverLoad(ToWork());
};
{ //TODO
//IsOverLoad.AddNotifySender(
// WorkType,
// MoneyBase,
// //MoneyLevel,
// StrengthFood,
// StrengthDrink,
// Feeling,
// LevelLimit,
// FinishBonus
//);
//IsOverLoad.SenderPropertyChanged += (s, _) =>
//{
// s.Value = VPet_Simulator.Windows.Interface.ExtensionFunction.IsOverLoad(ToWork());
//};
}
public WorkModel(WorkModel model)
: this()
{
WorkType.Value = model.WorkType.Value;
Id.Value = model.Id.Value;
Graph.Value = model.Graph.Value;
//MoneyLevel.Value = model.MoneyLevel.Value;
MoneyBase.Value = model.MoneyBase.Value;
StrengthFood.Value = model.StrengthFood.Value;
StrengthDrink.Value = model.StrengthDrink.Value;
Feeling.Value = model.Feeling.Value;
LevelLimit.Value = model.LevelLimit.Value;
Time.Value = model.Time.Value;
FinishBonus.Value = model.FinishBonus.Value;
WorkType = model.WorkType;
Id = model.Id;
Graph = model.Graph;
//MoneyLevel = model.MoneyLevel;
MoneyBase = model.MoneyBase;
StrengthFood = model.StrengthFood;
StrengthDrink = model.StrengthDrink;
Feeling = model.Feeling;
LevelLimit = model.LevelLimit;
Time = model.Time;
FinishBonus = model.FinishBonus;
BorderBrush.Value = model.BorderBrush.Value;
Background.Value = model.Background.Value;
ButtonBackground.Value = model.ButtonBackground.Value;
ButtonForeground.Value = model.ButtonForeground.Value;
Foreground.Value = model.Foreground.Value;
Left.Value = model.Left.Value;
Top.Value = model.Top.Value;
Width.Value = model.Width.Value;
BorderBrush = model.BorderBrush;
Background = model.Background;
ButtonBackground = model.ButtonBackground;
ButtonForeground = model.ButtonForeground;
Foreground = model.Foreground;
Left = model.Left;
Top = model.Top;
Width = model.Width;
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Copy();
CurrentI18nData.Value = I18nDatas[I18nHelper.Current.CultureName.Value];
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
public WorkModel(VPet_Simulator.Core.GraphHelper.Work work)
: this()
{
WorkType.Value = work.Type;
Id.Value = work.Name;
Graph.Value = work.Graph;
//MoneyLevel.Value = work.MoneyLevel;
MoneyBase.Value = work.MoneyBase;
StrengthFood.Value = work.StrengthFood;
StrengthDrink.Value = work.StrengthDrink;
Feeling.Value = work.Feeling;
LevelLimit.Value = work.LevelLimit;
Time.Value = work.Time;
FinishBonus.Value = work.FinishBonus;
WorkType = work.Type;
Id = work.Name;
Graph = work.Graph;
//MoneyLevel = work.MoneyLevel;
MoneyBase = work.MoneyBase;
StrengthFood = work.StrengthFood;
StrengthDrink = work.StrengthDrink;
Feeling = work.Feeling;
LevelLimit = work.LevelLimit;
Time = work.Time;
FinishBonus = work.FinishBonus;
BorderBrush.Value = new((Color)ColorConverter.ConvertFromString("#FF" + work.BorderBrush));
Background.Value = new((Color)ColorConverter.ConvertFromString("#FF" + work.Background));
Foreground.Value = new((Color)ColorConverter.ConvertFromString("#FF" + work.Foreground));
ButtonBackground.Value = new(
BorderBrush = new((Color)ColorConverter.ConvertFromString("#FF" + work.BorderBrush));
Background = new((Color)ColorConverter.ConvertFromString("#FF" + work.Background));
Foreground = new((Color)ColorConverter.ConvertFromString("#FF" + work.Foreground));
ButtonBackground = new(
(Color)ColorConverter.ConvertFromString("#AA" + work.ButtonBackground)
);
ButtonForeground.Value = new(
ButtonForeground = new(
(Color)ColorConverter.ConvertFromString("#FF" + work.ButtonForeground)
);
Left.Value = work.Left;
Top.Value = work.Top;
Width.Value = work.Width;
Left = work.Left;
Top = work.Top;
Width = work.Width;
}
public VPet_Simulator.Core.GraphHelper.Work ToWork()
{
return new()
{
Type = WorkType.Value,
Name = Id.Value,
Graph = Graph.Value,
//MoneyLevel = MoneyLevel.Value,
MoneyBase = MoneyBase.Value,
StrengthFood = StrengthFood.Value,
StrengthDrink = StrengthDrink.Value,
Feeling = Feeling.Value,
LevelLimit = LevelLimit.Value,
Time = Time.Value,
FinishBonus = FinishBonus.Value,
Type = WorkType,
Name = Id,
Graph = Graph,
//MoneyLevel = MoneyLevel,
MoneyBase = MoneyBase,
StrengthFood = StrengthFood,
StrengthDrink = StrengthDrink,
Feeling = Feeling,
LevelLimit = LevelLimit,
Time = Time,
FinishBonus = FinishBonus,
//
BorderBrush = BorderBrush.Value.ToString()[3..],
Background = Background.Value.ToString()[3..],
ButtonBackground = ButtonBackground.Value.ToString()[3..],
ButtonForeground = ButtonForeground.Value.ToString()[3..],
Foreground = Foreground.Value.ToString()[3..],
BorderBrush = BorderBrush.ToString()[3..],
Background = Background.ToString()[3..],
ButtonBackground = ButtonBackground.ToString()[3..],
ButtonForeground = ButtonForeground.ToString()[3..],
Foreground = Foreground.ToString()[3..],
//
Left = Left.Value,
Top = Top.Value,
Width = Width.Value,
Left = Left,
Top = Top,
Width = Width,
};
}
public void Close()
{
Image.Value.CloseStream();
Image.CloseStream();
}
}
public class I18nWorkModel
public class I18nWorkModel : ObservableObjectX<I18nWorkModel>
{
public ObservableValue<string> Name { get; } = new();
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
public I18nWorkModel Copy()
{
var result = new I18nWorkModel();
result.Name.Value = Name.Value;
result.Name = Name;
return result;
}
}

View File

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

View File

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

View File

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

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

View File

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

View File

@ -1,112 +0,0 @@
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

@ -1,83 +0,0 @@
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;
}
#if NETCOREAPP2_0_OR_GREATER
/// <summary>
/// 获取值
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <returns>(旧值, 新值)</returns>
public (T oldValue, T newValye) GetValue<T>()
{
return ((T)OldValue!, (T)NewValue!)!;
}
#else
/// <summary>
/// 获取值
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <returns>(旧值, 新值)</returns>
public ValueInfo<T> GetValue<T>()
{
return new((T)OldValue!, (T)NewValue!)!;
}
#endif
}
#if !NETCOREAPP2_0_OR_GREATER
/// <summary>
/// 值信息
/// </summary>
/// <typeparam name="T">值类型</typeparam>
public struct ValueInfo<T>
{
/// <summary>
/// 旧值
/// </summary>
public T OldValue { get; set; }
/// <summary>
/// 新值
/// </summary>
public T NewValue { get; set; }
/// <inheritdoc/>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public ValueInfo(T oldValue, T newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}
#endif

View File

@ -1,17 +0,0 @@
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

@ -1,57 +0,0 @@
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;
}
#if NETCOREAPP2_0_OR_GREATER
/// <summary>
/// 获取值
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <returns>(旧值, 新值)</returns>
public (T oldValue, T newValye) GetValue<T>()
{
return ((T)OldValue!, (T)NewValue!)!;
}
#else
/// <summary>
/// 获取值
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <returns>(旧值, 新值)</returns>
public ValueInfo<T> GetValue<T>()
{
return new((T)OldValue!, (T)NewValue!)!;
}
#endif
}

View File

@ -1,17 +0,0 @@
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

@ -1,16 +0,0 @@
using System;
using System.Threading.Tasks;
using System.Windows.Input;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 异步执行命令事件
/// </summary>
public delegate Task ExecuteAsyncEventHandler();
/// <summary>
/// 异步执行命令事件
/// </summary>
/// <param name="parameter">值</param>
public delegate Task ExecuteAsyncEventHandler<T>(T parameter);

View File

@ -1,15 +0,0 @@
using System;
using System.Windows.Input;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 执行事件
/// </summary>
public delegate void ExecuteEventHandler();
/// <summary>
/// 执行事件
/// </summary>
/// <param name="parameter">参数</param>
public delegate void ExecuteEventHandler<T>(T parameter);

View File

@ -1,11 +0,0 @@
using System.ComponentModel;
using System.Windows.Input;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 通知接收器
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">参数</param>
public delegate void NotifyReceivedEventHandler(ICommand sender, CancelEventArgs e);

View File

@ -1,118 +0,0 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 可观察命令
/// </summary>
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
public class ObservableCommand : ObservableClass<ObservableCommand>, ICommand
{
bool _isCanExecute = true;
/// <summary>
/// 能执行的属性
/// </summary>
public bool IsCanExecute
{
get => _isCanExecute;
set => SetProperty(ref _isCanExecute, value);
}
bool _currentCanExecute = true;
/// <summary>
/// 当前可执行状态
/// <para>
/// 在执行异步事件时会强制为 <see langword="false"/>, 但异步结束后会恢复为 <see cref="IsCanExecute"/> 的值
/// </para>
/// </summary>
public bool CurrentCanExecute
{
get => _currentCanExecute;
private set => SetProperty(ref _currentCanExecute, value);
}
/// <inheritdoc/>
public ObservableCommand()
{
PropertyChanged += OnCanExecuteChanged;
}
private void OnCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
{
CanExecuteChanged?.Invoke(this, new());
}
#region ICommand
/// <summary>
/// 能否被执行
/// </summary>
/// <param name="parameter">参数</param>
/// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public bool CanExecute(object? parameter)
{
return CurrentCanExecute && IsCanExecute;
}
/// <summary>
/// 执行方法
/// </summary>
/// <param name="parameter">参数</param>
public async void Execute(object? parameter)
{
if (IsCanExecute is not true)
return;
ExecuteCommand?.Invoke();
await ExecuteAsync();
}
/// <summary>
/// 执行异步方法, 会在等待中修改 <see cref="CurrentCanExecute"/>, 完成后恢复
/// <para>
/// 若要在执行此方法时触发 <see cref="ExecuteCommand"/> 事件, 请将 <paramref name="runAlone"/> 设置为 <see langword="true"/>
/// </para>
/// </summary>
/// <param name="runAlone">设置为 <see langword="true"/> 时触发 <see cref="ExecuteCommand"/> 事件</param>
/// <returns>任务</returns>
public async Task ExecuteAsync(bool runAlone = false)
{
if (IsCanExecute is not true)
return;
if (runAlone)
ExecuteCommand?.Invoke();
if (ExecuteAsyncCommand is null)
return;
CurrentCanExecute = false;
foreach (
var asyncEvent in ExecuteAsyncCommand
.GetInvocationList()
.Cast<ExecuteAsyncEventHandler>()
)
await asyncEvent.Invoke();
CurrentCanExecute = true;
}
#endregion
#region Event
/// <summary>
/// 能否执行属性改变后事件
/// </summary>
public event EventHandler? CanExecuteChanged;
/// <summary>
/// 执行事件
/// </summary>
public event ExecuteEventHandler? ExecuteCommand;
/// <summary>
/// 异步执行事件
/// </summary>
public event ExecuteAsyncEventHandler? ExecuteAsyncCommand;
#endregion
}

View File

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

View File

@ -1,13 +0,0 @@
using System.ComponentModel;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 通知发送者属性改变接收器
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="eventSender">属性改变事件发送者</param>
public delegate void NotifySenderPropertyChangedHandler<T>(
ObservableValue<T> sender,
INotifyPropertyChanged? eventSender
);

View File

@ -1,231 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 可观察值
/// </summary>
/// <typeparam name="T"></typeparam>
[DebuggerDisplay("\\{ObservableValue, Value = {Value}\\}")]
public class ObservableValue<T>
: INotifyPropertyChanging,
INotifyPropertyChanged,
IEquatable<ObservableValue<T>>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private T _value = default!;
/// <summary>
/// 值
/// </summary>
public T Value
{
get => _value;
set
{
if (_value?.Equals(value) is true)
return;
var oldValue = _value;
if (NotifyPropertyChanging(oldValue, value))
return;
_value = value;
NotifyPropertyChanged(oldValue, value);
}
}
/// <summary>
/// 包含值
/// </summary>
public bool HasValue => Value != null;
/// <summary>
/// 分组
/// </summary>
public ObservableValueGroup<T>? Group { get; internal set; }
/// <summary>
/// 唯一标识符
/// </summary>
public Guid Guid { get; } = Guid.NewGuid();
#region Ctor
/// <inheritdoc/>
public ObservableValue() { }
/// <inheritdoc/>
/// <param name="value">初始值</param>
public ObservableValue(T value)
{
_value = value;
}
#endregion
#region NotifyProperty
/// <summary>
/// 通知属性改变前
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <returns>取消改变</returns>
private bool NotifyPropertyChanging(T oldValue, T newValue)
{
PropertyChanging?.Invoke(this, new(nameof(Value)));
var args = new ValueChangingEventArgs<T>(oldValue, newValue);
ValueChanging?.Invoke(this, args);
// 取消改变后通知UI更改
if (args.Cancel)
PropertyChanged?.Invoke(this, new(nameof(Value)));
return args.Cancel;
}
/// <summary>
/// 通知属性改变后
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
private void NotifyPropertyChanged(T oldValue, T newValue)
{
PropertyChanged?.Invoke(this, new(nameof(Value)));
ValueChanged?.Invoke(this, new(oldValue, newValue));
}
#endregion
#region NotifySender
/// <summary>
/// 通知发送者
/// </summary>
public IReadOnlyCollection<INotifyPropertyChanged> NotifySenders => _notifySenders;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly HashSet<INotifyPropertyChanged> _notifySenders = new();
/// <summary>
/// 添加通知发送者
/// <para>
/// 添加的发送者改变后会执行 <see cref="SenderPropertyChanged"/>
/// </para>
/// <para>示例:
/// <code><![CDATA[
/// ObservableValue<string> value1 = new();
/// ObservableValue<string> value2 = new();
/// value2.AddNotifySender(value1);
/// value2.SenderPropertyChanged += (source, sender) =>
/// {
/// source.Value = sender.Value;
/// };
/// value1.Value = "A";
/// // value1.Value == "A", value2.Value == "A"
/// ]]>
/// </code></para>
/// </summary>
/// <param name="items">发送者</param>
public void AddNotifySender(params INotifyPropertyChanged[] items)
{
foreach (var item in items)
{
item.PropertyChanged -= NotifySenderPropertyChanged;
item.PropertyChanged += NotifySenderPropertyChanged;
_notifySenders.Add(item);
}
}
/// <summary>
/// 删除通知发送者
/// </summary>
/// <param name="items">发送者</param>
public void RemoveNotifySender(params INotifyPropertyChanged[] items)
{
foreach (var item in items)
{
item.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Remove(item);
}
}
/// <summary>
/// 清空通知发送者
/// </summary>
public void ClearNotifySender()
{
foreach (var sender in _notifySenders)
sender.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Clear();
}
private void NotifySenderPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
SenderPropertyChanged?.Invoke(this, (INotifyPropertyChanged)sender!);
}
#endregion
#region Other
/// <inheritdoc/>
public override string ToString()
{
return Value?.ToString() ?? string.Empty;
}
/// <inheritdoc/>
public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return obj is ObservableValue<T> value
&& EqualityComparer<T>.Default.Equals(Value, value.Value);
}
/// <inheritdoc/>
public bool Equals(ObservableValue<T>? other)
{
return Equals(obj: other);
}
/// <inheritdoc/>
public static bool operator ==(ObservableValue<T> a, ObservableValue<T> b)
{
return a.Equals(obj: b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableValue<T> a, ObservableValue<T> b)
{
return a.Equals(obj: b) is not true;
}
#endregion
#region Event
/// <summary>
/// 属性改变前事件
/// </summary>
public event PropertyChangingEventHandler? PropertyChanging;
/// <summary>
/// 属性改变后事件
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// 值改变前事件
/// </summary>
public event ValueChangingEventHandler<T>? ValueChanging;
/// <summary>
/// 值改变后事件
/// </summary>
public event ValueChangedEventHandler<T>? ValueChanged;
/// <summary>
/// 通知接收事件
/// </summary>
public event NotifySenderPropertyChangedHandler<T>? SenderPropertyChanged;
#endregion
}

View File

@ -1,147 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 可观察值组合
/// <para>示例:<code><![CDATA[
/// var value1 = new ObservableValue<string>();
/// var value2 = new ObservableValue<string>();
/// var group = new ObservableValueGroup<string>() { value1, value2 };
/// value1.Value = "A";
/// // value1 == "A", value2 == "A"
/// group.Remove(value1);
/// value1.Value = "C";
/// // value1 == "C", value2 == "A"]]></code></para>
/// </summary>
/// <typeparam name="T">值类型</typeparam>
[DebuggerDisplay("\\{ObservableValueGroup, Count = {Count}\\}")]
public class ObservableValueGroup<T> : IEnumerable<ObservableValue<T>?>
{
/// <summary>
/// 数量
/// </summary>
public int Count => _bindingValues.Count;
/// <summary>
/// 在添加的时候改变值 (如果分组中存在值)
/// </summary>
[DefaultValue(false)]
public bool ChangeOnAdd { get; set; } = false;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Dictionary<Guid, WeakReference<ObservableValue<T>>> _bindingValues = new();
/// <summary>
/// 添加项
/// </summary>
/// <param name="items">项</param>
public void Add(params ObservableValue<T>[] items)
{
foreach (var item in items)
AddToGroup(item);
}
private void AddToGroup(ObservableValue<T> item)
{
if (item.Group is not null)
throw new ArgumentException("item Group must be null", nameof(item));
_bindingValues.Add(item.Guid, new(item));
item.ValueChanged -= Item_ValueChanged;
if (ChangeOnAdd)
{
foreach (var bindingValue in _bindingValues)
{
if (bindingValue.Value.TryGetTarget(out var target))
{
item.Value = target.Value;
break;
}
}
}
item.ValueChanged += Item_ValueChanged;
item.Group = this;
}
/// <summary>
/// 删除项
/// </summary>
/// <param name="items">项</param>
public void Remove(params ObservableValue<T>[] items)
{
foreach (var item in items)
RemoveFromGroup(item);
}
private void RemoveFromGroup(ObservableValue<T> item)
{
var result = _bindingValues.Remove(item.Guid);
if (result)
{
item.ValueChanged -= Item_ValueChanged;
item.Group = null;
}
}
/// <summary>
/// 清空分组
/// </summary>
public void Clear()
{
foreach (var bindingValue in _bindingValues)
{
if (bindingValue.Value.TryGetTarget(out var target))
{
target.ValueChanged -= Item_ValueChanged;
target.Group = null;
}
}
_bindingValues.Clear();
}
/// <summary>
/// 查找项
/// </summary>
/// <param name="item">项</param>
/// <returns>包含为 <see langword="true"/> 不包含为 <see langword="false"/></returns>
public bool Contains(ObservableValue<T> item)
{
return _bindingValues.ContainsKey(item.Guid);
}
/// <inheritdoc/>
public IEnumerator<ObservableValue<T>?> GetEnumerator()
{
return _bindingValues
.Values.Select(v => v.TryGetTarget(out var t) ? t : null)
.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _onChange = false;
private void Item_ValueChanged(ObservableValue<T> sender, ValueChangedEventArgs<T> e)
{
if (_onChange)
return;
_onChange = true;
foreach (var bindingValue in _bindingValues.AsEnumerable())
{
if (bindingValue.Value.TryGetTarget(out var target))
target.Value = e.NewValue!;
else
_bindingValues.Remove(bindingValue.Key);
}
_onChange = false;
}
}

View File

@ -1,29 +0,0 @@
using System;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 值改变后事件参数
/// </summary>
/// <typeparam name="T">值类型</typeparam>
public class ValueChangedEventArgs<T> : EventArgs
{
/// <summary>
/// 旧值
/// </summary>
public T? OldValue { get; }
/// <summary>
/// 新值
/// </summary>
public T? NewValue { get; }
/// <inheritdoc/>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public ValueChangedEventArgs(T oldValue, T newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}

View File

@ -1,11 +0,0 @@
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 值改变后事件
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">参数</param>
public delegate void ValueChangedEventHandler<T>(
ObservableValue<T> sender,
ValueChangedEventArgs<T> e
);

View File

@ -1,29 +0,0 @@
using System.ComponentModel;
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 值改变前事件参数
/// </summary>
/// <typeparam name="T">值类型</typeparam>
public class ValueChangingEventArgs<T> : CancelEventArgs
{
/// <summary>
/// 旧值
/// </summary>
public T? OldValue { get; }
/// <summary>
/// 新值
/// </summary>
public T? NewValue { get; }
/// <inheritdoc/>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public ValueChangingEventArgs(T? oldValue, T? newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}

View File

@ -1,11 +0,0 @@
namespace HKW.HKWUtils.Observable;
/// <summary>
/// 值改变前事件
/// </summary>
/// <param name="sender">发送者</param>
/// <param name="e">参数</param>
public delegate void ValueChangingEventHandler<T>(
ObservableValue<T> sender,
ValueChangingEventArgs<T> e
);

View File

@ -21,17 +21,17 @@ namespace HKW.HKWUtils;
/// </summary>
public static class NativeExtensions
{
/// <summary>
///
/// </summary>
/// <param name="source"></param>
/// <param name="value"></param>
/// <param name="comparisonType"></param>
/// <returns></returns>
public static bool Contains(this string source, string value, StringComparison comparisonType)
{
return source.IndexOf(value, comparisonType) >= 0;
}
///// <summary>
/////
///// </summary>
///// <param name="source"></param>
///// <param name="value"></param>
///// <param name="comparisonType"></param>
///// <returns></returns>
//public static bool Contains(this string source, string value, StringComparison comparisonType)
//{
// return source.IndexOf(value, comparisonType) >= 0;
//}
//public static string GetSourceFile(this BitmapImage image)
//{

View File

@ -1,81 +0,0 @@
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

@ -1,79 +0,0 @@
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 a.Equals(b);
}
/// <inheritdoc/>
public static bool operator !=(ObservablePoint<T> a, ObservablePoint<T> b)
{
return a.Equals(b) is not true;
}
#endregion
}

View File

@ -1,82 +0,0 @@
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 a.Equals(b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableRange<T> a, ObservableRange<T> b)
{
return a.Equals(b) is not true;
}
#endregion
}

View File

@ -1,91 +0,0 @@
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 a.Equals(b);
}
/// <inheritdoc/>
public static bool operator !=(ObservableRect<T> a, ObservableRect<T> b)
{
return a.Equals(b) is not true;
}
#endregion
}

View File

@ -25,4 +25,10 @@
<PackageReference Include="Panuon.WPF.UI" Version="1.2.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="HKW.Utils" Version="1.2.2" />
<PackageReference Include="HKW.WPF" Version="1.0.3" />
<PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup>
</Project>

View File

@ -1,23 +1,32 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit;
public class AddCultureWindowVM
public class AddCultureWindowVM : ObservableObjectX<AddCultureWindowVM>
{
/// <summary>
/// 显示的文化
/// </summary>
public ObservableValue<ObservableCollection<string>> ShowCultures { get; } = new();
#region ShowCultures
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<string> _showCultures;
public ObservableCollection<string> ShowCultures
{
get => _showCultures;
set => SetProperty(ref _showCultures, value);
}
#endregion
/// <summary>
/// 全部文化
@ -28,25 +37,53 @@ public class AddCultureWindowVM
/// <summary>
/// 当前文化
/// </summary>
public ObservableValue<string> Culture { get; } = new();
#region Culture
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _culture;
public string Culture
{
get => _culture;
set => SetProperty(ref _culture, value);
}
#endregion
/// <summary>
/// 当前文化全名
/// </summary>
public ObservableValue<string> CultureFullName { get; } = new(UnknownCulture);
#region CultureFullName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _cultureFullName;
public string CultureFullName
{
get => _cultureFullName;
set => SetProperty(ref _cultureFullName, value);
}
#endregion
/// <summary>
/// 搜索文化
/// </summary>
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _Search;
public string Search
{
get => _Search;
set => SetProperty(ref _Search, value);
}
#endregion
public static string UnknownCulture = "未知文化".Translate();
public AddCultureWindowVM()
{
ShowCultures.Value = AllCultures;
Search.ValueChanged += Search_ValueChanged;
Culture.ValueChanged += Culture_ValueChanged;
//TODO
//ShowCultures = AllCultures;
//Search.ValueChanged += Search_ValueChanged;
//Culture.ValueChanged += Culture_ValueChanged;
}
private void Culture_ValueChanged(
@ -56,7 +93,7 @@ public class AddCultureWindowVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
CultureFullName.Value = UnknownCulture;
CultureFullName = UnknownCulture;
return;
}
CultureInfo info = null!;
@ -66,11 +103,11 @@ public class AddCultureWindowVM
}
catch
{
CultureFullName.Value = UnknownCulture;
CultureFullName = UnknownCulture;
}
if (info is not null)
{
CultureFullName.Value = info.GetFullInfo();
CultureFullName = info.GetFullInfo();
}
}
@ -81,11 +118,11 @@ public class AddCultureWindowVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowCultures.Value = AllCultures;
ShowCultures = AllCultures;
}
else
{
ShowCultures.Value = new(
ShowCultures = new(
AllCultures.Where(s => s.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@ -18,7 +19,7 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class AnimeEditWindowVM
public class AnimeEditWindowVM : ObservableObjectX<AnimeEditWindowVM>
{
/// <summary>
/// 当前宠物
@ -35,35 +36,81 @@ public class AnimeEditWindowVM
/// </summary>
public ObservableValue<AnimeTypeModel> Anime { get; } = new(new());
#region CurrentImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ImageModel _currentImageModel;
/// <summary>
/// 当前图像模型
/// </summary>
public ObservableValue<ImageModel> CurrentImageModel { get; } = new();
public ImageModel CurrentImageModel
{
get => _currentImageModel;
set => SetProperty(ref _currentImageModel, value);
}
#endregion
#region CurrentAnimeModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private AnimeModel _currentAnimeModel;
/// <summary>
/// 当前动画模型
/// </summary>
public ObservableValue<AnimeModel> CurrentAnimeModel { get; } = new();
public AnimeModel CurrentAnimeModel
{
get => _currentAnimeModel;
set => SetProperty(ref _currentAnimeModel, value);
}
#endregion
/// <summary>
/// 当前模式
/// </summary>
public ModeType CurrentMode { get; set; }
#region Loop
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _loop;
/// <summary>
/// 循环
/// </summary>
public ObservableValue<bool> Loop { get; } = new();
public bool Loop
{
get => _loop;
set => SetProperty(ref _loop, value);
}
#endregion
#region HasMultiType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _hasMultiType;
/// <summary>
/// 含有多个状态 参见 <see cref="AnimeTypeModel.HasMultiTypeAnimes"/>
/// </summary>
public ObservableValue<bool> HasMultiType { get; } = new(false);
public bool HasMultiType
{
get => _hasMultiType;
set => SetProperty(ref _hasMultiType, value);
}
#endregion
#region HasAnimeName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _hasAnimeName;
/// <summary>
/// 含有动画名称 参见 <see cref="AnimeTypeModel.HasNameAnimes"/>
/// </summary>
public ObservableValue<bool> HasAnimeName { get; } = new(false);
public bool HasAnimeName
{
get => _hasAnimeName;
set => SetProperty(ref _hasAnimeName, value);
}
#endregion
#region Command
/// <summary>
@ -120,8 +167,8 @@ public class AnimeEditWindowVM
public AnimeEditWindowVM()
{
_playerTask = new(Play);
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
//TODO
//CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
@ -146,11 +193,11 @@ public class AnimeEditWindowVM
private void CheckGraphType(AnimeTypeModel model)
{
if (AnimeTypeModel.HasMultiTypeAnimes.Contains(model.GraphType.Value))
HasMultiType.Value = true;
if (AnimeTypeModel.HasMultiTypeAnimes.Contains(model.GraphType))
HasMultiType = true;
if (AnimeTypeModel.HasNameAnimes.Contains(model.GraphType.Value))
HasAnimeName.Value = true;
if (AnimeTypeModel.HasNameAnimes.Contains(model.GraphType))
HasAnimeName = true;
}
#endregion
@ -221,8 +268,8 @@ public class AnimeEditWindowVM
/// <param name="value">动画模型</param>
private void RemoveImageCommand_ExecuteEvent(AnimeModel value)
{
CurrentImageModel.Value.Close();
value.Images.Remove(CurrentImageModel.Value);
CurrentImageModel.Close();
value.Images.Remove(CurrentImageModel);
}
/// <summary>
@ -248,8 +295,8 @@ public class AnimeEditWindowVM
}
if (newImage is null)
return;
CurrentImageModel.Value.Close();
CurrentImageModel.Value.Image.Value = newImage;
CurrentImageModel.Close();
CurrentImageModel.Image = newImage;
}
/// <summary>
@ -331,7 +378,7 @@ public class AnimeEditWindowVM
/// </summary>
private async Task PlayCommand_AsyncExecuteEvent()
{
if (CurrentAnimeModel.Value is null)
if (CurrentAnimeModel is null)
{
MessageBox.Show("未选中动画".Translate());
return;
@ -349,14 +396,14 @@ public class AnimeEditWindowVM
{
do
{
foreach (var model in CurrentAnimeModel.Value.Images)
foreach (var model in CurrentAnimeModel.Images)
{
CurrentImageModel.Value = model;
Task.Delay(model.Duration.Value).Wait();
CurrentImageModel = model;
Task.Delay(model.Duration).Wait();
if (_playing is false)
return;
}
} while (Loop.Value);
} while (Loop);
}
/// <summary>

View File

@ -1,22 +1,22 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet.ModMaker.Views.ModEdit.AnimeEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class AnimePageVM
public class AnimePageVM : ObservableObjectX<AnimePageVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
@ -24,7 +24,16 @@ public class AnimePageVM
/// <summary>
/// 显示的动画
/// </summary>
public ObservableValue<ObservableCollection<object>> ShowAnimes { get; } = new();
#region ShowAnimes
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<object> _showAnimes;
public ObservableCollection<object> ShowAnimes
{
get => _showAnimes;
set => SetProperty(ref _showAnimes, value);
}
#endregion
/// <summary>
/// 所有动画
@ -51,10 +60,19 @@ public class AnimePageVM
/// </summary>
public ObservableValue<PetModel> CurrentPet { get; } = new(new());
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
/// <summary>
/// 搜索
/// </summary>
public ObservableValue<string> Search { get; } = new();
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
/// <summary>
@ -74,9 +92,10 @@ public class AnimePageVM
#endregion
public AnimePageVM()
{
ShowAnimes.Value = AllAnimes;
ShowAnimes = AllAnimes;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
Search.ValueChanged += Search_ValueChanged;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
@ -110,7 +129,7 @@ public class AnimePageVM
)
{
InitializeAllAnimes();
ShowAnimes.Value = AllAnimes;
ShowAnimes = AllAnimes;
}
private void Search_ValueChanged(
@ -120,20 +139,20 @@ public class AnimePageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowAnimes.Value = AllAnimes;
ShowAnimes = AllAnimes;
}
else
{
ShowAnimes.Value = new(
ShowAnimes = new(
AllAnimes.Where(m =>
{
if (m is AnimeTypeModel animeTypeModel)
return animeTypeModel.Id.Value.Contains(
return animeTypeModel.Id.Contains(
e.NewValue,
StringComparison.OrdinalIgnoreCase
);
else if (m is FoodAnimeTypeModel foodAnimeTypeModel)
return foodAnimeTypeModel.Id.Value.Contains(
return foodAnimeTypeModel.Id.Contains(
e.NewValue,
StringComparison.OrdinalIgnoreCase
);
@ -164,7 +183,7 @@ public class AnimePageVM
var window = new FoodAnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.Anime.Value.Name.Value = animeName;
vm.Anime.Value.Name = animeName;
window.ShowDialog();
if (window.IsCancel)
return;
@ -175,8 +194,8 @@ public class AnimePageVM
var window = new AnimeEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.Anime.Value.GraphType.Value = graphType;
vm.Anime.Value.Name.Value = animeName;
vm.Anime.Value.GraphType = graphType;
vm.Anime.Value.Name = animeName;
window.ShowDialog();
if (window.IsCancel)
return;
@ -203,8 +222,8 @@ public class AnimePageVM
if (window.IsCancel)
return;
Animes[Animes.IndexOf(animeTypeModel)] = newAnime;
if (ShowAnimes.Value.Count != Animes.Count)
ShowAnimes.Value[ShowAnimes.Value.IndexOf(animeTypeModel)] = newAnime;
if (ShowAnimes.Count != Animes.Count)
ShowAnimes[ShowAnimes.IndexOf(animeTypeModel)] = newAnime;
}
else if (model is FoodAnimeTypeModel foodAnimeTypeModel)
{
@ -218,8 +237,8 @@ public class AnimePageVM
if (window.IsCancel)
return;
FoodAnimes[FoodAnimes.IndexOf(foodAnimeTypeModel)] = newAnime;
if (ShowAnimes.Value.Count != FoodAnimes.Count)
ShowAnimes.Value[ShowAnimes.Value.IndexOf(foodAnimeTypeModel)] = newAnime;
if (ShowAnimes.Count != FoodAnimes.Count)
ShowAnimes[ShowAnimes.IndexOf(foodAnimeTypeModel)] = newAnime;
}
}
@ -231,7 +250,7 @@ public class AnimePageVM
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
ShowAnimes.Value.Remove(model);
ShowAnimes.Remove(model);
if (model is AnimeTypeModel animeTypeModel)
{
Animes.Remove(animeTypeModel);

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
@ -17,7 +18,7 @@ using static VPet_Simulator.Core.IGameSave;
namespace VPet.ModMaker.ViewModels.ModEdit.AnimeEdit;
public class FoodAnimeEditWindowVM
public class FoodAnimeEditWindowVM : ObservableObjectX<FoodAnimeEditWindowVM>
{
/// <summary>
/// 当前宠物
@ -30,15 +31,33 @@ public class FoodAnimeEditWindowVM
public static BitmapImage DefaultFoodImage { get; } =
NativeUtils.LoadImageToMemoryStream(NativeResources.GetStream(NativeResources.FoodImage));
#region FoodImage
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _foodImage;
/// <summary>
/// 食物图片
/// </summary>
public ObservableValue<BitmapImage> FoodImage { get; } = new(DefaultFoodImage);
public BitmapImage FoodImage
{
get => _foodImage;
set => SetProperty(ref _foodImage, value);
}
#endregion
#region LengthRatio
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _lengthRatio;
/// <summary>
/// 比例
/// </summary>
public ObservableValue<double> LengthRatio { get; } = new(250.0 / 500.0);
public double LengthRatio
{
get => _lengthRatio;
set => SetProperty(ref _lengthRatio, value);
}
#endregion
/// <summary>
/// 旧动画
@ -50,45 +69,108 @@ public class FoodAnimeEditWindowVM
/// </summary>
public ObservableValue<FoodAnimeTypeModel> Anime { get; } = new(new());
#region CurrentFrontImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ImageModel _currentFrontImageModel;
/// <summary>
/// 当前顶层图像模型
/// </summary>
public ObservableValue<ImageModel> CurrentFrontImageModel { get; } = new();
public ImageModel CurrentFrontImageModel
{
get => _currentFrontImageModel;
set => SetProperty(ref _currentFrontImageModel, value);
}
#endregion
#region CurrentBackImageModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ImageModel _currentBackImageModel;
/// <summary>
/// 当前底层图像模型
/// </summary>
public ObservableValue<ImageModel> CurrentBackImageModel { get; } = new();
public ImageModel CurrentBackImageModel
{
get => _currentBackImageModel;
set => SetProperty(ref _currentBackImageModel, value);
}
#endregion
#region CurrentFoodLocationModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private FoodLocationModel _currentFoodLocationModel;
/// <summary>
/// 当前食物定位模型
/// </summary>
public ObservableValue<FoodLocationModel> CurrentFoodLocationModel { get; } = new();
public FoodLocationModel CurrentFoodLocationModel
{
get => _currentFoodLocationModel;
set => SetProperty(ref _currentFoodLocationModel, value);
}
#endregion
#region CurrentAnimeModel
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private FoodAnimeModel _currentAnimeModel;
/// <summary>
/// 当前动画模型
/// </summary>
public ObservableValue<FoodAnimeModel> CurrentAnimeModel { get; } = new();
public FoodAnimeModel CurrentAnimeModel
{
get => _currentAnimeModel;
set => SetProperty(ref _currentAnimeModel, value);
}
#endregion
/// <summary>
/// 当前模式
/// </summary>
public ModeType CurrentMode { get; set; }
#region Loop
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _loop;
/// <summary>
/// 循环
/// </summary>
public ObservableValue<bool> Loop { get; } = new();
public bool Loop
{
get => _loop;
set => SetProperty(ref _loop, value);
}
#endregion
#region HasMultiType
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _hasMultiType;
/// <summary>
/// 含有多个状态 参见 <see cref="AnimeTypeModel.HasMultiTypeAnimes"/>
/// </summary>
public ObservableValue<bool> HasMultiType { get; } = new(false);
public bool HasMultiType
{
get => _hasMultiType;
set => SetProperty(ref _hasMultiType, value);
}
#endregion
#region HasAnimeName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _hasAnimeName;
/// <summary>
/// 含有动画名称 参见 <see cref="AnimeTypeModel.HasNameAnimes"/>
/// </summary>
public ObservableValue<bool> HasAnimeName { get; } = new(false);
public bool HasAnimeName
{
get => _hasAnimeName;
set => SetProperty(ref _hasAnimeName, value);
}
#endregion
#region Command
/// <summary>
@ -207,8 +289,8 @@ public class FoodAnimeEditWindowVM
_frontPlayerTask = new(FrontPlay);
_backPlayerTask = new(BackPlay);
_foodPlayerTask = new(FoodPlay);
CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
//TODO
//CurrentAnimeModel.ValueChanged += CurrentAnimeModel_ValueChanged;
PlayCommand.ExecuteAsyncCommand += PlayCommand_AsyncExecuteEvent;
StopCommand.ExecuteCommand += StopCommand_ExecuteEvent;
@ -235,9 +317,9 @@ public class FoodAnimeEditWindowVM
private void ResetFoodImageCommand_ExecuteEvent()
{
if (FoodImage.Value != DefaultFoodImage)
FoodImage.Value.CloseStream();
FoodImage.Value = DefaultFoodImage;
if (FoodImage != DefaultFoodImage)
FoodImage.CloseStream();
FoodImage = DefaultFoodImage;
}
private void ChangeFoodImageCommand_ExecuteEvent()
@ -246,9 +328,9 @@ public class FoodAnimeEditWindowVM
new() { Title = "选择食物图片".Translate(), Filter = $"图片|*.png".Translate() };
if (openFileDialog.ShowDialog() is true)
{
if (FoodImage.Value != DefaultFoodImage)
FoodImage.Value.CloseStream();
FoodImage.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
if (FoodImage != DefaultFoodImage)
FoodImage.CloseStream();
FoodImage = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -331,8 +413,8 @@ public class FoodAnimeEditWindowVM
/// <param name="value">动画模型</param>
private void RemoveFrontImageCommand_ExecuteEvent(FoodAnimeModel value)
{
CurrentFrontImageModel.Value.Close();
value.FrontImages.Remove(CurrentFrontImageModel.Value);
CurrentFrontImageModel.Close();
value.FrontImages.Remove(CurrentFrontImageModel);
}
/// <summary>
@ -374,8 +456,8 @@ public class FoodAnimeEditWindowVM
}
if (newImage is null)
return;
CurrentFrontImageModel.Value.Close();
CurrentFrontImageModel.Value.Image.Value = newImage;
CurrentFrontImageModel.Close();
CurrentFrontImageModel.Image = newImage;
}
#endregion
@ -405,8 +487,8 @@ public class FoodAnimeEditWindowVM
/// <param name="value">动画模型</param>
private void RemoveBackImageCommand_ExecuteEvent(FoodAnimeModel value)
{
CurrentBackImageModel.Value.Close();
value.BackImages.Remove(CurrentBackImageModel.Value);
CurrentBackImageModel.Close();
value.BackImages.Remove(CurrentBackImageModel);
}
/// <summary>
@ -448,8 +530,8 @@ public class FoodAnimeEditWindowVM
}
if (newImage is null)
return;
CurrentBackImageModel.Value.Close();
CurrentBackImageModel.Value.Image.Value = newImage;
CurrentBackImageModel.Close();
CurrentBackImageModel.Image = newImage;
}
#endregion
@ -494,8 +576,8 @@ public class FoodAnimeEditWindowVM
private void RemoveFoodLocationCommand_ExecuteEvent(FoodAnimeModel value)
{
value.FoodLocations.Remove(CurrentFoodLocationModel.Value);
CurrentFoodLocationModel.Value = null;
value.FoodLocations.Remove(CurrentFoodLocationModel);
CurrentFoodLocationModel = null;
}
private void ClearFoodLocationCommand_ExecuteEvent(FoodAnimeModel value)
@ -547,7 +629,7 @@ public class FoodAnimeEditWindowVM
/// </summary>
private async Task PlayCommand_AsyncExecuteEvent()
{
if (CurrentAnimeModel.Value is null)
if (CurrentAnimeModel is null)
{
MessageBox.Show("未选中动画".Translate());
return;
@ -562,7 +644,7 @@ public class FoodAnimeEditWindowVM
_frontPlayerTask = new(FrontPlay);
_backPlayerTask = new(BackPlay);
_foodPlayerTask = new(FoodPlay);
} while (Loop.Value && _playing);
} while (Loop && _playing);
}
/// <summary>
@ -570,10 +652,10 @@ public class FoodAnimeEditWindowVM
/// </summary>
private void FrontPlay()
{
foreach (var model in CurrentAnimeModel.Value.FrontImages)
foreach (var model in CurrentAnimeModel.FrontImages)
{
CurrentFrontImageModel.Value = model;
Task.Delay(model.Duration.Value).Wait();
CurrentFrontImageModel = model;
Task.Delay(model.Duration).Wait();
if (_playing is false)
return;
}
@ -584,10 +666,10 @@ public class FoodAnimeEditWindowVM
/// </summary>
private void BackPlay()
{
foreach (var model in CurrentAnimeModel.Value.BackImages)
foreach (var model in CurrentAnimeModel.BackImages)
{
CurrentBackImageModel.Value = model;
Task.Delay(model.Duration.Value).Wait();
CurrentBackImageModel = model;
Task.Delay(model.Duration).Wait();
if (_playing is false)
return;
}
@ -598,10 +680,10 @@ public class FoodAnimeEditWindowVM
/// </summary>
private void FoodPlay()
{
foreach (var model in CurrentAnimeModel.Value.FoodLocations)
foreach (var model in CurrentAnimeModel.FoodLocations)
{
CurrentFoodLocationModel.Value = model;
Task.Delay(model.Duration.Value).Wait();
CurrentFoodLocationModel = model;
Task.Delay(model.Duration).Wait();
if (_playing is false)
return;
}

View File

@ -1,16 +1,17 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet.ModMaker.Models;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.ClickTextEdit;
public class ClickTextEditWindowVM
public class ClickTextEditWindowVM : ObservableObjectX<ClickTextEditWindowVM>
{
public I18nHelper I18nData => I18nHelper.Current;
@ -20,10 +21,19 @@ public class ClickTextEditWindowVM
/// </summary>
public ClickTextModel OldClickText { get; set; }
#region ClickText
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ClickTextModel _clickText = new();
/// <summary>
/// 点击文本
/// </summary>
public ObservableValue<ClickTextModel> ClickText { get; } = new(new());
public ClickTextModel ClickText
{
get => _clickText;
set => SetProperty(ref _clickText, value);
}
#endregion
#endregion
public ClickTextEditWindowVM() { }
}

View File

@ -1,35 +1,53 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views.ModEdit.ClickTextEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.ClickTextEdit;
public class ClickTextPageVM
public class ClickTextPageVM : ObservableObjectX<ClickTextPageVM>
{
#region Value
#region ShowClickTexts
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<ClickTextModel> _showClickTexts;
/// <summary>
/// 显示的点击文本
/// </summary>
public ObservableValue<ObservableCollection<ClickTextModel>> ShowClickTexts { get; } = new();
public ObservableCollection<ClickTextModel> ShowClickTexts
{
get => _showClickTexts;
set => SetProperty(ref _showClickTexts, value);
}
#endregion
/// <summary>
/// 点击文本
/// </summary>
public ObservableCollection<ClickTextModel> ClickTexts => ModInfoModel.Current.ClickTexts;
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
/// <summary>
/// 搜索
/// </summary>
public ObservableValue<string> Search { get; } = new();
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
/// <summary>
@ -50,8 +68,9 @@ public class ClickTextPageVM
public ClickTextPageVM()
{
ShowClickTexts.Value = ClickTexts;
Search.ValueChanged += Search_ValueChanged;
ShowClickTexts = ClickTexts;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
@ -64,14 +83,12 @@ public class ClickTextPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowClickTexts.Value = ClickTexts;
ShowClickTexts = ClickTexts;
}
else
{
ShowClickTexts.Value = new(
ClickTexts.Where(
m => m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
ShowClickTexts = new(
ClickTexts.Where(m => m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -86,7 +103,7 @@ public class ClickTextPageVM
window.ShowDialog();
if (window.IsCancel)
return;
ClickTexts.Add(vm.ClickText.Value);
ClickTexts.Add(vm.ClickText);
}
/// <summary>
@ -98,13 +115,13 @@ public class ClickTextPageVM
var window = new ClickTextEditWindow();
var vm = window.ViewModel;
vm.OldClickText = model;
var newLowTest = vm.ClickText.Value = new(model);
var newLowTest = vm.ClickText = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
ClickTexts[ClickTexts.IndexOf(model)] = newLowTest;
if (ShowClickTexts.Value.Count != ClickTexts.Count)
ShowClickTexts.Value[ShowClickTexts.Value.IndexOf(model)] = newLowTest;
if (ShowClickTexts.Count != ClickTexts.Count)
ShowClickTexts[ShowClickTexts.IndexOf(model)] = newLowTest;
}
/// <summary>
@ -115,13 +132,13 @@ public class ClickTextPageVM
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowClickTexts.Value.Count == ClickTexts.Count)
if (ShowClickTexts.Count == ClickTexts.Count)
{
ClickTexts.Remove(model);
}
else
{
ShowClickTexts.Value.Remove(model);
ShowClickTexts.Remove(model);
ClickTexts.Remove(model);
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
@ -14,13 +15,23 @@ using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.FoodEdit;
public class FoodEditWindowVM
public class FoodEditWindowVM : ObservableObjectX<FoodEditWindowVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
public static I18nHelper I18nData => I18nHelper.Current;
#region Value
public FoodModel OldFood { get; set; }
public ObservableValue<FoodModel> Food { get; } = new(new());
#region Food
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private FoodModel _food;
public FoodModel Food
{
get => _food;
set => SetProperty(ref _food, value);
}
#endregion
#endregion
#region Command
@ -34,7 +45,8 @@ public class FoodEditWindowVM
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
SetReferencePriceCommand.ExecuteCommand += SetReferencePriceToPrice;
Food.Value.ReferencePrice.ValueChanged += ReferencePrice_ValueChanged;
//TODO
//Food.Value.ReferencePrice.ValueChanged += ReferencePrice_ValueChanged;
}
private void ReferencePrice_ValueChanged(
@ -42,7 +54,7 @@ public class FoodEditWindowVM
ValueChangedEventArgs<double> e
)
{
if (ModInfo.AutoSetFoodPrice.Value)
if (ModInfo.AutoSetFoodPrice)
{
SetReferencePriceToPrice(e.NewValue);
}
@ -50,12 +62,12 @@ public class FoodEditWindowVM
private void SetReferencePriceToPrice(double value)
{
Food.Value.Price.Value = value;
Food.Price = value;
}
public void Close()
{
Food.Value.Close();
Food.Close();
}
private void AddImage()
@ -68,7 +80,7 @@ public class FoodEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Food.Value.Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Food.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -82,8 +94,8 @@ public class FoodEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Food.Value.Image.Value?.StreamSource?.Close();
Food.Value.Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Food.Image?.StreamSource?.Close();
Food.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
}

View File

@ -1,26 +1,45 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views.ModEdit.FoodEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.FoodEdit;
public class FoodPageVM
public class FoodPageVM : ObservableObjectX<FoodPageVM>
{
#region Value
public ObservableValue<ObservableCollection<FoodModel>> ShowFoods { get; } = new();
#region ShowFoods
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<FoodModel> _showFoods;
public ObservableCollection<FoodModel> ShowFoods
{
get => _showFoods;
set => SetProperty(ref _showFoods, value);
}
#endregion
public ObservableCollection<FoodModel> Foods => ModInfoModel.Current.Foods;
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -29,8 +48,9 @@ public class FoodPageVM
#endregion
public FoodPageVM()
{
ShowFoods.Value = Foods;
Search.ValueChanged += Search_ValueChanged;
ShowFoods = Foods;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
@ -44,14 +64,12 @@ public class FoodPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowFoods.Value = Foods;
ShowFoods = Foods;
}
else
{
ShowFoods.Value = new(
Foods.Where(
m => m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
ShowFoods = new(
Foods.Where(m => m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -65,7 +83,7 @@ public class FoodPageVM
window.ShowDialog();
if (window.IsCancel)
return;
Foods.Add(vm.Food.Value);
Foods.Add(vm.Food);
}
public void Edit(FoodModel food)
@ -73,13 +91,13 @@ public class FoodPageVM
var window = new FoodEditWindow();
var vm = window.ViewModel;
vm.OldFood = food;
var newFood = vm.Food.Value = new(food);
var newFood = vm.Food = new(food);
window.ShowDialog();
if (window.IsCancel)
return;
Foods[Foods.IndexOf(food)] = newFood;
if (ShowFoods.Value.Count != Foods.Count)
ShowFoods.Value[ShowFoods.Value.IndexOf(food)] = newFood;
if (ShowFoods.Count != Foods.Count)
ShowFoods[ShowFoods.IndexOf(food)] = newFood;
food.Close();
}
@ -87,13 +105,13 @@ public class FoodPageVM
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowFoods.Value.Count == Foods.Count)
if (ShowFoods.Count == Foods.Count)
{
Foods.Remove(food);
}
else
{
ShowFoods.Value.Remove(food);
ShowFoods.Remove(food);
Foods.Remove(food);
}
}

View File

@ -1,500 +1,523 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.I18nEdit;
public class I18nEditWindowVM
{
/// <summary>
/// 搜索
/// </summary>
public ObservableValue<string> Search { get; } = new();
public class I18nEditWindowVM : ObservableObjectX<I18nEditWindowVM> { }
//{
// #region Search
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _search;
/// <summary>
/// 全部I18n数据 (Id, I18nData)
/// </summary>
public Dictionary<string, I18nData> AllI18nDatas { get; } = new();
// /// <summary>
// /// 搜索
// /// </summary>
// public string Search
// {
// get => _search;
// set => SetProperty(ref _search, value);
// }
// #endregion
/// <summary>
/// 全部I18n数据
/// </summary>
public ObservableCollection<I18nData> I18nDatas { get; } = new();
// /// <summary>
// /// 全部I18n数据 (Id, I18nData)
// /// </summary>
// public Dictionary<string, I18nData> AllI18nDatas { get; } = new();
/// <summary>
/// 显示的I18n数据
/// </summary>
public ObservableValue<ObservableCollection<I18nData>> ShowI18nDatas { get; } = new();
// /// <summary>
// /// 全部I18n数据
// /// </summary>
// public ObservableCollection<I18nData> I18nDatas { get; } = new();
/// <summary>
/// 搜索目标列表
/// </summary>
public ObservableCollection<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) };
// /// <summary>
// /// 显示的I18n数据
// /// </summary>
// #region ShowI18nDatas
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private ObservableCollection<I18nData> _showI18nDatas;
/// <summary>
/// 搜索目标
/// </summary>
public ObservableValue<string> SearchTarget { get; } = new();
// public ObservableCollection<I18nData> ShowI18nDatas
// {
// get => _showI18nDatas;
// set => SetProperty(ref _showI18nDatas, value);
// }
// #endregion
public I18nEditWindowVM()
{
Search.ValueChanged += Search_ValueChanged;
ShowI18nDatas.Value = I18nDatas;
SearchTarget.Value = nameof(ModInfoModel.Id);
}
// /// <summary>
// /// 搜索目标列表
// /// </summary>
// public ObservableCollection<string> SearchTargets { get; } = new() { nameof(ModInfoModel.Id) };
/// <summary>
/// 搜索改变事件
/// </summary>
/// <param name="oldValue"></param>
/// <param name="newValue"></param>
private void Search_ValueChanged(
ObservableValue<string> sender,
ValueChangedEventArgs<string> e
)
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowI18nDatas.Value = I18nDatas;
}
else if (SearchTarget.Value == nameof(ModInfoModel.Id))
{
ShowI18nDatas.Value = new(
I18nDatas.Where(
m =>
m.Id.Value?.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase) is true
)
);
}
else
{
var cultureIndex = I18nHelper.Current.CultureNames.IndexOf(SearchTarget.Value);
ShowI18nDatas.Value = new(
I18nDatas.Where(
m =>
m.Datas[cultureIndex].Value?.Contains(
e.NewValue,
StringComparison.OrdinalIgnoreCase
)
is true
)
);
}
}
// /// <summary>
// /// 搜索目标
// /// </summary>
// #region SearchTarget
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _searchTarget;
/// <summary>
/// 文化列表改变事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CultureNames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newCulture = (string)e.NewItems[0];
AddCulture(newCulture);
SearchTargets.Add(newCulture);
foreach (var data in AllI18nDatas)
data.Value.Datas.Add(new());
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldCulture = (string)e.OldItems[0];
RemoveCulture(oldCulture);
SearchTargets.Remove(oldCulture);
foreach (var data in AllI18nDatas)
{
var value = data.Value.Datas[e.OldStartingIndex];
value.Group?.Remove(value);
data.Value.Datas.RemoveAt(e.OldStartingIndex);
}
if (SearchTarget.Value is null)
SearchTarget.Value = nameof(ModInfoModel.Id);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var oldCulture = (string)e.OldItems[0];
var newCulture = (string)e.NewItems[0];
ReplaceCulture(oldCulture, newCulture);
SearchTargets[SearchTargets.IndexOf(oldCulture)] = newCulture;
}
}
// public string SearchTarget
// {
// get => _searchTarget;
// set => SetProperty(ref _searchTarget, value);
// }
// #endregion
#region LoadData
/// <summary>
/// 初始化I18n数据
/// </summary>
/// <param name="model"></param>
public void InitializeI18nData(ModInfoModel model)
{
foreach (var culture in I18nHelper.Current.CultureNames)
{
AddCulture(culture);
SearchTargets.Add(culture);
}
try
{
LoadFood(model);
LoadClickText(model);
LoadLowText(model);
LoadSelectText(model);
LoadPets(model);
}
catch
{
Close();
throw;
}
I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
I18nHelper.Current.CultureNames.CollectionChanged += CultureNames_CollectionChanged;
}
// public I18nEditWindowVM()
// {
// //Search.ValueChanged += Search_ValueChanged;// TODO
// ShowI18nDatas = I18nDatas;
// SearchTarget = nameof(ModInfoModel.Id);
// }
/// <summary>
/// 载入食物
/// </summary>
/// <param name="model"></param>
private void LoadFood(ModInfoModel model)
{
foreach (var food in model.Foods)
{
AddData(food.Id, food, (m) => m.Name);
AddData(food.DescriptionId, food, (m) => m.Description);
}
model.Foods.CollectionChanged += (s, e) =>
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newModel = (FoodModel)e.NewItems[0];
AddData(newModel.Id, newModel, (m) => m.Name);
AddData(newModel.DescriptionId, newModel, (m) => m.Description);
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldModel = (FoodModel)e.OldItems[0];
RemoveData(oldModel.Id, oldModel, (m) => m.Name);
RemoveData(oldModel.DescriptionId, oldModel, (m) => m.Description);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var newModel = (FoodModel)e.NewItems[0];
var oldModel = (FoodModel)e.OldItems[0];
ReplaceData(newModel.Id, newModel, (m) => m.Name);
ReplaceData(newModel.DescriptionId, newModel, (m) => m.Description);
}
};
}
// /// <summary>
// /// 搜索改变事件
// /// </summary>
// /// <param name="oldValue"></param>
// /// <param name="newValue"></param>
// private void Search_ValueChanged(
// ObservableValue<string> sender,
// ValueChangedEventArgs<string> e
// )
// {
// if (string.IsNullOrWhiteSpace(e.NewValue))
// {
// ShowI18nDatas = I18nDatas;
// }
// else if (SearchTarget == nameof(ModInfoModel.Id))
// {
// ShowI18nDatas = new(
// I18nDatas.Where(m =>
// m.Id?.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase) is true
// )
// );
// }
// else
// {
// var cultureIndex = I18nHelper.Current.CultureNames.IndexOf(SearchTarget);
// ShowI18nDatas = new(
// I18nDatas.Where(m =>
// m.Datas[cultureIndex]
// .Value?.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
// is true
// )
// );
// }
// }
/// <summary>
/// 载入点击文本
/// </summary>
/// <param name="model"></param>
private void LoadClickText(ModInfoModel model)
{
foreach (var text in model.ClickTexts)
{
AddData(text.Id, text, (m) => m.Text);
}
model.ClickTexts.CollectionChanged += (s, e) =>
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newModel = (ClickTextModel)e.NewItems[0];
AddData(newModel.Id, newModel, (m) => m.Text);
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldModel = (ClickTextModel)e.OldItems[0];
RemoveData(oldModel.Id, oldModel, (m) => m.Text);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var newModel = (ClickTextModel)e.NewItems[0];
var oldModel = (ClickTextModel)e.OldItems[0];
ReplaceData(newModel.Id, newModel, (m) => m.Text);
}
};
}
// /// <summary>
// /// 文化列表改变事件
// /// </summary>
// /// <param name="sender"></param>
// /// <param name="e"></param>
// private void CultureNames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newCulture = (string)e.NewItems[0];
// AddCulture(newCulture);
// SearchTargets.Add(newCulture);
// foreach (var data in AllI18nDatas)
// data.Value.Datas.Add(new());
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldCulture = (string)e.OldItems[0];
// RemoveCulture(oldCulture);
// SearchTargets.Remove(oldCulture);
// foreach (var data in AllI18nDatas)
// {
// var value = data.Value.Datas[e.OldStartingIndex];
// value.Group?.Remove(value);
// data.Value.Datas.RemoveAt(e.OldStartingIndex);
// }
// if (SearchTarget is null)
// SearchTarget = nameof(ModInfoModel.Id);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var oldCulture = (string)e.OldItems[0];
// var newCulture = (string)e.NewItems[0];
// ReplaceCulture(oldCulture, newCulture);
// SearchTargets[SearchTargets.IndexOf(oldCulture)] = newCulture;
// }
// }
/// <summary>
/// 载入低状态为文本
/// </summary>
/// <param name="model"></param>
private void LoadLowText(ModInfoModel model)
{
foreach (var text in model.LowTexts)
{
AddData(text.Id, text, (m) => m.Text);
}
model.LowTexts.CollectionChanged += (s, e) =>
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newModel = (LowTextModel)e.NewItems[0];
AddData(newModel.Id, newModel, (m) => m.Text);
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldModel = (LowTextModel)e.OldItems[0];
RemoveData(oldModel.Id, oldModel, (m) => m.Text);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var newModel = (LowTextModel)e.NewItems[0];
var oldModel = (LowTextModel)e.OldItems[0];
ReplaceData(newModel.Id, newModel, (m) => m.Text);
}
};
}
// #region LoadData
// /// <summary>
// /// 初始化I18n数据
// /// </summary>
// /// <param name="model"></param>
// public void InitializeI18nData(ModInfoModel model)
// {
// foreach (var culture in I18nHelper.Current.CultureNames)
// {
// AddCulture(culture);
// SearchTargets.Add(culture);
// }
// try
// {
// LoadFood(model);
// LoadClickText(model);
// LoadLowText(model);
// LoadSelectText(model);
// LoadPets(model);
// }
// catch
// {
// Close();
// throw;
// }
// I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
// I18nHelper.Current.CultureNames.CollectionChanged += CultureNames_CollectionChanged;
// }
/// <summary>
/// 载入选择文本
/// </summary>
/// <param name="model"></param>
private void LoadSelectText(ModInfoModel model)
{
foreach (var text in model.SelectTexts)
{
AddData(text.Id, text, (m) => m.Text);
AddData(text.ChooseId, text, (m) => m.Choose);
}
model.SelectTexts.CollectionChanged += (s, e) =>
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newModel = (SelectTextModel)e.NewItems[0];
AddData(newModel.Id, newModel, (m) => m.Text);
AddData(newModel.ChooseId, newModel, (m) => m.Choose);
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldModel = (SelectTextModel)e.OldItems[0];
RemoveData(oldModel.Id, oldModel, (m) => m.Text);
RemoveData(oldModel.ChooseId, oldModel, (m) => m.Choose);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var newModel = (SelectTextModel)e.NewItems[0];
var oldModel = (SelectTextModel)e.OldItems[0];
ReplaceData(newModel.Id, newModel, (m) => m.Text);
ReplaceData(newModel.ChooseId, newModel, (m) => m.Choose);
}
};
}
// /// <summary>
// /// 载入食物
// /// </summary>
// /// <param name="model"></param>
// private void LoadFood(ModInfoModel model)
// {
// foreach (var food in model.Foods)
// {
// AddData(food.Id, food, (m) => m.Name);
// AddData(food.DescriptionId, food, (m) => m.Description);
// }
// model.Foods.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (FoodModel)e.NewItems[0];
// AddData(newModel.Id, newModel, (m) => m.Name);
// AddData(newModel.DescriptionId, newModel, (m) => m.Description);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (FoodModel)e.OldItems[0];
// RemoveData(oldModel.Id, oldModel, (m) => m.Name);
// RemoveData(oldModel.DescriptionId, oldModel, (m) => m.Description);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (FoodModel)e.NewItems[0];
// var oldModel = (FoodModel)e.OldItems[0];
// ReplaceData(newModel.Id, newModel, (m) => m.Name);
// ReplaceData(newModel.DescriptionId, newModel, (m) => m.Description);
// }
// };
// }
/// <summary>
/// 载入宠物
/// </summary>
/// <param name="model"></param>
public void LoadPets(ModInfoModel model)
{
foreach (var pet in model.Pets)
{
if (pet.FromMain.Value)
continue;
AddData(pet.Id, pet, (m) => m.Name);
AddData(pet.PetNameId, pet, (m) => m.PetName);
AddData(pet.DescriptionId, pet, (m) => m.Description);
foreach (var work in pet.Works)
AddData(work.Id, work, (m) => m.Name);
}
model.Pets.CollectionChanged += (s, e) =>
{
if (e.Action is NotifyCollectionChangedAction.Add)
{
var newModel = (PetModel)e.NewItems[0];
AddData(newModel.Id, newModel, (m) => m.Name);
AddData(newModel.DescriptionId, newModel, (m) => m.Description);
foreach (var work in newModel.Works)
AddData(work.Id, work, (m) => m.Name);
}
else if (e.Action is NotifyCollectionChangedAction.Remove)
{
var oldModel = (PetModel)e.OldItems[0];
if (oldModel.FromMain.Value)
return;
RemoveData(oldModel.Id, oldModel, (m) => m.Name);
RemoveData(oldModel.DescriptionId, oldModel, (m) => m.Description);
foreach (var work in oldModel.Works)
RemoveData(work.Id, work, (m) => m.Name);
}
else if (e.Action is NotifyCollectionChangedAction.Replace)
{
var newModel = (PetModel)e.NewItems[0];
var oldModel = (PetModel)e.OldItems[0];
ReplaceData(newModel.Id, newModel, (m) => m.Name);
ReplaceData(newModel.DescriptionId, newModel, (m) => m.Description);
foreach (var work in newModel.Works)
ReplaceData(work.Id, work, (m) => m.Name);
}
};
}
#endregion
// /// <summary>
// /// 载入点击文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadClickText(ModInfoModel model)
// {
// foreach (var text in model.ClickTexts)
// {
// AddData(text.Id, text, (m) => m.Text);
// }
// model.ClickTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (ClickTextModel)e.NewItems[0];
// AddData(newModel.Id, newModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (ClickTextModel)e.OldItems[0];
// RemoveData(oldModel.Id, oldModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (ClickTextModel)e.NewItems[0];
// var oldModel = (ClickTextModel)e.OldItems[0];
// ReplaceData(newModel.Id, newModel, (m) => m.Text);
// }
// };
// }
#region DatEdit
/// <summary>
/// 添加数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <param name="i18nModel"></param>
/// <param name="i18nValue"></param>
private void AddData<T>(
ObservableValue<string> id,
I18nModel<T> i18nModel,
Func<T, ObservableValue<string>> i18nValue
)
where T : class, new()
{
if (AllI18nDatas.TryGetValue(id.Value, out var outData))
{
foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
{
if (outData.Datas[culture.Index].Group is null)
{
var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
}
outData.Datas[culture.Index].Group!.Add(
i18nValue(i18nModel.I18nDatas[culture.Value])
);
}
}
else
{
var data = new I18nData();
data.Id.Value = id.Value;
foreach (var culture in I18nHelper.Current.CultureNames)
data.Datas.Add(i18nValue(i18nModel.I18nDatas[culture]));
I18nDatas.Add(data);
AllI18nDatas.Add(id.Value, data);
//id.ValueChanged += IdChange;
}
}
// /// <summary>
// /// 载入低状态为文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadLowText(ModInfoModel model)
// {
// foreach (var text in model.LowTexts)
// {
// AddData(text.Id, text, (m) => m.Text);
// }
// model.LowTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (LowTextModel)e.NewItems[0];
// AddData(newModel.Id, newModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (LowTextModel)e.OldItems[0];
// RemoveData(oldModel.Id, oldModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (LowTextModel)e.NewItems[0];
// var oldModel = (LowTextModel)e.OldItems[0];
// ReplaceData(newModel.Id, newModel, (m) => m.Text);
// }
// };
// }
/// <summary>
/// Id改变
/// </summary>
/// <param name="oldValue"></param>
/// <param name="newValue"></param>
private void IdChange(ObservableValue<string> sender, ValueChangedEventArgs<string> e)
{
var sourceData = AllI18nDatas[e.OldValue];
sourceData.Id.Group?.Remove(sourceData.Id);
if (AllI18nDatas.TryGetValue(e.OldValue, out var outData))
{
foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
{
if (outData.Datas[culture.Index].Group is null)
{
var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
}
outData.Datas[culture.Index].Group!.Add(sourceData.Datas[culture.Index]);
}
}
else
{
sourceData.Id.Value = e.NewValue;
AllI18nDatas.Remove(e.OldValue);
AllI18nDatas.Add(e.NewValue, sourceData);
}
}
// /// <summary>
// /// 载入选择文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadSelectText(ModInfoModel model)
// {
// foreach (var text in model.SelectTexts)
// {
// AddData(text.Id, text, (m) => m.Text);
// AddData(text.ChooseId, text, (m) => m.Choose);
// }
// model.SelectTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (SelectTextModel)e.NewItems[0];
// AddData(newModel.Id, newModel, (m) => m.Text);
// AddData(newModel.ChooseId, newModel, (m) => m.Choose);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (SelectTextModel)e.OldItems[0];
// RemoveData(oldModel.Id, oldModel, (m) => m.Text);
// RemoveData(oldModel.ChooseId, oldModel, (m) => m.Choose);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (SelectTextModel)e.NewItems[0];
// var oldModel = (SelectTextModel)e.OldItems[0];
// ReplaceData(newModel.Id, newModel, (m) => m.Text);
// ReplaceData(newModel.ChooseId, newModel, (m) => m.Choose);
// }
// };
// }
/// <summary>
/// 删除I18n数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <param name="i18nModel"></param>
/// <param name="i18nValue"></param>
private void RemoveData<T>(
ObservableValue<string> id,
I18nModel<T> i18nModel,
Func<T, ObservableValue<string>> i18nValue
)
where T : class, new()
{
var data = AllI18nDatas[id.Value];
foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
{
if (data.Datas[culture.Index].Group is ObservableValueGroup<string> group)
{
group.Remove(i18nValue(i18nModel.I18nDatas[culture.Value]));
if (group.Count == 1)
{
group.Clear();
return;
}
}
else
{
I18nDatas.Remove(data);
AllI18nDatas.Remove(id.Value);
return;
}
}
}
// /// <summary>
// /// 载入宠物
// /// </summary>
// /// <param name="model"></param>
// public void LoadPets(ModInfoModel model)
// {
// foreach (var pet in model.Pets)
// {
// if (pet.FromMain.Value)
// continue;
// AddData(pet.ID, pet, (m) => m.Name);
// AddData(pet.PetNameId, pet, (m) => m.PetName);
// AddData(pet.DescriptionId, pet, (m) => m.Description);
// foreach (var work in pet.Works)
// AddData(work.Id, work, (m) => m.Name);
// }
// model.Pets.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (PetModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Name);
// AddData(newModel.DescriptionId, newModel, (m) => m.Description);
// foreach (var work in newModel.Works)
// AddData(work.Id, work, (m) => m.Name);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (PetModel)e.OldItems[0];
// if (oldModel.FromMain.Value)
// return;
// RemoveData(oldModel.ID, oldModel, (m) => m.Name);
// RemoveData(oldModel.DescriptionId, oldModel, (m) => m.Description);
// foreach (var work in oldModel.Works)
// RemoveData(work.Id, work, (m) => m.Name);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (PetModel)e.NewItems[0];
// var oldModel = (PetModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Name);
// ReplaceData(newModel.DescriptionId, newModel, (m) => m.Description);
// foreach (var work in newModel.Works)
// ReplaceData(work.Id, work, (m) => m.Name);
// }
// };
// }
// #endregion
/// <summary>
/// 替换I18n数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <param name="i18nModel"></param>
/// <param name="i18nValue"></param>
private void ReplaceData<T>(
ObservableValue<string> id,
I18nModel<T> i18nModel,
Func<T, ObservableValue<string>> i18nValue
)
where T : class, new()
{
var data = AllI18nDatas[id.Value];
foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
{
var oldValue = data.Datas[culture.Index];
var newValue = i18nValue(i18nModel.I18nDatas[culture.Value]);
if (oldValue.Group is ObservableValueGroup<string> group)
{
group.Add(newValue);
group.Remove(oldValue);
}
data.Datas[culture.Index] = newValue;
}
}
#endregion
// #region DatEdit
// /// <summary>
// /// 添加数据
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void AddData<T>(
// ObservableValue<string> id,
// I18nModel<T> i18nModel,
// Func<T, ObservableValue<string>> i18nValue
// )
// where T : class, new()
// {
// if (AllI18nDatas.TryGetValue(id.Value, out var outData))
// {
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (outData.Datas[culture.Index].Group is null)
// {
// var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
// }
// outData
// .Datas[culture.Index]
// .Group!.Add(i18nValue(i18nModel.I18nDatas[culture.Value]));
// }
// }
// else
// {
// var data = new I18nData();
// data.Id = id.Value;
// foreach (var culture in I18nHelper.Current.CultureNames)
// data.Datas.Add(i18nValue(i18nModel.I18nDatas[culture]));
// I18nDatas.Add(data);
// AllI18nDatas.Add(id.Value, data);
// //id.ValueChanged += IdChange;
// }
// }
public void Close()
{
I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
foreach (var i18nData in AllI18nDatas)
{
foreach (var data in i18nData.Value.Datas)
data.Group?.Clear();
}
}
// /// <summary>
// /// Id改变
// /// </summary>
// /// <param name="oldValue"></param>
// /// <param name="newValue"></param>
// private void IdChange(ObservableValue<string> sender, ValueChangedEventArgs<string> e)
// {
// var sourceData = AllI18nDatas[e.OldValue];
// //sourceData.Id.Group?.Remove(sourceData.Id); //TODO
// if (AllI18nDatas.TryGetValue(e.OldValue, out var outData))
// {
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (outData.Datas[culture.Index].Group is null)
// {
// var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
// }
// outData.Datas[culture.Index].Group!.Add(sourceData.Datas[culture.Index]);
// }
// }
// else
// {
// sourceData.Id = e.NewValue;
// AllI18nDatas.Remove(e.OldValue);
// AllI18nDatas.Add(e.NewValue, sourceData);
// }
// }
#region Event
private void AddCulture(string culture)
{
CultureChanged?.Invoke(null, culture);
}
// /// <summary>
// /// 删除I18n数据
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void RemoveData<T>(
// ObservableValue<string> id,
// I18nModel<T> i18nModel,
// Func<T, ObservableValue<string>> i18nValue
// )
// where T : class, new()
// {
// var data = AllI18nDatas[id.Value];
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (data.Datas[culture.Index].Group is ObservableValueGroup<string> group)
// {
// group.Remove(i18nValue(i18nModel.I18nDatas[culture.Value]));
// if (group.Count == 1)
// {
// group.Clear();
// return;
// }
// }
// else
// {
// I18nDatas.Remove(data);
// AllI18nDatas.Remove(id.Value);
// return;
// }
// }
// }
private void RemoveCulture(string culture)
{
CultureChanged?.Invoke(culture, string.Empty);
}
// /// <summary>
// /// 替换I18n数据
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void ReplaceData<T>(
// ObservableValue<string> id,
// I18nModel<T> i18nModel,
// Func<T, ObservableValue<string>> i18nValue
// )
// where T : class, new()
// {
// var data = AllI18nDatas[id.Value];
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// var oldValue = data.Datas[culture.Index];
// var newValue = i18nValue(i18nModel.I18nDatas[culture.Value]);
// if (oldValue.Group is ObservableValueGroup<string> group)
// {
// group.Add(newValue);
// group.Remove(oldValue);
// }
// data.Datas[culture.Index] = newValue;
// }
// }
// #endregion
private void ReplaceCulture(string oldCulture, string newCulture)
{
CultureChanged?.Invoke(oldCulture, newCulture);
}
// public void Close()
// {
// I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
// foreach (var i18nData in AllI18nDatas)
// {
// foreach (var data in i18nData.Value.Datas)
// data.Group?.Clear();
// }
// }
public event EventHandler<string> CultureChanged;
#endregion
}
// #region Event
// private void AddCulture(string culture)
// {
// CultureChanged?.Invoke(null, culture);
// }
// private void RemoveCulture(string culture)
// {
// CultureChanged?.Invoke(culture, string.Empty);
// }
// private void ReplaceCulture(string oldCulture, string newCulture)
// {
// CultureChanged?.Invoke(oldCulture, newCulture);
// }
// public event EventHandler<string> CultureChanged;
// #endregion
//}

View File

@ -1,21 +1,32 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet.ModMaker.Models;
using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.LowTextEdit;
public class LowTextEditWindowVM
public class LowTextEditWindowVM : ObservableObjectX<LowTextEditWindowVM>
{
public I18nHelper I18nData => I18nHelper.Current;
#region Value
public LowTextModel OldLowText { get; set; }
public ObservableValue<LowTextModel> LowText { get; } = new(new());
#region LowText
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowTextModel _lowText;
public LowTextModel LowText
{
get => _lowText;
set => SetProperty(ref _lowText, value);
}
#endregion
#endregion

View File

@ -1,27 +1,46 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views.ModEdit.LowTextEdit;
using Expression = System.Linq.Expressions.Expression;
namespace VPet.ModMaker.ViewModels.ModEdit.LowTextEdit;
public class LowTextPageVM
public class LowTextPageVM : ObservableObjectX<LowTextPageVM>
{
#region Value
public ObservableValue<ObservableCollection<LowTextModel>> ShowLowTexts { get; } = new();
#region ShowLowTexts
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<LowTextModel> _showLowTexts;
public ObservableCollection<LowTextModel> ShowLowTexts
{
get => _showLowTexts;
set => SetProperty(ref _showLowTexts, value);
}
#endregion
public ObservableCollection<LowTextModel> LowTexts => ModInfoModel.Current.LowTexts;
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -31,8 +50,8 @@ public class LowTextPageVM
public LowTextPageVM()
{
ShowLowTexts.Value = LowTexts;
Search.ValueChanged += Search_ValueChanged;
ShowLowTexts = LowTexts;
//Search.ValueChanged += Search_ValueChanged;//TODO
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
@ -45,14 +64,12 @@ public class LowTextPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowLowTexts.Value = LowTexts;
ShowLowTexts = LowTexts;
}
else
{
ShowLowTexts.Value = new(
LowTexts.Where(
m => m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
ShowLowTexts = new(
LowTexts.Where(m => m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -64,7 +81,7 @@ public class LowTextPageVM
window.ShowDialog();
if (window.IsCancel)
return;
LowTexts.Add(vm.LowText.Value);
LowTexts.Add(vm.LowText);
}
public void Edit(LowTextModel model)
@ -72,26 +89,26 @@ public class LowTextPageVM
var window = new LowTextEditWindow();
var vm = window.ViewModel;
vm.OldLowText = model;
var newLowTest = vm.LowText.Value = new(model);
var newLowTest = vm.LowText = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
LowTexts[LowTexts.IndexOf(model)] = newLowTest;
if (ShowLowTexts.Value.Count != LowTexts.Count)
ShowLowTexts.Value[ShowLowTexts.Value.IndexOf(model)] = newLowTest;
if (ShowLowTexts.Count != LowTexts.Count)
ShowLowTexts[ShowLowTexts.IndexOf(model)] = newLowTest;
}
private void Remove(LowTextModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowLowTexts.Value.Count == LowTexts.Count)
if (ShowLowTexts.Count == LowTexts.Count)
{
LowTexts.Remove(model);
}
else
{
ShowLowTexts.Value.Remove(model);
ShowLowTexts.Remove(model);
LowTexts.Remove(model);
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@ -21,7 +22,7 @@ using VPet.ModMaker.Views.ModEdit.I18nEdit;
namespace VPet.ModMaker.ViewModels.ModEdit;
public class ModEditWindowVM
public class ModEditWindowVM : ObservableObjectX<ModEditWindowVM>
{
public ModEditWindow ModEditWindow { get; }
@ -29,7 +30,16 @@ public class ModEditWindowVM
/// <summary>
/// 当前模组信息
/// </summary>
public ObservableValue<ModInfoModel> ModInfo { get; } = new(ModInfoModel.Current);
#region ModInfo
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ModInfoModel _modInfo = ModInfoModel.Current;
public ModInfoModel ModInfo
{
get => _modInfo;
set => SetProperty(ref _modInfo, value);
}
#endregion
/// <summary>
/// I18n数据
@ -103,7 +113,7 @@ public class ModEditWindowVM
private void SaveAsTranslationMod()
{
if (ValidationData(ModInfo.Value) is false)
if (ValidationData(ModInfo) is false)
return;
var window = new SaveTranslationModWindow();
window.ShowDialog();
@ -120,7 +130,7 @@ public class ModEditWindowVM
/// </summary>
public void Close()
{
ModInfo.Value.Image.Value?.StreamSource?.Close();
ModInfo.Image?.StreamSource?.Close();
I18nEditWindow.Current?.Close(true);
}
@ -137,10 +147,8 @@ public class ModEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
ModInfo.Value.Image.Value?.StreamSource?.Close();
ModInfo.Value.Image.Value = NativeUtils.LoadImageToMemoryStream(
openFileDialog.FileName
);
ModInfo.Image?.StreamSource?.Close();
ModInfo.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -154,9 +162,9 @@ public class ModEditWindowVM
window.ShowDialog();
if (window.IsCancel)
return;
I18nHelper.Current.CultureNames.Add(window.ViewModel.Culture.Value);
I18nHelper.Current.CultureNames.Add(window.ViewModel.Culture);
if (I18nHelper.Current.CultureNames.Count == 1)
I18nHelper.Current.CultureName.Value = window.ViewModel.Culture.Value;
I18nHelper.Current.CultureName = window.ViewModel.Culture;
}
/// <summary>
@ -166,12 +174,12 @@ public class ModEditWindowVM
private void EditCulture(string oldCulture)
{
var window = new AddCultureWindow();
window.ViewModel.Culture.Value = oldCulture.Translate();
window.ViewModel.Culture = oldCulture.Translate();
window.ShowDialog();
if (window.IsCancel)
return;
I18nHelper.Current.CultureNames[I18nHelper.Current.CultureNames.IndexOf(oldCulture)] =
window.ViewModel.Culture.Value;
window.ViewModel.Culture;
}
/// <summary>
@ -202,29 +210,29 @@ public class ModEditWindowVM
is not MessageBoxResult.Yes
)
return;
ModInfo.Value.I18nDatas[culture].Name.Value = ModInfo.Value.Id.Value;
ModInfo.Value.I18nDatas[culture].Description.Value = ModInfo.Value.DescriptionId.Value;
foreach (var food in ModInfo.Value.Foods)
ModInfo.I18nDatas[culture].Name = ModInfo.Id;
ModInfo.I18nDatas[culture].Description = ModInfo.DescriptionId;
foreach (var food in ModInfo.Foods)
{
food.I18nDatas[culture].Name.Value = food.Id.Value;
food.I18nDatas[culture].Description.Value = food.DescriptionId.Value;
food.I18nDatas[culture].Name = food.Id;
food.I18nDatas[culture].Description = food.DescriptionId;
}
foreach (var text in ModInfo.Value.LowTexts)
text.I18nDatas[culture].Text.Value = text.Id.Value;
foreach (var text in ModInfo.Value.ClickTexts)
text.I18nDatas[culture].Text.Value = text.Id.Value;
foreach (var text in ModInfo.Value.SelectTexts)
foreach (var text in ModInfo.LowTexts)
text.I18nDatas[culture].Text = text.Id;
foreach (var text in ModInfo.ClickTexts)
text.I18nDatas[culture].Text = text.Id;
foreach (var text in ModInfo.SelectTexts)
{
text.I18nDatas[culture].Text.Value = text.Id.Value;
text.I18nDatas[culture].Choose.Value = text.ChooseId.Value;
text.I18nDatas[culture].Text = text.Id;
text.I18nDatas[culture].Choose = text.ChooseId;
}
foreach (var pet in ModInfo.Value.Pets)
foreach (var pet in ModInfo.Pets)
{
pet.I18nDatas[culture].Name.Value = pet.Id.Value;
pet.I18nDatas[culture].PetName.Value = pet.PetNameId.Value;
pet.I18nDatas[culture].Description.Value = pet.DescriptionId.Value;
pet.I18nDatas[culture].Name = pet.ID;
pet.I18nDatas[culture].PetName = pet.PetNameId;
pet.I18nDatas[culture].Description = pet.DescriptionId;
foreach (var work in pet.Works)
work.I18nDatas[culture].Name.Value = work.Id.Value;
work.I18nDatas[culture].Name = work.Id;
}
}
#endregion
@ -235,19 +243,19 @@ public class ModEditWindowVM
/// </summary>
private void Save()
{
if (ValidationData(ModInfo.Value) is false)
if (ValidationData(ModInfo) is false)
return;
if (
MessageBox.Show("确定保存吗".Translate(), "", MessageBoxButton.YesNo)
is not MessageBoxResult.Yes
)
return;
if (string.IsNullOrEmpty(ModInfo.Value.SourcePath.Value))
if (string.IsNullOrEmpty(ModInfo.SourcePath))
{
MessageBox.Show("源路径为空, 请使用 保存至".Translate());
return;
}
SaveTo(ModInfo.Value.SourcePath.Value);
SaveTo(ModInfo.SourcePath);
}
/// <summary>
@ -255,7 +263,7 @@ public class ModEditWindowVM
/// </summary>
private void SaveTo()
{
if (ValidationData(ModInfo.Value) is false)
if (ValidationData(ModInfo) is false)
return;
var dialog = new VistaFolderBrowserDialog();
if (dialog.ShowDialog() is not true)
@ -272,9 +280,9 @@ public class ModEditWindowVM
var pending = PendingBox.Show("保存中".Translate());
try
{
ModInfo.Value.SaveTo(path);
if (string.IsNullOrWhiteSpace(ModInfo.Value.SourcePath.Value))
ModInfo.Value.SourcePath.Value = path;
ModInfo.SaveTo(path);
if (string.IsNullOrWhiteSpace(ModInfo.SourcePath))
ModInfo.SourcePath = path;
pending.Close();
MessageBox.Show(ModEditWindow, "保存成功".Translate());
}
@ -303,12 +311,12 @@ public class ModEditWindowVM
);
return false;
}
if (string.IsNullOrWhiteSpace(model.Id.Value))
if (string.IsNullOrWhiteSpace(model.Id))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return false;
}
if (string.IsNullOrWhiteSpace(model.Author.Value))
if (string.IsNullOrWhiteSpace(model.Author))
{
MessageBox.Show("作者不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return false;

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -11,16 +12,53 @@ using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit;
public class MoveEditWindowVM
public class MoveEditWindowVM : ObservableObjectX<MoveEditWindowVM>
{
#region Value
public PetModel CurrentPet { get; set; }
public MoveModel OldMove { get; set; }
public ObservableValue<MoveModel> Move { get; } = new(new());
#region Move
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private MoveModel _move = new();
public MoveModel Move
{
get => _move;
set => SetProperty(ref _move, value);
}
#endregion
#endregion
#region BorderLength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _borderLength = 250;
public double BorderLength
{
get => _borderLength;
set => SetProperty(ref _borderLength, value);
}
#endregion
#region LengthRatio
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _lengthRatio = 250 / 500;
public double LengthRatio
{
get => _lengthRatio;
set => SetProperty(ref _lengthRatio, value);
}
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
public ObservableValue<double> BorderLength { get; } = new(250);
public ObservableValue<double> LengthRatio { get; } = new(250.0 / 500.0);
public ObservableValue<BitmapImage> Image { get; } = new();
#region Command
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
@ -29,7 +67,8 @@ public class MoveEditWindowVM
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
Image.ValueChanged += Image_ValueChanged;
//TODO
//Image.ValueChanged += Image_ValueChanged;
}
private void Image_ValueChanged(
@ -42,7 +81,7 @@ public class MoveEditWindowVM
public void Close()
{
Image.Value?.StreamSource?.Close();
Image?.StreamSource?.Close();
}
private void AddImage()
@ -55,7 +94,7 @@ public class MoveEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -69,8 +108,8 @@ public class MoveEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Image.Value?.StreamSource?.Close();
Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image?.StreamSource?.Close();
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
}

View File

@ -1,28 +1,48 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views.ModEdit.MoveEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.MoveEdit;
public class MovePageVM
public class MovePageVM : ObservableObjectX<MovePageVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
public ObservableValue<ObservableCollection<MoveModel>> ShowMoves { get; } = new();
#region ShowMoves
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<MoveModel> _showMoves;
public ObservableCollection<MoveModel> ShowMoves
{
get => _showMoves;
set => SetProperty(ref _showMoves, value);
}
#endregion
public ObservableCollection<MoveModel> Moves => CurrentPet.Value.Moves;
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public ObservableValue<PetModel> CurrentPet { get; } = new(new());
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -31,9 +51,10 @@ public class MovePageVM
#endregion
public MovePageVM()
{
ShowMoves.Value = Moves;
ShowMoves = Moves;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
Search.ValueChanged += Search_ValueChanged;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
@ -45,7 +66,7 @@ public class MovePageVM
ValueChangedEventArgs<PetModel> e
)
{
ShowMoves.Value = e.NewValue.Moves;
//ShowMoves.Value = e.NewValue.Moves;
}
private void Search_ValueChanged(
@ -55,14 +76,12 @@ public class MovePageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowMoves.Value = Moves;
ShowMoves = Moves;
}
else
{
ShowMoves.Value = new(
Moves.Where(
m => m.Graph.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
ShowMoves = new(
Moves.Where(m => m.Graph.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -77,7 +96,7 @@ public class MovePageVM
window.ShowDialog();
if (window.IsCancel)
return;
Moves.Add(vm.Move.Value);
Moves.Add(vm.Move);
}
public void Edit(MoveModel model)
@ -86,26 +105,26 @@ public class MovePageVM
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.OldMove = model;
var newMove = vm.Move.Value = new(model);
var newMove = vm.Move = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
Moves[Moves.IndexOf(model)] = newMove;
if (ShowMoves.Value.Count != Moves.Count)
ShowMoves.Value[ShowMoves.Value.IndexOf(model)] = newMove;
if (ShowMoves.Count != Moves.Count)
ShowMoves[ShowMoves.IndexOf(model)] = newMove;
}
private void Remove(MoveModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowMoves.Value.Count == Moves.Count)
if (ShowMoves.Count == Moves.Count)
{
Moves.Remove(model);
}
else
{
ShowMoves.Value.Remove(model);
ShowMoves.Remove(model);
Moves.Remove(model);
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -12,15 +13,52 @@ using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.PetEdit;
public class PetEditWindowVM
public class PetEditWindowVM : ObservableObjectX<PetEditWindowVM>
{
public I18nHelper I18nData => I18nHelper.Current;
public PetModel OldPet { get; set; }
public ObservableValue<PetModel> Pet { get; } = new(new());
public ObservableValue<double> BorderLength { get; } = new(250);
public ObservableValue<double> LengthRatio { get; } = new(250.0 / 500.0);
public ObservableValue<BitmapImage> Image { get; } = new();
#region Pet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _Pet;
public PetModel Pet
{
get => _Pet;
set => SetProperty(ref _Pet, value);
}
#endregion
#region BorderLength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _borderLength = 250;
public double BorderLength
{
get => _borderLength;
set => SetProperty(ref _borderLength, value);
}
#endregion
#region LengthRatio
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _lengthRatio = 250 / 500;
public double LengthRatio
{
get => _lengthRatio;
set => SetProperty(ref _lengthRatio, value);
}
#endregion
#region Image
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private BitmapImage _image;
public BitmapImage Image
{
get => _image;
set => SetProperty(ref _image, value);
}
#endregion
#region Command
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
@ -29,7 +67,8 @@ public class PetEditWindowVM
{
AddImageCommand.ExecuteCommand += AddImage;
ChangeImageCommand.ExecuteCommand += ChangeImage;
Image.ValueChanged += Image_ValueChanged;
//TODO
//Image.ValueChanged += Image_ValueChanged;
}
private void Image_ValueChanged(
@ -42,7 +81,7 @@ public class PetEditWindowVM
public void Close()
{
Image.Value?.CloseStream();
Image?.CloseStream();
}
private void AddImage()
@ -55,7 +94,7 @@ public class PetEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -69,8 +108,8 @@ public class PetEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Image.Value?.StreamSource?.Close();
Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Image?.StreamSource?.Close();
Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
}

View File

@ -1,27 +1,46 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.ViewModels.ModEdit.I18nEdit;
using VPet.ModMaker.Views.ModEdit.I18nEdit;
using VPet.ModMaker.Views.ModEdit.PetEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.PetEdit;
public class PetPageVM
public class PetPageVM : ObservableObjectX<PetPageVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
public ObservableValue<ObservableCollection<PetModel>> ShowPets { get; } = new();
#region ShowPets
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<PetModel> _showPets;
public ObservableCollection<PetModel> ShowPets
{
get => _showPets;
set => SetProperty(ref _showPets, value);
}
#endregion
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -30,8 +49,9 @@ public class PetPageVM
#endregion
public PetPageVM()
{
ShowPets.Value = Pets;
Search.ValueChanged += Search_ValueChanged;
//TODO
//ShowPets = Pets;
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
@ -45,12 +65,12 @@ public class PetPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowPets.Value = Pets;
ShowPets = Pets;
}
else
{
ShowPets.Value = new(
Pets.Where(m => m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
ShowPets = new(
Pets.Where(m => m.ID.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -64,12 +84,12 @@ public class PetPageVM
window.ShowDialog();
if (window.IsCancel)
return;
Pets.Add(vm.Pet.Value);
Pets.Add(vm.Pet);
}
public void Edit(PetModel model)
{
if (model.FromMain.Value)
if (model.FromMain)
{
if (
MessageBox.Show("这是本体自带的宠物, 确定要编辑吗".Translate(), "", MessageBoxButton.YesNo)
@ -80,11 +100,11 @@ public class PetPageVM
var window = new PetEditWindow();
var vm = window.ViewModel;
vm.OldPet = model;
var newPet = vm.Pet.Value = new(model);
var newPet = vm.Pet = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
if (model.FromMain.Value)
if (model.FromMain)
{
var index = Pets.IndexOf(model);
Pets.Remove(model);
@ -94,27 +114,27 @@ public class PetPageVM
{
Pets[Pets.IndexOf(model)] = newPet;
}
if (ShowPets.Value.Count != Pets.Count)
ShowPets.Value[ShowPets.Value.IndexOf(model)] = newPet;
if (ShowPets.Count != Pets.Count)
ShowPets[ShowPets.IndexOf(model)] = newPet;
model.Close();
}
private void Remove(PetModel model)
{
if (model.FromMain.Value)
if (model.FromMain)
{
MessageBox.Show("这是本体自带的宠物, 无法删除".Translate());
return;
}
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowPets.Value.Count == Pets.Count)
if (ShowPets.Count == Pets.Count)
{
Pets.Remove(model);
}
else
{
ShowPets.Value.Remove(model);
ShowPets.Remove(model);
Pets.Remove(model);
}
}

View File

@ -1,23 +1,33 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit;
public class SaveTranslationModWindowVM
public class SaveTranslationModWindowVM : ObservableObjectX<SaveTranslationModWindowVM>
{
#region Value
public ObservableValue<bool?> CheckAll { get; } = new(true);
#region CheckAll
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool? _checkAll;
public bool? CheckAll
{
get => _checkAll;
set => SetProperty(ref _checkAll, value);
}
#endregion
public ObservableCollection<CheckCultureModel> CheckCultures { get; } = [];
#endregion
@ -28,37 +38,44 @@ public class SaveTranslationModWindowVM
public SaveTranslationModWindowVM()
{
foreach (var culture in I18nHelper.Current.CultureNames)
{
var model = new CheckCultureModel();
model.CultureName.Value = culture;
CheckCultures.Add(model);
CheckAll.AddNotifySender(model.IsChecked);
}
CheckAll.ValueChanged += CheckAll_ValueChanged;
CheckAll.SenderPropertyChanged += CheckAll_SenderPropertyChanged;
SaveCommand.ExecuteCommand += Save;
//TODO
//foreach (var culture in I18nHelper.Current.CultureNames)
//{
// var model = new CheckCultureModel();
// model.CultureName.Value = culture;
// CheckCultures.Add(model);
// CheckAll.AddNotifySender(model.IsChecked);
//}
//CheckAll.ValueChanged += CheckAll_ValueChanged;
//CheckAll.SenderPropertyChanged += CheckAll_SenderPropertyChanged;
//SaveCommand.ExecuteCommand += Save;
}
private void CheckAll_ValueChanged(ObservableValue<bool?> sender, ValueChangedEventArgs<bool?> e)
private void CheckAll_ValueChanged(
ObservableValue<bool?> sender,
ValueChangedEventArgs<bool?> e
)
{
if (e.NewValue is null)
{
if (CheckCultures.All(m => m.IsChecked.Value))
CheckAll.Value = false;
else if (CheckCultures.All(m => m.IsChecked.Value is false))
CheckAll.Value = true;
if (CheckCultures.All(m => m.IsChecked))
CheckAll = false;
else if (CheckCultures.All(m => m.IsChecked is false))
CheckAll = true;
return;
}
foreach (var model in CheckCultures)
model.IsChecked.Value = e.NewValue.Value;
model.IsChecked = e.NewValue.Value;
}
private void CheckAll_SenderPropertyChanged(ObservableValue<bool?> source, INotifyPropertyChanged sender)
private void CheckAll_SenderPropertyChanged(
ObservableValue<bool?> source,
INotifyPropertyChanged sender
)
{
var count = 0;
foreach (var model in CheckCultures)
if (model.IsChecked.Value)
if (model.IsChecked)
count += 1;
if (count == CheckCultures.Count)
@ -71,17 +88,21 @@ public class SaveTranslationModWindowVM
public void Save()
{
SaveFileDialog saveFileDialog = new()
{
Title = "保存模组信息文件,并在文件夹内保存模组数据".Translate(),
Filter = $"LPS文件|*.lps;".Translate(),
FileName = "info.lps".Translate()
};
SaveFileDialog saveFileDialog =
new()
{
Title = "保存模组信息文件,并在文件夹内保存模组数据".Translate(),
Filter = $"LPS文件|*.lps;".Translate(),
FileName = "info.lps".Translate()
};
if (saveFileDialog.ShowDialog() is not true)
return;
try
{
ModInfoModel.Current.SaveTranslationMod(Path.GetDirectoryName(saveFileDialog.FileName), CheckCultures.Where(m => m.IsChecked.Value).Select(m => m.CultureName.Value));
ModInfoModel.Current.SaveTranslationMod(
Path.GetDirectoryName(saveFileDialog.FileName),
CheckCultures.Where(m => m.IsChecked).Select(m => m.CultureName)
);
MessageBox.Show("保存成功".Translate());
}
catch (Exception ex)
@ -91,8 +112,26 @@ public class SaveTranslationModWindowVM
}
}
public class CheckCultureModel
public class CheckCultureModel : ObservableObjectX<CheckCultureModel>
{
public ObservableValue<bool> IsChecked { get; } = new(true);
public ObservableValue<string> CultureName { get; } = new();
#region IsChecked
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _isChecked;
public bool IsChecked
{
get => _isChecked;
set => SetProperty(ref _isChecked, value);
}
#endregion
#region CultureName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _cultureName = string.Empty;
public string CultureName
{
get => _cultureName;
set => SetProperty(ref _cultureName, value);
}
#endregion
}

View File

@ -1,18 +1,29 @@
using HKW.HKWUtils.Observable;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.SelectTextEdit;
public class SelectTextEditWindowVM
public class SelectTextEditWindowVM : ObservableObjectX<SelectTextEditWindowVM>
{
public I18nHelper I18nData => I18nHelper.Current;
#region Value
public SelectTextModel OldSelectText { get; set; }
public ObservableValue<SelectTextModel> SelectText { get; } = new(new());
#region SelectText
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private SelectTextModel _selectText = new();
public SelectTextModel SelectText
{
get => _selectText;
set => SetProperty(ref _selectText, value);
}
#endregion
#endregion
}

View File

@ -1,24 +1,43 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views.ModEdit.SelectTextEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.SelectTextEdit;
public class SelectTextPageVM
public class SelectTextPageVM : ObservableObjectX<SelectTextPageVM>
{
#region Value
public ObservableValue<ObservableCollection<SelectTextModel>> ShowSelectTexts { get; } = new();
#region ShowSelectTexts
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<SelectTextModel> _showSelectTexts;
public ObservableCollection<SelectTextModel> ShowSelectTexts
{
get => _showSelectTexts;
set => SetProperty(ref _showSelectTexts, value);
}
#endregion
public ObservableCollection<SelectTextModel> SelectTexts => ModInfoModel.Current.SelectTexts;
public ObservableValue<string> Search { get; } = new();
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -28,8 +47,9 @@ public class SelectTextPageVM
public SelectTextPageVM()
{
ShowSelectTexts.Value = SelectTexts;
Search.ValueChanged += Search_ValueChanged;
ShowSelectTexts = SelectTexts;
//TODO
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
RemoveCommand.ExecuteCommand += Remove;
@ -42,13 +62,13 @@ public class SelectTextPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowSelectTexts.Value = SelectTexts;
ShowSelectTexts = SelectTexts;
}
else
{
ShowSelectTexts.Value = new(
SelectTexts.Where(
m => m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
ShowSelectTexts = new(
SelectTexts.Where(m =>
m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
);
}
@ -61,7 +81,7 @@ public class SelectTextPageVM
window.ShowDialog();
if (window.IsCancel)
return;
SelectTexts.Add(vm.SelectText.Value);
SelectTexts.Add(vm.SelectText);
}
public void Edit(SelectTextModel model)
@ -69,26 +89,26 @@ public class SelectTextPageVM
var window = new SelectTextEditWindow();
var vm = window.ViewModel;
vm.OldSelectText = model;
var newLowTest = vm.SelectText.Value = new(model);
var newLowTest = vm.SelectText = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
SelectTexts[SelectTexts.IndexOf(model)] = newLowTest;
if (ShowSelectTexts.Value.Count != SelectTexts.Count)
ShowSelectTexts.Value[ShowSelectTexts.Value.IndexOf(model)] = newLowTest;
if (ShowSelectTexts.Count != SelectTexts.Count)
ShowSelectTexts[ShowSelectTexts.IndexOf(model)] = newLowTest;
}
private void Remove(SelectTextModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowSelectTexts.Value.Count == SelectTexts.Count)
if (ShowSelectTexts.Count == SelectTexts.Count)
{
SelectTexts.Remove(model);
}
else
{
ShowSelectTexts.Value.Remove(model);
ShowSelectTexts.Remove(model);
SelectTexts.Remove(model);
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -12,17 +13,45 @@ using VPet_Simulator.Windows.Interface;
namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit;
public class WorkEditWindowVM
public class WorkEditWindowVM : ObservableObjectX<WorkEditWindowVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
public static I18nHelper I18nData => I18nHelper.Current;
#region Value
public PetModel CurrentPet { get; set; }
public WorkModel OldWork { get; set; }
public ObservableValue<WorkModel> Work { get; } = new(new());
#region Work
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private WorkModel _work;
public WorkModel Work
{
get => _work;
set => SetProperty(ref _work, value);
}
#endregion
#endregion
#region BorderLength
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _borderLength = 250;
public double BorderLength
{
get => _borderLength;
set => SetProperty(ref _borderLength, value);
}
#endregion
#region LengthRatio
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private double _lengthRatio = 250 / 500;
public double LengthRatio
{
get => _lengthRatio;
set => SetProperty(ref _lengthRatio, value);
}
#endregion
public ObservableValue<double> BorderLength { get; } = new(250);
public ObservableValue<double> LengthRatio { get; } = new(250.0 / 500.0);
#region Command
public ObservableCommand AddImageCommand { get; } = new();
public ObservableCommand ChangeImageCommand { get; } = new();
@ -38,9 +67,9 @@ public class WorkEditWindowVM
private void FixOverLoadCommand_ExecuteCommand()
{
var work = Work.Value.ToWork();
work.FixOverLoad();
Work.Value = new(work);
//var work = Work.ToWork();
//work.FixOverLoad();
//Work = new(work);
}
private void AddImage()
@ -53,7 +82,7 @@ public class WorkEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Work.Value.Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Work.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
@ -67,8 +96,8 @@ public class WorkEditWindowVM
};
if (openFileDialog.ShowDialog() is true)
{
Work.Value.Image.Value?.CloseStream();
Work.Value.Image.Value = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
Work.Image?.CloseStream();
Work.Image = NativeUtils.LoadImageToMemoryStream(openFileDialog.FileName);
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -12,16 +13,46 @@ using VPet.ModMaker.Views.ModEdit.WorkEdit;
namespace VPet.ModMaker.ViewModels.ModEdit.WorkEdit;
public class WorkPageVM
public class WorkPageVM : ObservableObjectX<WorkPageVM>
{
public static ModInfoModel ModInfo => ModInfoModel.Current;
#region Value
public ObservableValue<ObservableCollection<WorkModel>> ShowWorks { get; } = new();
public ObservableCollection<WorkModel> Works => CurrentPet.Value.Works;
#region ShowWorks
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<WorkModel> _showWorks;
public ObservableCollection<WorkModel> ShowWorks
{
get => _showWorks;
set => SetProperty(ref _showWorks, value);
}
#endregion
public ObservableCollection<WorkModel> Works => CurrentPet.Works;
public ObservableCollection<PetModel> Pets => ModInfoModel.Current.Pets;
public ObservableValue<PetModel> CurrentPet { get; } = new(new());
public ObservableValue<string> Search { get; } = new();
#region CurrentPet
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private PetModel _currentPet;
public PetModel CurrentPet
{
get => _currentPet;
set => SetProperty(ref _currentPet, value);
}
#endregion
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search;
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
#endregion
#region Command
public ObservableCommand AddCommand { get; } = new();
@ -30,9 +61,10 @@ public class WorkPageVM
#endregion
public WorkPageVM()
{
ShowWorks.Value = Works;
CurrentPet.ValueChanged += CurrentPet_ValueChanged;
Search.ValueChanged += Search_ValueChanged;
ShowWorks = Works;
//TODO
//CurrentPet.ValueChanged += CurrentPet_ValueChanged;
//Search.ValueChanged += Search_ValueChanged;
AddCommand.ExecuteCommand += Add;
EditCommand.ExecuteCommand += Edit;
@ -44,7 +76,7 @@ public class WorkPageVM
ValueChangedEventArgs<PetModel> e
)
{
ShowWorks.Value = e.NewValue.Works;
ShowWorks = e.NewValue.Works;
}
private void Search_ValueChanged(
@ -54,14 +86,12 @@ public class WorkPageVM
{
if (string.IsNullOrWhiteSpace(e.NewValue))
{
ShowWorks.Value = Works;
ShowWorks = Works;
}
else
{
ShowWorks.Value = new(
Works.Where(m =>
m.Id.Value.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase)
)
ShowWorks = new(
Works.Where(m => m.Id.Contains(e.NewValue, StringComparison.OrdinalIgnoreCase))
);
}
}
@ -70,39 +100,39 @@ public class WorkPageVM
{
var window = new WorkEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
window.ShowDialog();
if (window.IsCancel)
return;
Works.Add(vm.Work.Value);
Works.Add(vm.Work);
}
public void Edit(WorkModel model)
{
var window = new WorkEditWindow();
var vm = window.ViewModel;
vm.CurrentPet = CurrentPet.Value;
vm.CurrentPet = CurrentPet;
vm.OldWork = model;
var newWork = vm.Work.Value = new(model);
var newWork = vm.Work = new(model);
window.ShowDialog();
if (window.IsCancel)
return;
Works[Works.IndexOf(model)] = newWork;
if (ShowWorks.Value.Count != Works.Count)
ShowWorks.Value[ShowWorks.Value.IndexOf(model)] = newWork;
if (ShowWorks.Count != Works.Count)
ShowWorks[ShowWorks.IndexOf(model)] = newWork;
}
private void Remove(WorkModel model)
{
if (MessageBox.Show("确定删除吗".Translate(), "", MessageBoxButton.YesNo) is MessageBoxResult.No)
return;
if (ShowWorks.Value.Count == Works.Count)
if (ShowWorks.Count == Works.Count)
{
Works.Remove(model);
}
else
{
ShowWorks.Value.Remove(model);
ShowWorks.Remove(model);
Works.Remove(model);
}
}

View File

@ -1,18 +1,19 @@
using HKW.HKWUtils.Observable;
using LinePutScript;
using LinePutScript.Converter;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using Panuon.WPF.UI;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using HKW.HKWUtils.Observable;
using LinePutScript;
using LinePutScript.Converter;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using Panuon.WPF.UI;
using VPet.ModMaker.Models;
using VPet.ModMaker.Views;
using VPet.ModMaker.Views.ModEdit;
@ -20,7 +21,7 @@ using VPet.ModMaker.Views.ModEdit.I18nEdit;
namespace VPet.ModMaker.ViewModels;
public class ModMakerWindowVM
public class ModMakerWindowVM : ObservableObjectX<ModMakerWindowVM>
{
#region Value
public ModMakerWindow ModMakerWindow { get; }
@ -30,12 +31,30 @@ public class ModMakerWindowVM
/// <summary>
/// 历史搜索文本
/// </summary>
public ObservableValue<string> HistoriesSearchText { get; } = new();
#region HistoriesSearchText
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _historiesSearchText;
public string HistoriesSearchText
{
get => _historiesSearchText;
set => SetProperty(ref _historiesSearchText, value);
}
#endregion
/// <summary>
/// 显示的历史
/// </summary>
public ObservableValue<ObservableCollection<ModMakeHistory>> ShowHistories { get; } = new();
#region ShowHistories
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObservableCollection<ModMakeHistory> _showHistories;
public ObservableCollection<ModMakeHistory> ShowHistories
{
get => _showHistories;
set => SetProperty(ref _showHistories, value);
}
#endregion
/// <summary>
/// 历史
@ -68,12 +87,13 @@ public class ModMakerWindowVM
{
LoadHistories();
ModMakerWindow = window;
ShowHistories.Value = Histories;
//TODO
//ShowHistories.Value = Histories;
CreateNewModCommand.ExecuteCommand += CreateNewMod;
LoadModFromFileCommand.ExecuteCommand += LoadModFromFile;
ClearHistoriesCommand.ExecuteCommand += ClearHistories;
RemoveHistoryCommand.ExecuteCommand += RemoveHistory;
HistoriesSearchText.ValueChanged += HistoriesSearchText_ValueChanged;
//HistoriesSearchText.ValueChanged += HistoriesSearchText_ValueChanged;
}
private void HistoriesSearchText_ValueChanged(
@ -82,9 +102,9 @@ public class ModMakerWindowVM
)
{
if (string.IsNullOrEmpty(e.NewValue))
ShowHistories.Value = Histories;
ShowHistories = Histories;
else
ShowHistories.Value = new(Histories.Where(i => i.Id.Contains(e.NewValue)));
ShowHistories = new(Histories.Where(i => i.Id.Contains(e.NewValue)));
}
#region History
@ -133,12 +153,12 @@ public class ModMakerWindowVM
private void AddHistories(ModInfoModel modInfo)
{
if (
Histories.FirstOrDefault(h => h.SourcePath == modInfo.SourcePath.Value)
Histories.FirstOrDefault(h => h.SourcePath == modInfo.SourcePath)
is ModMakeHistory history
)
{
history.Id = modInfo.Id.Value;
history.SourcePath = modInfo.SourcePath.Value;
history.Id = modInfo.Id;
history.SourcePath = modInfo.SourcePath;
history.LastTime = DateTime.Now;
}
else
@ -146,8 +166,8 @@ public class ModMakerWindowVM
Histories.Add(
new()
{
Id = modInfo.Id.Value,
SourcePath = modInfo.SourcePath.Value,
Id = modInfo.Id,
SourcePath = modInfo.SourcePath,
LastTime = DateTime.Now,
}
);
@ -161,7 +181,7 @@ public class ModMakerWindowVM
is not MessageBoxResult.Yes
)
return;
ShowHistories.Value.Clear();
ShowHistories.Clear();
Histories.Clear();
File.WriteAllText(ModMakerInfo.HistoryFile, string.Empty);
}
@ -195,7 +215,7 @@ public class ModMakerWindowVM
GC.Collect();
ModMakerWindow.Hide();
// 将当前模组添加到历史
if (string.IsNullOrEmpty(ModInfoModel.Current.SourcePath.Value) is false)
if (string.IsNullOrEmpty(ModInfoModel.Current.SourcePath) is false)
AddHistories(ModInfoModel.Current);
SaveHistories();
ModEditWindow = new();
@ -204,7 +224,7 @@ public class ModMakerWindowVM
ModEditWindow.Closed += (s, e) =>
{
var modInfo = ModInfoModel.Current;
if (string.IsNullOrEmpty(modInfo.SourcePath.Value) is false)
if (string.IsNullOrEmpty(modInfo.SourcePath) is false)
{
AddHistories(modInfo);
SaveHistories();

View File

@ -1,7 +1,4 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@ -16,6 +13,9 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
using VPet.ModMaker.Models;
using VPet.ModMaker.ViewModels;
using VPet.ModMaker.ViewModels.ModEdit;
@ -46,12 +46,12 @@ public partial class AddCultureWindow : WindowX
private void Button_Yes_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.Culture.Value))
if (string.IsNullOrWhiteSpace(ViewModel.Culture))
{
MessageBox.Show("文化不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (I18nHelper.Current.CultureNames.Contains(ViewModel.Culture.Value))
if (I18nHelper.Current.CultureNames.Contains(ViewModel.Culture))
{
MessageBox.Show("此文化已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

@ -11,9 +11,11 @@
Title="{ll:Str 编辑动画}"
Width="1000"
Height="600"
d:DataContext="{d:DesignInstance Type=vm:AnimeEditWindowVM}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<d:Window.DataContext>
<vm:AnimeEditWindowVM />
</d:Window.DataContext>
<Window.Resources>
<Style
x:Key="ListBoxItem_Style"
@ -35,19 +37,19 @@
Command="{Binding PlacementTarget.Tag.AddImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 添加图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="清空图片"
Command="{Binding PlacementTarget.Tag.ClearImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 清空图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="删除此项"
Command="{Binding PlacementTarget.Tag.RemoveAnimeCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除此项}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Expander.ContextMenu>
<Expander.Header>
@ -67,14 +69,14 @@
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}"
Text="{Binding Id.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Id, UpdateSourceTrigger=PropertyChanged}" />
<!-- pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}" -->
<ComboBox
Grid.Column="2"
Margin="10,0,0,0"
ItemsSource="{Binding DataContext.Anime.Value.AnimatTypes, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding AnimeType.Value}"
Visibility="{Binding DataContext.HasMultiType.Value, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Converter={StaticResource FalseToHiddenConverter}}" />
ItemsSource="{Binding DataContext.Anime.AnimatTypes, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding AnimeType}"
Visibility="{Binding DataContext.HasMultiType, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Converter={StaticResource FalseToCollapsedConverter}}" />
</Grid>
</Expander.Header>
<ListBox
@ -86,7 +88,7 @@
PreviewMouseWheel="ListBox_PreviewMouseWheel"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedItem="{Binding DataContext.CurrentImageModel.Value, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding DataContext.CurrentImageModel, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
@ -103,13 +105,13 @@
Command="{Binding PlacementTarget.Tag.ChangeImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 修改图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="删除图片"
Command="{Binding PlacementTarget.Tag.RemoveImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.RowDefinitions>
@ -121,12 +123,12 @@
Height="150"
d:DataContext=""
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Source="{Binding Image.Value, IsAsync=True}">
Source="{Binding Image, IsAsync=True}">
<Image.ToolTip>
<Image
Width="250"
Height="250"
Source="{Binding Image.Value, IsAsync=True}" />
Source="{Binding Image, IsAsync=True}" />
</Image.ToolTip>
</Image>
<Grid Grid.Row="1">
@ -135,7 +137,7 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label d:Content="持续时间(ms)" Content="{ll:Str 持续时间(ms)}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration.Value, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
</Grid>
</Grid>
</DataTemplate>
@ -158,12 +160,12 @@
<Image
Width="250"
Height="250"
Source="{Binding CurrentImageModel.Value.Image.Value}">
Source="{Binding CurrentImageModel.Image}">
<Image.ToolTip>
<Image
Width="500"
Height="500"
Source="{Binding CurrentImageModel.Value.Image.Value}" />
Source="{Binding CurrentImageModel.Image}" />
</Image.ToolTip>
</Image>
<Grid Grid.Row="1">
@ -184,7 +186,7 @@
<ToggleButton
Grid.Column="2"
Content="{ll:Str 循环}"
IsChecked="{Binding Loop.Value}"
IsChecked="{Binding Loop}"
Style="{DynamicResource StndardToggleButtonStyle}" />
</Grid>
<Grid Grid.Row="2">
@ -199,17 +201,17 @@
<!--<Label Content="{ll:Str 动画Id}" />
<TextBox Grid.Column="1" />-->
<Label Content="{ll:Str 动画类型}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.Value.GraphType.Value}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" />
<Label
Grid.Row="1"
Content="{ll:Str 动画名称}"
Visibility="{Binding HasAnimeName.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Visibility="{Binding HasAnimeName, Converter={StaticResource FalseToCollapsedConverter}}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画名称}"
Text="{Binding Anime.Value.Name.Value, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasAnimeName.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Text="{Binding Anime.Name, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasAnimeName, Converter={StaticResource FalseToCollapsedConverter}}" />
</Grid>
</Grid>
<Grid Grid.Column="1">
@ -222,7 +224,7 @@
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.HappyAnimes.Count" />
<Binding Path="Anime.HappyAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -231,14 +233,14 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.HappyAnimes, IsAsync=True}"
ItemsSource="{Binding Anime.HappyAnimes, IsAsync=True}"
SelectionChanged="ListBox_Animes_SelectionChanged" />
</TabItem>
<TabItem d:Header="Nomal (0)" Tag="Nomal">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.NomalAnimes.Count" />
<Binding Path="Anime.NomalAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -246,13 +248,13 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.NomalAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.NomalAnimes, IsAsync=True}" />
</TabItem>
<TabItem d:Header="PoorCondition (0)" Tag="PoorCondition">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.PoorConditionAnimes.Count" />
<Binding Path="Anime.PoorConditionAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -260,13 +262,13 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.PoorConditionAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.PoorConditionAnimes, IsAsync=True}" />
</TabItem>
<TabItem d:Header="Ill (0)" Tag="Ill">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.IllAnimes.Count" />
<Binding Path="Anime.IllAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -274,7 +276,7 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.IllAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.IllAnimes, IsAsync=True}" />
</TabItem>
</TabControl>
<Grid Grid.Row="1">

View File

@ -65,8 +65,8 @@ public partial class AnimeEditWindow : Window
if (Enum.TryParse<ModeType>(str, true, out var mode))
{
ViewModel.CurrentMode = mode;
ViewModel.CurrentImageModel.Value = null;
ViewModel.CurrentAnimeModel.Value = null;
ViewModel.CurrentImageModel = null;
ViewModel.CurrentAnimeModel = null;
}
}
@ -141,7 +141,7 @@ public partial class AnimeEditWindow : Window
if (sender is not ListBox listBox)
return;
if (listBox.DataContext is AnimeModel model)
ViewModel.CurrentAnimeModel.Value = model;
ViewModel.CurrentAnimeModel = model;
listBox.ScrollIntoView(listBox.SelectedItem);
e.Handled = true;
}

View File

@ -23,7 +23,7 @@
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}" Text="{Binding Search.Value, UpdateSourceTrigger=PropertyChanged}">
<TextBox pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}" Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style BasedOn="{StaticResource StandardTextBoxStyle}" TargetType="TextBox">
<Setter Property="IsEnabled" Value="True" />
@ -40,19 +40,19 @@
Grid.Column="1"
pu:ComboBoxHelper.Watermark="{ll:Str 选择宠物}"
ItemsSource="{Binding Pets}"
SelectedItem="{Binding CurrentPet.Value}"
SelectedItem="{Binding CurrentPet}"
Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Value.Name.Value}" />
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Name}" />
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">
<Binding
Converter="{StaticResource BoolInverter}"
Path="DataContext.ModInfo.ShowMainPet.Value"
Path="DataContext.ModInfo.ShowMainPet"
RelativeSource="{RelativeSource AncestorType=Page}" />
<Binding Path="FromMain.Value" />
<Binding Path="FromMain" />
</MultiBinding>
</Setter.Value>
</Setter>
@ -61,7 +61,7 @@
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id.Value}" />
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{ll:Str {} (来自本体)}" Visibility="{Binding FromMain, Converter={StaticResource FalseToCollapsedConverter}}" />
</StackPanel>
</DataTemplate>
@ -85,7 +85,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowAnimes.Value}"
ItemsSource="{Binding ShowAnimes}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="50"
@ -100,40 +100,40 @@
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Id.Value}"
Binding="{Binding Id}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 动画类型}"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTextColumn
Binding="{Binding HappyAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 开心状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTextColumn
Binding="{Binding NomalAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 普通状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTextColumn
Binding="{Binding PoorConditionAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 不开心状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTextColumn
Binding="{Binding IllAnimes.Count}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 生病状态动画数量}"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
</DataGrid.Columns>
</DataGrid>
<Button

View File

@ -40,7 +40,7 @@
Command="{Binding PlacementTarget.Tag.RemoveAnimeCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除此动画}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.ColumnDefinitions>
@ -59,7 +59,7 @@
<!--<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}"
Text="{Binding Id.Value, UpdateSourceTrigger=PropertyChanged}" />-->
Text="{Binding Id, UpdateSourceTrigger=PropertyChanged}" />-->
<!-- pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}" -->
</Grid>
</Expander.Header>
@ -79,13 +79,13 @@
Command="{Binding PlacementTarget.Tag.AddFrontImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 添加图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="添加图片"
Command="{Binding PlacementTarget.Tag.ClearFrontImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 清空图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</StackPanel.ContextMenu>
<Label d:Content="顶层图片" Content="{ll:Str 顶层图片}" />
@ -107,7 +107,7 @@
PreviewMouseMove="ListBox_PreviewMouseMove"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedItem="{Binding DataContext.CurrentFrontImageModel.Value, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding DataContext.CurrentFrontImageModel, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
@ -124,13 +124,13 @@
Command="{Binding PlacementTarget.Tag.ChangeFrontImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 修改图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="删除图片"
Command="{Binding PlacementTarget.Tag.RemoveFrontImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.RowDefinitions>
@ -142,12 +142,12 @@
Height="150"
d:DataContext=""
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Source="{Binding Image.Value, IsAsync=True}">
Source="{Binding Image, IsAsync=True}">
<Image.ToolTip>
<Image
Width="250"
Height="250"
Source="{Binding Image.Value, IsAsync=True}" />
Source="{Binding Image, IsAsync=True}" />
</Image.ToolTip>
</Image>
<Grid Grid.Row="1">
@ -156,7 +156,7 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label d:Content="持续时间(ms)" Content="{ll:Str 持续时间(ms)}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration.Value, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
</Grid>
</Grid>
</DataTemplate>
@ -173,13 +173,13 @@
Command="{Binding PlacementTarget.Tag.AddBackImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 添加图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="添加图片"
Command="{Binding PlacementTarget.Tag.ClearBackImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 清空图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</StackPanel.ContextMenu>
<Label d:Content="底层图片" Content="{ll:Str 底层图片}" />
@ -201,7 +201,7 @@
PreviewMouseMove="ListBox_PreviewMouseMove"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedItem="{Binding DataContext.CurrentBackImageModel.Value, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding DataContext.CurrentBackImageModel, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
@ -218,13 +218,13 @@
Command="{Binding PlacementTarget.Tag.ChangeBackImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 修改图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="删除图片"
Command="{Binding PlacementTarget.Tag.RemoveBackImageCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除图片}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.RowDefinitions>
@ -236,12 +236,12 @@
Height="150"
d:DataContext=""
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Source="{Binding Image.Value, IsAsync=True}">
Source="{Binding Image, IsAsync=True}">
<Image.ToolTip>
<Image
Width="250"
Height="250"
Source="{Binding Image.Value, IsAsync=True}" />
Source="{Binding Image, IsAsync=True}" />
</Image.ToolTip>
</Image>
<Grid Grid.Row="1">
@ -250,7 +250,7 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label d:Content="持续时间(ms)" Content="{ll:Str 持续时间(ms)}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration.Value, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
<pu:NumberInput Grid.Column="1" Value="{Binding DataContext.Duration, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
</Grid>
</Grid>
</DataTemplate>
@ -267,13 +267,13 @@
Command="{Binding PlacementTarget.Tag.AddFoodLocationCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 添加食物定位}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
<MenuItem
d:Header="清空食物定位"
Command="{Binding PlacementTarget.Tag.ClearFoodLocationCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 清空食物定位}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</StackPanel.ContextMenu>
<Label d:Content="食物位置" Content="{ll:Str 食物位置}" />
@ -291,7 +291,7 @@
ItemsSource="{Binding FoodLocations, IsAsync=True}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedItem="{Binding DataContext.CurrentFoodLocationModel.Value, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectedItem="{Binding DataContext.CurrentFoodLocationModel, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
@ -308,7 +308,7 @@
Command="{Binding PlacementTarget.Tag.RemoveFoodLocationCommand, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}"
Header="{ll:Str 删除食物定位}"
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute.Value, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
IsEnabled="{Binding PlacementTarget.Tag.PlayCommand.CurrentCanExecute, RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}}" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.ColumnDefinitions>
@ -324,7 +324,7 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label d:Content="持续时间 (ms)" Content="{ll:Str 持续时间 (ms)}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Duration.Value}" />
<pu:NumberInput Grid.Column="1" Value="{Binding Duration}" />
<Label
Grid.Row="1"
d:Content="旋转角度"
@ -332,7 +332,7 @@
<pu:NumberInput
Grid.Row="1"
Grid.Column="1"
Value="{Binding Rotate.Value}" />
Value="{Binding Rotate}" />
<Label
Grid.Row="2"
d:Content="透明度"
@ -340,7 +340,7 @@
<pu:NumberInput
Grid.Row="2"
Grid.Column="1"
Value="{Binding Opacity.Value}" />
Value="{Binding Opacity}" />
<Label
Grid.Row="3"
d:Content="长度"
@ -399,7 +399,7 @@
<MenuItem Command="{Binding ResetFoodImageCommand}" Header="{ll:Str 重置测试食物图片}">
<MenuItem.IsEnabled>
<MultiBinding Converter="{StaticResource NotEqualsConverter}">
<Binding Path="FoodImage.Value" />
<Binding Path="FoodImage" />
<Binding Path="DefaultFoodImage" />
</MultiBinding>
</MenuItem.IsEnabled>
@ -410,20 +410,20 @@
x:Name="Image_Back"
Width="250"
Height="250"
Source="{Binding CurrentBackImageModel.Value.Image.Value}" />
Source="{Binding CurrentBackImageModel.Image}" />
<Image
x:Name="Image_Food"
Height="{Binding Width, RelativeSource={RelativeSource Mode=Self}}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Opacity="{Binding CurrentFoodLocationModel.Value.Opacity.Value}"
Opacity="{Binding CurrentFoodLocationModel.Opacity}"
RenderTransformOrigin="0,0"
Source="{Binding FoodImage.Value}">
Source="{Binding FoodImage}">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="{Binding CurrentFoodLocationModel.Value.Rotate.Value}" />
<RotateTransform Angle="{Binding CurrentFoodLocationModel.Rotate}" />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
@ -432,17 +432,17 @@
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="CurrentFoodLocationModel.Value.Rect.Width" />
<Binding Path="LengthRatio.Value" />
<Binding Path="CurrentFoodLocationModel.Rect.Width" />
<Binding Path="LengthRatio" />
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Path="LengthRatio.Value" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.Y" />
<Binding Path="LengthRatio" />
<Binding Path="CurrentFoodLocationModel.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Rect.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
@ -453,25 +453,25 @@
x:Name="Image_Front"
Width="250"
Height="250"
Source="{Binding CurrentFrontImageModel.Value.Image.Value}">
Source="{Binding CurrentFrontImageModel.Image}">
<Image.ToolTip>
<Grid>
<Image
Width="500"
Height="500"
Source="{Binding CurrentBackImageModel.Value.Image.Value}" />
Source="{Binding CurrentBackImageModel.Image}" />
<Image
Height="{Binding Width, RelativeSource={RelativeSource Mode=Self}}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Opacity="{Binding CurrentFoodLocationModel.Value.Opacity.Value}"
Opacity="{Binding CurrentFoodLocationModel.Opacity}"
RenderTransformOrigin="0,0"
Source="{Binding FoodImage.Value}">
Source="{Binding FoodImage}">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="{Binding CurrentFoodLocationModel.Value.Rotate.Value}" />
<RotateTransform Angle="{Binding CurrentFoodLocationModel.Rotate}" />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
@ -480,7 +480,7 @@
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="*">
<Binding Path="CurrentFoodLocationModel.Value.Rect.Width" />
<Binding Path="CurrentFoodLocationModel.Rect.Width" />
<Binding Source="1" />
</MultiBinding>
</Setter.Value>
@ -489,8 +489,8 @@
<Setter.Value>
<MultiBinding Converter="{StaticResource RatioMarginConverter}">
<Binding Source="1" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Value.Rect.Y" />
<Binding Path="CurrentFoodLocationModel.Rect.X" />
<Binding Path="CurrentFoodLocationModel.Rect.Y" />
</MultiBinding>
</Setter.Value>
</Setter>
@ -500,7 +500,7 @@
<Image
Width="500"
Height="500"
Source="{Binding CurrentFrontImageModel.Value.Image.Value}" />
Source="{Binding CurrentFrontImageModel.Image}" />
</Grid>
</Image.ToolTip>
</Image>
@ -523,7 +523,7 @@
<ToggleButton
Grid.Column="2"
Content="{ll:Str 循环}"
IsChecked="{Binding Loop.Value}"
IsChecked="{Binding Loop}"
Style="{DynamicResource StndardToggleButtonStyle}" />
</Grid>
<Grid Grid.Row="2">
@ -538,17 +538,17 @@
<!--<Label Content="{ll:Str 动画Id}" />
<TextBox Grid.Column="1" />-->
<Label Content="{ll:Str 动画类型}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.Value.GraphType}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" />
<Label
Grid.Row="1"
Content="{ll:Str 动画名称}"
Visibility="{Binding HasAnimeName.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Visibility="{Binding HasAnimeName, Converter={StaticResource FalseToCollapsedConverter}}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画名称}"
Text="{Binding Anime.Value.Name.Value, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasAnimeName.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Text="{Binding Anime.Name, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasAnimeName, Converter={StaticResource FalseToCollapsedConverter}}" />
</Grid>
</Grid>
<Grid Grid.Column="1">
@ -561,7 +561,7 @@
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.HappyAnimes.Count" />
<Binding Path="Anime.HappyAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -570,14 +570,14 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.HappyAnimes, IsAsync=True}"
ItemsSource="{Binding Anime.HappyAnimes, IsAsync=True}"
SelectionChanged="ListBox_Animes_SelectionChanged" />
</TabItem>
<TabItem d:Header="Nomal (0)" Tag="Nomal">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.NomalAnimes.Count" />
<Binding Path="Anime.NomalAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -585,13 +585,13 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.NomalAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.NomalAnimes, IsAsync=True}" />
</TabItem>
<TabItem d:Header="PoorCondition (0)" Tag="PoorCondition">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.PoorConditionAnimes.Count" />
<Binding Path="Anime.PoorConditionAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -599,13 +599,13 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.PoorConditionAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.PoorConditionAnimes, IsAsync=True}" />
</TabItem>
<TabItem d:Header="Ill (0)" Tag="Ill">
<TabItem.Header>
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="{}{0} ({1})">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}" />
<Binding Path="Anime.Value.IllAnimes.Count" />
<Binding Path="Anime.IllAnimes.Count" />
</MultiBinding>
</TabItem.Header>
<ListBox
@ -613,7 +613,7 @@
d:SelectedIndex="0"
ItemContainerStyle="{StaticResource ListBoxItem_Style}"
ItemTemplate="{StaticResource Expander_AnimeItem}"
ItemsSource="{Binding Anime.Value.IllAnimes, IsAsync=True}" />
ItemsSource="{Binding Anime.IllAnimes, IsAsync=True}" />
</TabItem>
</TabControl>
<Grid Grid.Row="1">

View File

@ -68,10 +68,10 @@ public partial class FoodAnimeEditWindow : Window
if (Enum.TryParse<ModeType>(str, true, out var mode))
{
ViewModel.CurrentMode = mode;
ViewModel.CurrentFrontImageModel.Value = null;
ViewModel.CurrentBackImageModel.Value = null;
ViewModel.CurrentFoodLocationModel.Value = null;
ViewModel.CurrentAnimeModel.Value = null;
ViewModel.CurrentFrontImageModel = null;
ViewModel.CurrentBackImageModel = null;
ViewModel.CurrentFoodLocationModel = null;
ViewModel.CurrentAnimeModel = null;
}
}
@ -161,7 +161,7 @@ public partial class FoodAnimeEditWindow : Window
if (sender is not ListBox listBox)
return;
if (listBox.DataContext is FoodAnimeModel model)
ViewModel.CurrentAnimeModel.Value = model;
ViewModel.CurrentAnimeModel = model;
listBox.ScrollIntoView(listBox.SelectedItem);
e.Handled = true;
}

View File

@ -44,13 +44,13 @@
<Label
Grid.Row="1"
Content="{ll:Str 动画名称}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToCollapsedConverter}}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding AnimeName.Value, UpdateSourceTrigger=PropertyChanged}"
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToHiddenConverter}}" />
Visibility="{Binding HasNameAnime.Value, Converter={StaticResource FalseToCollapsedConverter}}" />
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>

View File

@ -1,6 +1,4 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@ -14,6 +12,8 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.Models.ModModel;
using VPet_Simulator.Core;
@ -58,7 +58,7 @@ public partial class SelectGraphTypeWindow : Window
)
{
GraphTypes.Value = new(
AnimeTypeModel.GraphTypes.Except(CurrentPet.Value.Animes.Select(m => m.GraphType.Value))
AnimeTypeModel.GraphTypes.Except(CurrentPet.Value.Animes.Select(m => m.GraphType))
);
// 可添加多个项的类型
foreach (var graphType in AnimeTypeModel.HasNameAnimes)

View File

@ -38,7 +38,7 @@
Grid.Column="1"
pu:TextBoxHelper.Watermark="Id"
Style="{StaticResource TextBox_Wrap}"
Text="{Binding ClickText.Value.Id.Value, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding ClickText.Id, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</Grid>
<TextBox
@ -47,7 +47,7 @@
d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,"
pu:TextBoxHelper.Watermark="{ll:Str 文本}"
Style="{StaticResource TextBox_Wrap}"
Text="{Binding ClickText.Value.CurrentI18nData.Value.Text.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding ClickText.CurrentI18nData.Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
@ -72,7 +72,7 @@
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 非必要}"
Text="{Binding ClickText.Value.Working.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding ClickText.Working, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="3" Content="{ll:Str 宠物状态}" />
<Grid Grid.Row="3" Grid.Column="1">
<Grid.ColumnDefinitions>
@ -81,20 +81,20 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ClickText.Value.Mode.EnumValue.Value}" />
<TextBlock Text="{Binding ClickText.Mode.Value}" />
<ComboBox
x:Name="ComboBox_Mode"
Grid.Column="1"
ItemsSource="{Binding ClickText.Value.ModeTypes}"
ItemsSource="{Binding ClickText.ModeTypes}"
SelectedIndex="0" />
<Button
Grid.Column="2"
Command="{Binding ClickText.Value.Mode.AddCommand}"
Command="{Binding ClickText.Mode.AddCommand}"
CommandParameter="{Binding SelectedItem, ElementName=ComboBox_Mode}"
Content="+" />
<Button
Grid.Column="3"
Command="{Binding ClickText.Value.Mode.RemoveCommand}"
Command="{Binding ClickText.Mode.RemoveCommand}"
CommandParameter="{Binding SelectedItem, ElementName=ComboBox_Mode}"
Content="-" />
</Grid>
@ -102,8 +102,8 @@
<ComboBox
Grid.Row="4"
Grid.Column="1"
ItemsSource="{Binding ClickText.Value.WorkingStates}"
SelectedItem="{Binding ClickText.Value.WorkingState.Value}" />
ItemsSource="{Binding ClickText.WorkingStates}"
SelectedItem="{Binding ClickText.WorkingState}" />
<Label Grid.Row="5" Content="{ll:Str 日期区间}" />
<Grid Grid.Row="5" Grid.Column="1">
<Grid.ColumnDefinitions>
@ -112,54 +112,54 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ClickText.Value.DayTime.EnumValue.Value}" />
<TextBlock Text="{Binding ClickText.DayTime.Value}" />
<ComboBox
x:Name="ComboBox_DayTime"
Grid.Column="1"
ItemsSource="{Binding ClickText.Value.DayTimes}"
ItemsSource="{Binding ClickText.DayTimes}"
SelectedIndex="0" />
<Button
Grid.Column="2"
Command="{Binding ClickText.Value.DayTime.AddCommand}"
Command="{Binding ClickText.DayTime.AddCommand}"
CommandParameter="{Binding SelectedItem, ElementName=ComboBox_DayTime}"
Content="+" />
<Button
Grid.Column="3"
Command="{Binding ClickText.Value.DayTime.RemoveCommand}"
Command="{Binding ClickText.DayTime.RemoveCommand}"
CommandParameter="{Binding SelectedItem, ElementName=ComboBox_DayTime}"
Content="-" />
</Grid>
<ListBox Grid.Row="6" Grid.ColumnSpan="2">
<ListBoxItem
DataContext="{Binding ClickText.Value.Like}"
DataContext="{Binding ClickText.Like}"
Tag="{ll:Str 好感度范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Health}"
DataContext="{Binding ClickText.Health}"
Tag="{ll:Str 健康度范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Level}"
DataContext="{Binding ClickText.Level}"
Tag="{ll:Str 等级范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Money}"
DataContext="{Binding ClickText.Money}"
Tag="{ll:Str 金钱范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Food}"
DataContext="{Binding ClickText.Food}"
Tag="{ll:Str 食物范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Drink}"
DataContext="{Binding ClickText.Drink}"
Tag="{ll:Str 口渴范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Feel}"
DataContext="{Binding ClickText.Feel}"
Tag="{ll:Str 心情范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
<ListBoxItem
DataContext="{Binding ClickText.Value.Strength}"
DataContext="{Binding ClickText.Strength}"
Tag="{ll:Str 体力范围}"
Template="{StaticResource ListBoxItem_RangeData}" />
</ListBox>

View File

@ -1,5 +1,4 @@
using LinePutScript.Localization.WPF;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -12,6 +11,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LinePutScript.Localization.WPF;
using VPet.ModMaker.Models;
using VPet.ModMaker.ViewModels.ModEdit.ClickTextEdit;
@ -46,22 +46,20 @@ public partial class ClickTextEditWindow : Window
private void Button_Yes_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(ViewModel.ClickText.Value.Id.Value))
if (string.IsNullOrEmpty(ViewModel.ClickText.Id))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (
ViewModel.OldClickText?.Id.Value != ViewModel.ClickText.Value.Id.Value
&& ModInfoModel.Current.ClickTexts.Any(
i => i.Id.Value == ViewModel.ClickText.Value.Id.Value
)
ViewModel.OldClickText?.Id != ViewModel.ClickText.Id
&& ModInfoModel.Current.ClickTexts.Any(i => i.Id == ViewModel.ClickText.Id)
)
{
MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (string.IsNullOrEmpty(ViewModel.ClickText.Value.CurrentI18nData.Value.Text.Value))
if (string.IsNullOrEmpty(ViewModel.ClickText.CurrentI18nData.Text))
{
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

@ -21,7 +21,7 @@
<TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding Search.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}"
@ -29,7 +29,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowClickTexts.Value}"
ItemsSource="{Binding ShowClickTexts}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="64"
@ -45,41 +45,41 @@
<DataGrid.Columns>
<DataGridTextColumn
MaxWidth="200"
Binding="{Binding Id.Value}"
Binding="{Binding Id}"
CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}"
Header="Id"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTextColumn
MaxWidth="300"
Binding="{Binding CurrentI18nData.Value.Text.Value}"
Binding="{Binding CurrentI18nData.Text}"
CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}"
Header="{ll:Str 文本}"
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Value.Text.Value" />
SortMemberPath="CurrentI18nData.Text" />
<DataGridTextColumn
Binding="{Binding Mode.EnumValue.Value}"
Binding="{Binding Mode.EnumValue}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 状态}"
IsReadOnly="True"
SortMemberPath="Mode.EnumValue.Value" />
SortMemberPath="Mode.EnumValue" />
<DataGridTextColumn
Binding="{Binding Working.Value}"
Binding="{Binding Working}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 指定工作}"
IsReadOnly="True"
SortMemberPath="Working.Value" />
SortMemberPath="Working" />
<DataGridTextColumn
Binding="{Binding WorkingState.Value}"
Binding="{Binding WorkingState}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 工作状态}"
IsReadOnly="True"
SortMemberPath="WorkingState.Value" />
SortMemberPath="WorkingState" />
<DataGridTextColumn
Binding="{Binding DayTime.EnumValue}"
CanUserSort="True"

View File

@ -30,7 +30,7 @@
x:Name="Image_FoodImage"
Width="250"
Height="250"
Source="{Binding Food.Value.Image.Value}"
Source="{Binding Food.Image}"
Stretch="Uniform">
<Image.ContextMenu>
<ContextMenu>
@ -44,7 +44,7 @@
Command="{Binding AddImageCommand}"
Content="{ll:Str 添加图片}"
Style="{DynamicResource Button_HiddenOnTagNull}"
Tag="{Binding Food.Value.Image.Value}" />
Tag="{Binding Food.Image}" />
</Grid>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<Grid>
@ -63,33 +63,33 @@
<TextBox
Grid.Column="1"
pu:TextBoxHelper.Watermark="Id"
Text="{Binding Food.Value.Id.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Food.Id, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Content="{ll:Str 食物类型}" />
<ComboBox
x:Name="ComboBox_FoodType"
Grid.Row="1"
Grid.Column="1"
ItemsSource="{Binding Food.Value.FoodTypes}"
SelectedItem="{Binding Food.Value.Type.Value}" />
ItemsSource="{Binding Food.FoodTypes}"
SelectedItem="{Binding Food.Type}" />
<Label Grid.Row="2" Content="{ll:Str 动画名称}" />
<TextBox
Grid.Row="2"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 绑定的动画名称(非必要)}"
Text="{Binding Food.Value.Graph.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Food.Graph, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="3" Content="{ll:Str 食物名称}" />
<TextBox
Grid.Row="3"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 食物名称}"
Text="{Binding Food.Value.CurrentI18nData.Value.Name.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Food.CurrentI18nData.Name, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="4" Content="{ll:Str 食物描述}" />
<TextBox
Grid.Row="4"
Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 食物描述}"
Style="{StaticResource TextBox_Wrap}"
Text="{Binding Food.Value.CurrentI18nData.Value.Description.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Food.CurrentI18nData.Description, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</ScrollViewer>
</Grid>
@ -122,42 +122,42 @@
<pu:NumberInput
x:Name="NumberInput_StrengthFood"
Grid.Column="1"
Value="{Binding Food.Value.StrengthFood.Value, Mode=TwoWay}" />
Value="{Binding Food.StrengthFood, Mode=TwoWay}" />
<Label Grid.Row="2" Content="{ll:Str 口渴值}" />
<pu:NumberInput
Grid.Row="2"
Grid.Column="1"
Value="{Binding Food.Value.StrengthDrink.Value, Mode=TwoWay}" />
Value="{Binding Food.StrengthDrink, Mode=TwoWay}" />
<Label Grid.Row="3" Content="{ll:Str 健康值}" />
<pu:NumberInput
Grid.Row="3"
Grid.Column="1"
Value="{Binding Food.Value.Health.Value, Mode=TwoWay}" />
Value="{Binding Food.Health, Mode=TwoWay}" />
<Label Grid.Row="4" Content="{ll:Str 体力值}" />
<pu:NumberInput
Grid.Row="4"
Grid.Column="1"
Value="{Binding Food.Value.Strength.Value, Mode=TwoWay}" />
Value="{Binding Food.Strength, Mode=TwoWay}" />
<Label Grid.Row="5" Content="{ll:Str 心情值}" />
<pu:NumberInput
Grid.Row="5"
Grid.Column="1"
Value="{Binding Food.Value.Feeling.Value, Mode=TwoWay}" />
Value="{Binding Food.Feeling, Mode=TwoWay}" />
<Label Grid.Row="6" Content="{ll:Str 好感值}" />
<pu:NumberInput
Grid.Row="6"
Grid.Column="1"
Value="{Binding Food.Value.Likability.Value, Mode=TwoWay}" />
Value="{Binding Food.Likability, Mode=TwoWay}" />
<Label Grid.Row="7" Content="{ll:Str 经验值}" />
<pu:NumberInput
Grid.Row="7"
Grid.Column="1"
Value="{Binding Food.Value.Exp.Value, Mode=TwoWay}" />
Value="{Binding Food.Exp, Mode=TwoWay}" />
<Label Grid.Row="8" Content="{ll:Str 价格}" />
<pu:NumberInput
Grid.Row="8"
Grid.Column="1"
Value="{Binding Food.Value.Price.Value, Mode=TwoWay}" />
Value="{Binding Food.Price, Mode=TwoWay}" />
<Label Grid.Row="9" Content="{ll:Str 参考价格}" />
<Grid Grid.Row="9" Grid.Column="1">
<Grid.ColumnDefinitions>
@ -165,11 +165,11 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Food.Value.ReferencePrice.Value}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Food.ReferencePrice}" />
<Button
Grid.Column="1"
Command="{Binding SetReferencePriceCommand}"
CommandParameter="{Binding Food.Value.ReferencePrice.Value}"
CommandParameter="{Binding Food.ReferencePrice}"
Content="{ll:Str 设置}"
Style="{DynamicResource ThemedButtonStyle}" />
<pu:Switch
@ -177,7 +177,7 @@
BoxHeight="16"
BoxWidth="30"
Content="{ll:Str 自动设置}"
IsChecked="{Binding ModInfo.AutoSetFoodPrice.Value}" />
IsChecked="{Binding ModInfo.AutoSetFoodPrice}" />
</Grid>
</Grid>
</ScrollViewer>

View File

@ -1,6 +1,4 @@
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -13,6 +11,8 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using VPet.ModMaker.Models;
using VPet.ModMaker.ViewModels.ModEdit.FoodEdit;
using VPet_Simulator.Windows.Interface;
@ -51,19 +51,19 @@ public partial class FoodEditWindow : Window
private void Button_Yes_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(ViewModel.Food.Value.Id.Value))
if (string.IsNullOrWhiteSpace(ViewModel.Food.Id))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (ViewModel.Food.Value.Image.Value is null)
if (ViewModel.Food.Image is null)
{
MessageBox.Show("图像不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (
ViewModel.OldFood?.Id.Value != ViewModel.Food.Value.Id.Value
&& ModInfoModel.Current.Foods.Any(i => i.Id == ViewModel.Food.Value.Id)
ViewModel.OldFood?.Id != ViewModel.Food.Id
&& ModInfoModel.Current.Foods.Any(i => i.Id == ViewModel.Food.Id)
)
{
MessageBox.Show("此Id已存在", "", MessageBoxButton.OK, MessageBoxImage.Warning);

View File

@ -21,7 +21,7 @@
<TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding Search.Value, UpdateSourceTrigger=PropertyChanged}" />
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}"
@ -29,7 +29,7 @@
AutoGenerateColumns="False"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
ItemsSource="{Binding ShowFoods.Value}"
ItemsSource="{Binding ShowFoods}"
MouseDoubleClick="DataGrid_MouseDoubleClick"
RowDetailsVisibilityMode="Visible"
RowHeight="64"
@ -44,12 +44,12 @@
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Id.Value}"
Binding="{Binding Id}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="Id"
IsReadOnly="True"
SortMemberPath="Id.Value" />
SortMemberPath="Id" />
<DataGridTemplateColumn Header="{ll:Str 食物图片}" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
@ -58,7 +58,7 @@
Height="64"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="{Binding Image.Value, IsAsync=True}"
Source="{Binding Image, IsAsync=True}"
Stretch="Uniform">
<Image.ToolTip>
<Image
@ -66,7 +66,7 @@
Height="256"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="{Binding Image.Value, IsAsync=True}"
Source="{Binding Image, IsAsync=True}"
Stretch="Uniform" />
</Image.ToolTip>
</Image>
@ -74,90 +74,90 @@
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn
Binding="{Binding CurrentI18nData.Value.Name.Value}"
Binding="{Binding CurrentI18nData.Name}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 食物名称}"
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Value.Name.Value" />
SortMemberPath="CurrentI18nData.Name" />
<DataGridTextColumn
Binding="{Binding Type.Value}"
Binding="{Binding Type}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 食物类型}"
IsReadOnly="True"
SortMemberPath="Type.Value" />
SortMemberPath="Type" />
<DataGridTextColumn
Binding="{Binding Graph.Value}"
Binding="{Binding Graph}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 指定动画}"
IsReadOnly="True"
SortMemberPath="Type.Value" />
SortMemberPath="Type" />
<DataGridTextColumn
Binding="{Binding StrengthFood.Value}"
Binding="{Binding StrengthFood}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 饱腹值}"
IsReadOnly="True"
SortMemberPath="StrengthFood.Value" />
SortMemberPath="StrengthFood" />
<DataGridTextColumn
Binding="{Binding StrengthDrink.Value}"
Binding="{Binding StrengthDrink}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 口渴值}"
IsReadOnly="True"
SortMemberPath="StrengthDrink.Value" />
SortMemberPath="StrengthDrink" />
<DataGridTextColumn
Binding="{Binding Health.Value}"
Binding="{Binding Health}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 健康值}"
IsReadOnly="True"
SortMemberPath="Health.Value" />
SortMemberPath="Health" />
<DataGridTextColumn
Binding="{Binding Strength.Value}"
Binding="{Binding Strength}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 体力值}"
IsReadOnly="True"
SortMemberPath="Strength.Value" />
SortMemberPath="Strength" />
<DataGridTextColumn
Binding="{Binding Feeling.Value}"
Binding="{Binding Feeling}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 心情值}"
IsReadOnly="True"
SortMemberPath="Feeling.Value" />
SortMemberPath="Feeling" />
<DataGridTextColumn
Binding="{Binding Likability.Value}"
Binding="{Binding Likability}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 好感值}"
IsReadOnly="True"
SortMemberPath="Likability.Value" />
SortMemberPath="Likability" />
<DataGridTextColumn
Binding="{Binding Exp.Value}"
Binding="{Binding Exp}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 经验值}"
IsReadOnly="True"
SortMemberPath="Exp.Value" />
SortMemberPath="Exp" />
<DataGridTextColumn
Binding="{Binding Price.Value}"
Binding="{Binding Price}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 价格}"
IsReadOnly="True"
SortMemberPath="Price.Value" />
SortMemberPath="Price" />
<DataGridTextColumn
MaxWidth="300"
Binding="{Binding CurrentI18nData.Value.Description.Value}"
Binding="{Binding CurrentI18nData.Description}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_Wrap}"
Header="{ll:Str 描述}"
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Value.Description.Value" />
SortMemberPath="CurrentI18nData.Description" />
</DataGrid.Columns>
</DataGrid>
<Button

Some files were not shown because too many files have changed in this diff Show More