using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.Win32;
using Sandbox.Definitions;
using SpaceEngineersBlueprintEditor.Model;
using SpaceEngineersBlueprintEditor.SpaceEngineersCore;
using System.Collections;
using System.Reflection;
using VRage.Collections;
using VRage.Game;
using XFEExtension.NetCore.FileExtension;
namespace SpaceEngineersBlueprintEditor.Utilities.Helpers;
///
/// 太空工程师帮助类
///
public static class SpaceEngineersHelper
{
///
/// 加载完成事件
///
public static event EventHandler? LoadComplete;
///
/// 普通块
///
public static string[] NormalBlock { get; } =
[
"LargeBlockArmorBlock",
"LargeBlockArmorRoundSlope" ,
"LargeBlockArmorRoundCornerInv",
"LargeBlockArmorRoundCorner",
"LargeBlockArmorSlope2Base",
"LargeBlockArmorHalfSlopedCorner",
"LargeBlockArmorHalfCorner",
"LargeBlockArmorHalfSlopeCorner",
"LargeHalfSlopeArmorBlock",
"LargeHalfArmorBlock",
"LargeBlockArmorSlope2Tip",
"LargeBlockArmorBlock",
"LargeBlockArmorCornerSquareInverted",
"LargeBlockArmorCornerSquare",
"LargeBlockArmorCornerInv",
"LargeBlockArmorCorner",
"LargeBlockArmorSlope",
"LargeBlockArmorCorner2Base",
"LargeBlockArmorHalfSlopeInverted",
"LargeBlockArmorHalfSlopeCornerInverted",
"LargeBlockArmorInvCorner2Tip",
"LargeBlockArmorInvCorner2Base",
"LargeBlockArmorCorner2Tip",
"LargeBlockArmorSlopeTransitionBase",
"LargeBlockArmorSlopeTransitionTipMirrored",
"LargeBlockArmorSlopeTransitionMirrored",
"LargeBlockArmorSlopeTransitionBaseMirrored",
"LargeBlockArmorSlopeTransitionTip",
"LargeArmorPanelLight",
"LargeArmorQuarterPanelLight",
"LargeArmorHalfPanelLight",
"LargeArmor2x1HalfSlopedTipPanelLightLeft",
"LargeArmor2x1HalfSlopedPanelLightLeft",
"LargeArmor2x1HalfSlopedTipPanelLightRight",
"LargeArmor2x1HalfSlopedPanelLightRight",
"LargeArmorHalfSlopedPanelLight",
"LargeArmor2x1SlopedSideTipPanelLightInv",
"LargeArmor2x1SlopedSideBasePanelLightInv",
"LargeArmor2x1SlopedSideTipPanelLight",
"LargeArmor2x1SlopedSideBasePanelLight",
"LargeArmor2x1SlopedPanelTipLight",
"LargeArmor2x1SlopedPanelLight",
"LargeArmorSlopedSidePanelLight",
"LargeArmorSlopedPanelLight",
"LargeBlockArmorSlopeTransition",
"SmallBlockArmorBlock",
"SmallBlockArmorRoundSlope" ,
"SmallBlockArmorRoundCornerInv",
"SmallBlockArmorRoundCorner",
"SmallBlockArmorSlope2Base",
"SmallBlockArmorHalfSlopedCorner",
"SmallBlockArmorHalfCorner",
"SmallBlockArmorHalfSlopeCorner",
"HalfSlopeArmorBlock",
"HalfArmorBlock",
"SmallBlockArmorSlope2Tip",
"SmallBlockArmorBlock",
"SmallBlockArmorCornerSquareInverted",
"SmallBlockArmorCornerSquare",
"SmallBlockArmorCornerInv",
"SmallBlockArmorCorner",
"SmallBlockArmorSlope",
"SmallBlockArmorCorner2Base",
"SmallBlockArmorHalfSlopeInverted",
"SmallBlockArmorHalfSlopeCornerInverted",
"SmallBlockArmorInvCorner2Tip",
"SmallBlockArmorInvCorner2Base",
"SmallBlockArmorCorner2Tip",
"SmallBlockArmorSlopeTransitionBase",
"SmallBlockArmorSlopeTransitionTipMirrored",
"SmallBlockArmorSlopeTransitionMirrored",
"SmallBlockArmorSlopeTransitionBaseMirrored",
"SmallBlockArmorSlopeTransitionTip",
"SmallArmorPanelLight",
"SmallArmorQuarterPanelLight",
"SmallArmorHalfPanelLight",
"SmallArmor2x1HalfSlopedTipPanelLightLeft",
"SmallArmor2x1HalfSlopedPanelLightLeft",
"SmallArmor2x1HalfSlopedTipPanelLightRight",
"SmallArmor2x1HalfSlopedPanelLightRight",
"SmallArmorHalfSlopedPanelLight",
"SmallArmor2x1SlopedSideTipPanelLightInv",
"SmallArmor2x1SlopedSideBasePanelLightInv",
"SmallArmor2x1SlopedSideTipPanelLight",
"SmallArmor2x1SlopedSideBasePanelLight",
"SmallArmor2x1SlopedPanelTip",
"SmallArmor2x1SlopedPanelLight",
"SmallArmorSlopedSidePanelLight",
"SmallArmorSlopedPanelLight",
"SmallBlockArmorSlopeTransition",
];
///
/// 重甲块
///
public static string[] HeavyBlock { get; } =
[
"LargeHeavyBlockArmorBlock",
"LargeHeavyBlockArmorRoundSlope" ,
"LargeHeavyBlockArmorRoundCornerInv",
"LargeHeavyBlockArmorRoundCorner",
"LargeHeavyBlockArmorSlope2Base",
"LargeBlockHeavyArmorHalfSlopedCorner",
"LargeBlockHeavyArmorHalfCorner",
"LargeBlockHeavyArmorHalfSlopeCorner",
"LargeHeavyHalfSlopeArmorBlock",
"LargeHeavyHalfArmorBlock",
"LargeHeavyBlockArmorSlope2Tip",
"LargeHeavyBlockArmorBlock",
"LargeBlockHeavyArmorCornerSquareInverted",
"LargeBlockHeavyArmorCornerSquare",
"LargeHeavyBlockArmorCornerInv",
"LargeHeavyBlockArmorCorner",
"LargeHeavyBlockArmorSlope",
"LargeHeavyBlockArmorCorner2Base",
"LargeBlockHeavyArmorHalfSlopeInverted",
"LargeBlockHeavyArmorHalfSlopeCornerInverted",
"LargeHeavyBlockArmorInvCorner2Tip",
"LargeHeavyBlockArmorInvCorner2Base",
"LargeHeavyBlockArmorCorner2Tip",
"LargeBlockHeavyArmorSlopeTransitionBase",
"LargeBlockHeavyArmorSlopeTransitionTipMirrored",
"LargeBlockHeavyArmorSlopeTransitionMirrored",
"LargeBlockHeavyArmorSlopeTransitionBaseMirrored",
"LargeBlockHeavyArmorSlopeTransitionTip",
"LargeArmorPanelHeavy",
"LargeArmorQuarterPanelHeavy",
"LargeArmorHalfPanelHeavy",
"LargeArmor2x1HalfSlopedTipPanelHeavyLeft",
"LargeArmor2x1HalfSlopedPanelHeavyLeft",
"LargeArmor2x1HalfSlopedTipPanelHeavyRight",
"LargeArmor2x1HalfSlopedPanelHeavyRight",
"LargeArmorHalfSlopedPanelHeavy",
"LargeArmor2x1SlopedSideTipPanelHeavyInv",
"LargeArmor2x1SlopedSideBasePanelHeavyInv",
"LargeArmor2x1SlopedSideTipPanelHeavy",
"LargeArmor2x1SlopedSideBasePanelHeavy",
"LargeArmor2x1SlopedPanelTipHeavy",
"LargeArmor2x1SlopedPanelHeavy",
"LargeArmorSlopedSidePanelHeavy",
"LargeArmorSlopedPanelHeavy",
"LargeBlockHeavyArmorSlopeTransition",
"SmallHeavyBlockArmorBlock",
"SmallHeavyBlockArmorRoundSlope" ,
"SmallHeavyBlockArmorRoundCornerInv",
"SmallHeavyBlockArmorRoundCorner",
"SmallHeavyBlockArmorSlope2Base",
"SmallBlockHeavyArmorHalfSlopedCorner",
"SmallBlockHeavyArmorHalfCorner",
"SmallBlockHeavyArmorHalfSlopeCorner",
"HeavyHalfSlopeArmorBlock",
"HeavyHalfArmorBlock",
"SmallHeavyBlockArmorSlope2Tip",
"SmallHeavyBlockArmorBlock",
"SmallBlockHeavyArmorCornerSquareInverted",
"SmallBlockHeavyArmorCornerSquare",
"SmallHeavyBlockArmorCornerInv",
"SmallHeavyBlockArmorCorner",
"SmallHeavyBlockArmorSlope",
"SmallHeavyBlockArmorCorner2Base",
"SmallBlockHeavyArmorHalfSlopeInverted",
"SmallBlockHeavyArmorHalfSlopeCornerInverted",
"SmallHeavyBlockArmorInvCorner2Tip",
"SmallHeavyBlockArmorInvCorner2Base",
"SmallHeavyBlockArmorCorner2Tip",
"SmallBlockHeavyArmorSlopeTransitionBase",
"SmallBlockHeavyArmorSlopeTransitionTipMirrored",
"SmallBlockHeavyArmorSlopeTransitionMirrored",
"SmallBlockHeavyArmorSlopeTransitionBaseMirrored",
"SmallBlockHeavyArmorSlopeTransitionTip",
"SmallArmorPanelHeavy",
"SmallArmorQuarterPanelHeavy",
"SmallArmorHalfPanelHeavy",
"SmallArmor2x1HalfSlopedTipPanelHeavyLeft",
"SmallArmor2x1HalfSlopedPanelHeavyLeft",
"SmallArmor2x1HalfSlopedTipPanelHeavyRight",
"SmallArmor2x1HalfSlopedPanelHeavyRight",
"SmallArmorHalfSlopedPanelHeavy",
"SmallArmor2x1SlopedSideTipPanelHeavyInv",
"SmallArmor2x1SlopedSideBasePanelHeavyInv",
"SmallArmor2x1SlopedSideTipPanelHeavy",
"SmallArmor2x1SlopedSideBasePanelHeavy",
"SmallArmor2x1SlopedPanelTipHeavy",
"SmallArmor2x1SlopedPanelHeavy",
"SmallArmorSlopedSidePanelHeavy",
"SmallArmorSlopedPanelHeavy",
"SmallBlockHeavyArmorSlopeTransition",
];
///
/// 小型块
///
public static string[] SmallBlock { get; } =
[
"SmallBlockArmorBlock",
"SmallBlockArmorRoundSlope" ,
"SmallBlockArmorRoundCornerInv",
"SmallBlockArmorRoundCorner",
"SmallBlockArmorSlope2Base",
"SmallBlockArmorHalfSlopedCorner",
"SmallBlockArmorHalfCorner",
"SmallBlockArmorHalfSlopeCorner",
"HalfSlopeArmorBlock",
"HalfArmorBlock",
"SmallBlockArmorSlope2Tip",
"SmallBlockArmorBlock",
"SmallBlockArmorCornerSquareInverted",
"SmallBlockArmorCornerSquare",
"SmallBlockArmorCornerInv",
"SmallBlockArmorCorner",
"SmallBlockArmorSlope",
"SmallBlockArmorCorner2Base",
"SmallBlockArmorHalfSlopeInverted",
"SmallBlockArmorHalfSlopeCornerInverted",
"SmallBlockArmorInvCorner2Tip",
"SmallBlockArmorInvCorner2Base",
"SmallBlockArmorCorner2Tip",
"SmallBlockArmorSlopeTransitionBase",
"SmallBlockArmorSlopeTransitionTipMirrored",
"SmallBlockArmorSlopeTransitionMirrored",
"SmallBlockArmorSlopeTransitionBaseMirrored",
"SmallBlockArmorSlopeTransitionTip",
"SmallArmorPanelLight",
"SmallArmorQuarterPanelLight",
"SmallArmorHalfPanelLight",
"SmallArmor2x1HalfSlopedTipPanelLightLeft",
"SmallArmor2x1HalfSlopedPanelLightLeft",
"SmallArmor2x1HalfSlopedTipPanelLightRight",
"SmallArmor2x1HalfSlopedPanelLightRight",
"SmallArmorHalfSlopedPanelLight",
"SmallArmor2x1SlopedSideTipPanelLightInv",
"SmallArmor2x1SlopedSideBasePanelLightInv",
"SmallArmor2x1SlopedSideTipPanelLight",
"SmallArmor2x1SlopedSideBasePanelLight",
"SmallArmor2x1SlopedPanelTip",
"SmallArmor2x1SlopedPanelLight",
"SmallArmorSlopedSidePanelLight",
"SmallArmorSlopedPanelLight",
"SmallBlockArmorSlopeTransition",
"SmallHeavyBlockArmorBlock",
"SmallHeavyBlockArmorRoundSlope" ,
"SmallHeavyBlockArmorRoundCornerInv",
"SmallHeavyBlockArmorRoundCorner",
"SmallHeavyBlockArmorSlope2Base",
"SmallBlockHeavyArmorHalfSlopedCorner",
"SmallBlockHeavyArmorHalfCorner",
"SmallBlockHeavyArmorHalfSlopeCorner",
"HeavyHalfSlopeArmorBlock",
"HeavyHalfArmorBlock",
"SmallHeavyBlockArmorSlope2Tip",
"SmallHeavyBlockArmorBlock",
"SmallBlockHeavyArmorCornerSquareInverted",
"SmallBlockHeavyArmorCornerSquare",
"SmallHeavyBlockArmorCornerInv",
"SmallHeavyBlockArmorCorner",
"SmallHeavyBlockArmorSlope",
"SmallHeavyBlockArmorCorner2Base",
"SmallBlockHeavyArmorHalfSlopeInverted",
"SmallBlockHeavyArmorHalfSlopeCornerInverted",
"SmallHeavyBlockArmorInvCorner2Tip",
"SmallHeavyBlockArmorInvCorner2Base",
"SmallHeavyBlockArmorCorner2Tip",
"SmallBlockHeavyArmorSlopeTransitionBase",
"SmallBlockHeavyArmorSlopeTransitionTipMirrored",
"SmallBlockHeavyArmorSlopeTransitionMirrored",
"SmallBlockHeavyArmorSlopeTransitionBaseMirrored",
"SmallBlockHeavyArmorSlopeTransitionTip",
"SmallArmorPanelHeavy",
"SmallArmorQuarterPanelHeavy",
"SmallArmorHalfPanelHeavy",
"SmallArmor2x1HalfSlopedTipPanelHeavyLeft",
"SmallArmor2x1HalfSlopedPanelHeavyLeft",
"SmallArmor2x1HalfSlopedTipPanelHeavyRight",
"SmallArmor2x1HalfSlopedPanelHeavyRight",
"SmallArmorHalfSlopedPanelHeavy",
"SmallArmor2x1SlopedSideTipPanelHeavyInv",
"SmallArmor2x1SlopedSideBasePanelHeavyInv",
"SmallArmor2x1SlopedSideTipPanelHeavy",
"SmallArmor2x1SlopedSideBasePanelHeavy",
"SmallArmor2x1SlopedPanelTipHeavy",
"SmallArmor2x1SlopedPanelHeavy",
"SmallArmorSlopedSidePanelHeavy",
"SmallArmorSlopedPanelHeavy",
"SmallBlockHeavyArmorSlopeTransition",
"Small",
];
///
/// 大型块
///
public static string[] LargeBlock { get; } =
[
"LargeBlockArmorBlock",
"LargeBlockArmorRoundSlope" ,
"LargeBlockArmorRoundCornerInv",
"LargeBlockArmorRoundCorner",
"LargeBlockArmorSlope2Base",
"LargeBlockArmorHalfSlopedCorner",
"LargeBlockArmorHalfCorner",
"LargeBlockArmorHalfSlopeCorner",
"LargeHalfSlopeArmorBlock",
"LargeHalfArmorBlock",
"LargeBlockArmorSlope2Tip",
"LargeBlockArmorBlock",
"LargeBlockArmorCornerSquareInverted",
"LargeBlockArmorCornerSquare",
"LargeBlockArmorCornerInv",
"LargeBlockArmorCorner",
"LargeBlockArmorSlope",
"LargeBlockArmorCorner2Base",
"LargeBlockArmorHalfSlopeInverted",
"LargeBlockArmorHalfSlopeCornerInverted",
"LargeBlockArmorInvCorner2Tip",
"LargeBlockArmorInvCorner2Base",
"LargeBlockArmorCorner2Tip",
"LargeBlockArmorSlopeTransitionBase",
"LargeBlockArmorSlopeTransitionTipMirrored",
"LargeBlockArmorSlopeTransitionMirrored",
"LargeBlockArmorSlopeTransitionBaseMirrored",
"LargeBlockArmorSlopeTransitionTip",
"LargeArmorPanelLight",
"LargeArmorQuarterPanelLight",
"LargeArmorHalfPanelLight",
"LargeArmor2x1HalfSlopedTipPanelLightLeft",
"LargeArmor2x1HalfSlopedPanelLightLeft",
"LargeArmor2x1HalfSlopedTipPanelLightRight",
"LargeArmor2x1HalfSlopedPanelLightRight",
"LargeArmorHalfSlopedPanelLight",
"LargeArmor2x1SlopedSideTipPanelLightInv",
"LargeArmor2x1SlopedSideBasePanelLightInv",
"LargeArmor2x1SlopedSideTipPanelLight",
"LargeArmor2x1SlopedSideBasePanelLight",
"LargeArmor2x1SlopedPanelTipLight",
"LargeArmor2x1SlopedPanelLight",
"LargeArmorSlopedSidePanelLight",
"LargeArmorSlopedPanelLight",
"LargeBlockArmorSlopeTransition",
"LargeHeavyBlockArmorBlock",
"LargeHeavyBlockArmorRoundSlope" ,
"LargeHeavyBlockArmorRoundCornerInv",
"LargeHeavyBlockArmorRoundCorner",
"LargeHeavyBlockArmorSlope2Base",
"LargeBlockHeavyArmorHalfSlopedCorner",
"LargeBlockHeavyArmorHalfCorner",
"LargeBlockHeavyArmorHalfSlopeCorner",
"LargeHeavyHalfSlopeArmorBlock",
"LargeHeavyHalfArmorBlock",
"LargeHeavyBlockArmorSlope2Tip",
"LargeHeavyBlockArmorBlock",
"LargeBlockHeavyArmorCornerSquareInverted",
"LargeBlockHeavyArmorCornerSquare",
"LargeHeavyBlockArmorCornerInv",
"LargeHeavyBlockArmorCorner",
"LargeHeavyBlockArmorSlope",
"LargeHeavyBlockArmorCorner2Base",
"LargeBlockHeavyArmorHalfSlopeInverted",
"LargeBlockHeavyArmorHalfSlopeCornerInverted",
"LargeHeavyBlockArmorInvCorner2Tip",
"LargeHeavyBlockArmorInvCorner2Base",
"LargeHeavyBlockArmorCorner2Tip",
"LargeBlockHeavyArmorSlopeTransitionBase",
"LargeBlockHeavyArmorSlopeTransitionTipMirrored",
"LargeBlockHeavyArmorSlopeTransitionMirrored",
"LargeBlockHeavyArmorSlopeTransitionBaseMirrored",
"LargeBlockHeavyArmorSlopeTransitionTip",
"LargeArmorPanelHeavy",
"LargeArmorQuarterPanelHeavy",
"LargeArmorHalfPanelHeavy",
"LargeArmor2x1HalfSlopedTipPanelHeavyLeft",
"LargeArmor2x1HalfSlopedPanelHeavyLeft",
"LargeArmor2x1HalfSlopedTipPanelHeavyRight",
"LargeArmor2x1HalfSlopedPanelHeavyRight",
"LargeArmorHalfSlopedPanelHeavy",
"LargeArmor2x1SlopedSideTipPanelHeavyInv",
"LargeArmor2x1SlopedSideBasePanelHeavyInv",
"LargeArmor2x1SlopedSideTipPanelHeavy",
"LargeArmor2x1SlopedSideBasePanelHeavy",
"LargeArmor2x1SlopedPanelTipHeavy",
"LargeArmor2x1SlopedPanelHeavy",
"LargeArmorSlopedSidePanelHeavy",
"LargeArmorSlopedPanelHeavy",
"LargeBlockHeavyArmorSlopeTransition",
"Large",
];
///
/// 是否已经加载完成
///
public static bool IsLoadComplete { get; private set; } = false;
///
/// 所有类型定义集
///
public static DictionaryValuesReader AllDefinitions => MyDefinitionManager.Static.GetAllDefinitions();
///
/// 方块定义集
///
public static IEnumerable CubeBlockDefinitions => AllDefinitions.Where(definition => definition is MyCubeBlockDefinition).Cast();
///
/// 组件定义集
///
public static IEnumerable ComponentDefinitions => AllDefinitions.Where(definition => definition is MyComponentDefinition).Cast();
///
/// 物品定义集
///
public static IEnumerable ItemDefinitions => AllDefinitions.Where(definition => definition is MyPhysicalItemDefinition).Cast();
///
/// 场景定义集
///
public static IEnumerable ScenarioDefinition => AllDefinitions.Where(definition => definition is MyScenarioDefinition).Cast();
///
/// 加载蓝图模型
///
/// 蓝图文件路径
/// 蓝图模型(异步)
public static async Task LoadBlueprintModel(string blueprintFile) => new()
{
ViewData = LoadBlueprintInfo(blueprintFile)?.ToBlueprintInfoViewData(),
BlueprintDefinitions = await LoadBlueprintAsync(blueprintFile)
};
///
/// 异步加载蓝图定义
///
/// 蓝图文件路径
/// 蓝图定义(异步)
public static async Task LoadBlueprintAsync(string blueprintFile) => await Task.Run(() => SpaceEngineerDefinitions.Load(blueprintFile));
///
/// 加载蓝图信息
///
/// 蓝图文件路径
/// 蓝图信息
public static BlueprintInfo? LoadBlueprintInfo(string blueprintFile)
{
var rootPath = Path.GetDirectoryName(blueprintFile);
var imagePath = $@"{rootPath}\thumb.png";
return new(imagePath, File.Exists(blueprintFile), File.Exists(imagePath), Path.GetFileName(rootPath)!, new FileInfo(blueprintFile).Length.FileSize(), blueprintFile);
}
///
/// 分析蓝图定义
///
/// 蓝图属性视图数据
/// 不希望分析的属性名称列表
public static void AnalyzeBlueprint(BlueprintPropertyViewData blueprintPropertyViewData, params string[] exceptedName)
{
if (blueprintPropertyViewData.IsAnalyzed)
return;
blueprintPropertyViewData.IsAnalyzed = true;
blueprintPropertyViewData.Children.Clear();
if (CheckIfNull(blueprintPropertyViewData))
return;
if (IsCyclicReference(blueprintPropertyViewData))
return;
if (IsSpecialObject(blueprintPropertyViewData))
return;
var canMutateParent = !blueprintPropertyViewData.Type!.IsValueType ||
blueprintPropertyViewData.ValueSetter is not null;
foreach (var member in GetBrowsableMembers(blueprintPropertyViewData.Type, exceptedName))
{
try
{
if (member is FieldInfo fieldInfo)
{
var value = fieldInfo.GetValue(blueprintPropertyViewData.Value);
var child = new BlueprintPropertyViewData()
{
Type = fieldInfo.FieldType,
Name = fieldInfo.Name,
Value = value,
Parent = blueprintPropertyViewData,
ValueChanged = blueprintPropertyViewData.ValueChanged,
ValueSetter = canMutateParent && !fieldInfo.IsInitOnly && !fieldInfo.IsLiteral
? targetValue => fieldInfo.SetValue(blueprintPropertyViewData.Value, targetValue)
: null
};
SetDetail(child, value);
blueprintPropertyViewData.Children.Add(child);
}
else if (member is PropertyInfo propertyInfo)
{
var value = propertyInfo.GetValue(blueprintPropertyViewData.Value);
var child = new BlueprintPropertyViewData()
{
Type = propertyInfo.PropertyType,
Name = propertyInfo.Name,
Value = value,
Parent = blueprintPropertyViewData,
ValueChanged = blueprintPropertyViewData.ValueChanged,
ValueSetter = canMutateParent && propertyInfo.SetMethod?.IsPublic == true
? targetValue => propertyInfo.SetValue(blueprintPropertyViewData.Value, targetValue)
: null
};
SetDetail(child, value);
blueprintPropertyViewData.Children.Add(child);
}
}
catch (Exception ex)
{
blueprintPropertyViewData.Children.Add(new()
{
Type = member is FieldInfo field ? field.FieldType :
member is PropertyInfo property ? property.PropertyType : null,
Name = member.Name,
Parent = blueprintPropertyViewData,
ValueChanged = blueprintPropertyViewData.ValueChanged,
HasError = true,
ErrorMessage = ex.GetBaseException().Message,
CustomData = ex.GetBaseException().Message
});
}
}
}
private static IEnumerable GetBrowsableMembers(Type type, string[] exceptedNames)
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
var fields = type.GetFields(flags)
.Where(field => !field.IsStatic)
.Cast();
var properties = type.GetProperties(flags)
.Where(property => property.GetMethod?.IsPublic == true &&
property.GetIndexParameters().Length == 0)
.Cast();
return fields
.Concat(properties)
.Where(member => !exceptedNames.Contains(member.Name, StringComparer.Ordinal))
.GroupBy(member => member.Name, StringComparer.Ordinal)
.Select(group => group.First())
.OrderBy(member => member.Name, StringComparer.OrdinalIgnoreCase);
}
///
/// 检测是否为Null
///
/// 蓝图属性视图数据
/// 是否为Null
private static bool CheckIfNull(BlueprintPropertyViewData blueprintPropertyViewData)
{
if (blueprintPropertyViewData.Value is null || blueprintPropertyViewData.Type is null)
{
blueprintPropertyViewData.CustomData = "NullObject".GetLocalized();
return true;
}
return false;
}
private static bool IsCyclicReference(BlueprintPropertyViewData blueprintPropertyViewData)
{
if (blueprintPropertyViewData.Type?.IsValueType != false)
return false;
for (var ancestor = blueprintPropertyViewData.Parent; ancestor is not null; ancestor = ancestor.Parent)
{
if (!ReferenceEquals(ancestor.Value, blueprintPropertyViewData.Value))
continue;
blueprintPropertyViewData.CustomData = "Cyclic reference";
return true;
}
return false;
}
///
/// 是否是特殊对象
///
/// 蓝图属性视图数据
/// 是否是特殊对象
private static bool IsSpecialObject(BlueprintPropertyViewData blueprintPropertyViewData)
{
if (blueprintPropertyViewData.IsEnumerable)
{
AddArrayOrEnumerableChildren(blueprintPropertyViewData);
return true;
}
return false;
}
///
/// 添加数组或者枚举类型子数据
///
/// 蓝图属性视图数据
private static void AddArrayOrEnumerableChildren(BlueprintPropertyViewData blueprintPropertyViewData)
{
var enumerable = (IEnumerable)blueprintPropertyViewData.Value!;
var list = enumerable as IList;
var index = 0;
foreach (var item in enumerable)
{
var type = item?.GetType() ?? GetEnumerableElementType(blueprintPropertyViewData.Type!) ?? typeof(object);
var itemIndex = index;
var child = new BlueprintPropertyViewData()
{
Type = type,
Name = $"[{itemIndex}]",
DisplayNameOverride = $"[{itemIndex}] {type.Name}",
Value = item,
Parent = blueprintPropertyViewData,
ValueChanged = blueprintPropertyViewData.ValueChanged,
ValueSetter = list is not null && !list.IsReadOnly
? targetValue => list[itemIndex] = targetValue
: null
};
SetDetail(child, item);
blueprintPropertyViewData.Children.Add(child);
index++;
}
}
private static Type? GetEnumerableElementType(Type enumerableType)
{
if (enumerableType.IsArray)
return enumerableType.GetElementType();
return enumerableType
.GetInterfaces()
.Append(enumerableType)
.FirstOrDefault(type => type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
?.GetGenericArguments()[0];
}
///
/// 设置定义细节
///
/// 蓝图属性视图数据
/// 目标定义值
public static void SetDetail(BlueprintPropertyViewData blueprintPropertyViewData, object? value)
{
if (value is MyObjectBuilder_CubeBlock myObjectBuilder_CubeBlock)
{
try
{
var cubeBlock = MyDefinitionManager.Static.GetCubeBlockDefinition(myObjectBuilder_CubeBlock);
var blockName = cubeBlock?.DisplayNameText ??
myObjectBuilder_CubeBlock.SubtypeName ??
myObjectBuilder_CubeBlock.GetType().Name;
if (blueprintPropertyViewData.Name?.StartsWith('[') == true)
blueprintPropertyViewData.DisplayNameOverride = $"{blockName} {blueprintPropertyViewData.Name}";
if (cubeBlock?.Icons is { Length: > 0 })
{
var imagePath = @$"{AppPath.DefinitionImages}\{FileHelper.ChangeExtension(cubeBlock.Icons[0], "png")}";
if (File.Exists(imagePath))
blueprintPropertyViewData.CubeImage = new BitmapImage(new Uri(imagePath));
}
}
catch
{
// Mod blocks can legitimately have no currently loaded definition or icon.
}
blueprintPropertyViewData.CustomData = value is MyObjectBuilder_TerminalBlock terminalBlock
? terminalBlock.CustomName
: myObjectBuilder_CubeBlock.SubtypeName;
}
else if (value is MyObjectBuilder_CubeGrid myObjectBuilder_CubeGrid)
{
blueprintPropertyViewData.CustomData = myObjectBuilder_CubeGrid.DisplayName;
if (blueprintPropertyViewData.Name?.StartsWith('[') == true)
blueprintPropertyViewData.DisplayNameOverride =
$"{myObjectBuilder_CubeGrid.DisplayName} {blueprintPropertyViewData.Name}";
}
else if (blueprintPropertyViewData.IsEnumerable)
{
var count = value is ICollection collection
? collection.Count
: value is null
? 0
: ((IEnumerable)value).Cast