mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
clean up TypeDefinitionConverter code
This commit is contained in:
parent
77a0c9c40a
commit
d963d71b12
@ -34,6 +34,9 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Cecil, Version=0.11.3.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.11.3\lib\net40\Mono.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
@ -43,15 +46,6 @@
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Unity.Cecil">
|
||||
<HintPath>Libraries\Unity.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.CecilTools">
|
||||
<HintPath>Libraries\Unity.CecilTools.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.SerializationLogic">
|
||||
<HintPath>Libraries\Unity.SerializationLogic.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyLoader.cs" />
|
||||
@ -85,6 +79,14 @@
|
||||
<Compile Include="SpriteHelper.cs" />
|
||||
<Compile Include="Texture2DConverter.cs" />
|
||||
<Compile Include="Texture2DExtensions.cs" />
|
||||
<Compile Include="Unity.CecilTools\CecilUtils.cs" />
|
||||
<Compile Include="Unity.CecilTools\ElementType.cs" />
|
||||
<Compile Include="Unity.CecilTools\Extensions\MethodDefinitionExtensions.cs" />
|
||||
<Compile Include="Unity.CecilTools\Extensions\ResolutionExtensions.cs" />
|
||||
<Compile Include="Unity.CecilTools\Extensions\TypeDefinitionExtensions.cs" />
|
||||
<Compile Include="Unity.CecilTools\Extensions\TypeReferenceExtensions.cs" />
|
||||
<Compile Include="Unity.SerializationLogic\UnityEngineTypePredicates.cs" />
|
||||
<Compile Include="Unity.SerializationLogic\UnitySerializationLogic.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
|
||||
@ -104,5 +106,8 @@
|
||||
<Name>Texture2DDecoderWrapper</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -26,22 +26,22 @@ namespace AssetStudio
|
||||
{
|
||||
var nodes = new List<TypeTreeNode>();
|
||||
|
||||
Stack<TypeReference> baseTypes = new Stack<TypeReference>();
|
||||
TypeReference baseType = TypeDef.BaseType;
|
||||
while (!UnitySerializationLogic.IsNonSerialized(baseType))
|
||||
var baseTypes = new Stack<TypeReference>();
|
||||
var lastBaseType = TypeDef.BaseType;
|
||||
while (!UnitySerializationLogic.IsNonSerialized(lastBaseType))
|
||||
{
|
||||
GenericInstanceType genericInstanceType = baseType as GenericInstanceType;
|
||||
var genericInstanceType = lastBaseType as GenericInstanceType;
|
||||
if (genericInstanceType != null)
|
||||
{
|
||||
TypeResolver.Add(genericInstanceType);
|
||||
}
|
||||
baseTypes.Push(baseType);
|
||||
baseType = baseType.Resolve().BaseType;
|
||||
baseTypes.Push(lastBaseType);
|
||||
lastBaseType = lastBaseType.Resolve().BaseType;
|
||||
}
|
||||
while (baseTypes.Count > 0)
|
||||
{
|
||||
TypeReference typeReference = baseTypes.Pop();
|
||||
TypeDefinition typeDefinition = typeReference.Resolve();
|
||||
var typeReference = baseTypes.Pop();
|
||||
var typeDefinition = typeReference.Resolve();
|
||||
foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize))
|
||||
{
|
||||
if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef))
|
||||
@ -50,15 +50,15 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
var genericInstanceType2 = typeReference as GenericInstanceType;
|
||||
if (genericInstanceType2 != null)
|
||||
var genericInstanceType = typeReference as GenericInstanceType;
|
||||
if (genericInstanceType != null)
|
||||
{
|
||||
TypeResolver.Remove(genericInstanceType2);
|
||||
TypeResolver.Remove(genericInstanceType);
|
||||
}
|
||||
}
|
||||
foreach (FieldDefinition fieldDefinition2 in FilteredFields())
|
||||
foreach (var field in FilteredFields())
|
||||
{
|
||||
nodes.AddRange(ProcessingFieldRef(fieldDefinition2));
|
||||
nodes.AddRange(ProcessingFieldRef(field));
|
||||
}
|
||||
|
||||
return nodes;
|
||||
@ -66,75 +66,60 @@ namespace AssetStudio
|
||||
|
||||
private bool WillUnitySerialize(FieldDefinition fieldDefinition)
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
{
|
||||
TypeReference typeReference = TypeResolver.Resolve(fieldDefinition.FieldType);
|
||||
if (UnitySerializationLogic.ShouldNotTryToResolve(typeReference))
|
||||
var resolvedFieldType = TypeResolver.Resolve(fieldDefinition.FieldType);
|
||||
if (UnitySerializationLogic.ShouldNotTryToResolve(resolvedFieldType))
|
||||
{
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (!UnityEngineTypePredicates.IsUnityEngineObject(resolvedFieldType))
|
||||
{
|
||||
if (!UnityEngineTypePredicates.IsUnityEngineObject(typeReference))
|
||||
if (resolvedFieldType.FullName == fieldDefinition.DeclaringType.FullName)
|
||||
{
|
||||
if (typeReference.FullName == fieldDefinition.DeclaringType.FullName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
result = UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);
|
||||
}
|
||||
return UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception(string.Format("Exception while processing {0} {1}, error {2}", fieldDefinition.FieldType.FullName, fieldDefinition.FullName, ex.Message));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool IsHiddenByParentClass(IEnumerable<TypeReference> parentTypes, FieldDefinition fieldDefinition, TypeDefinition processingType)
|
||||
{
|
||||
return processingType.Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name) || parentTypes.Any((TypeReference t) => t.Resolve().Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name));
|
||||
return processingType.Fields.Any(f => f.Name == fieldDefinition.Name) || parentTypes.Any(t => t.Resolve().Fields.Any(f => f.Name == fieldDefinition.Name));
|
||||
}
|
||||
|
||||
private IEnumerable<FieldDefinition> FilteredFields()
|
||||
{
|
||||
foreach (var f in TypeDef.Fields.Where(WillUnitySerialize))
|
||||
{
|
||||
if (UnitySerializationLogic.IsSupportedCollection(f.FieldType) || !f.FieldType.IsGenericInstance || UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()))
|
||||
{
|
||||
yield return f;
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
return TypeDef.Fields.Where(WillUnitySerialize).Where(f =>
|
||||
UnitySerializationLogic.IsSupportedCollection(f.FieldType) ||
|
||||
!f.FieldType.IsGenericInstance ||
|
||||
UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()));
|
||||
}
|
||||
|
||||
private FieldReference ResolveGenericFieldReference(FieldReference fieldRef)
|
||||
{
|
||||
FieldReference field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType));
|
||||
var field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType));
|
||||
return TypeDef.Module.ImportReference(field);
|
||||
}
|
||||
|
||||
private TypeReference ResolveDeclaringType(TypeReference declaringType)
|
||||
{
|
||||
TypeDefinition typeDefinition = declaringType.Resolve();
|
||||
TypeReference result;
|
||||
var typeDefinition = declaringType.Resolve();
|
||||
if (typeDefinition == null || !typeDefinition.HasGenericParameters)
|
||||
{
|
||||
result = typeDefinition;
|
||||
return typeDefinition;
|
||||
}
|
||||
else
|
||||
var genericInstanceType = new GenericInstanceType(typeDefinition);
|
||||
foreach (var genericParameter in typeDefinition.GenericParameters)
|
||||
{
|
||||
GenericInstanceType genericInstanceType = new GenericInstanceType(typeDefinition);
|
||||
foreach (GenericParameter item in typeDefinition.GenericParameters)
|
||||
{
|
||||
genericInstanceType.GenericArguments.Add(item);
|
||||
}
|
||||
result = TypeResolver.Resolve(genericInstanceType);
|
||||
genericInstanceType.GenericArguments.Add(genericParameter);
|
||||
}
|
||||
return result;
|
||||
return TypeResolver.Resolve(genericInstanceType);
|
||||
}
|
||||
|
||||
private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef)
|
||||
@ -155,7 +140,6 @@ namespace AssetStudio
|
||||
|
||||
private static bool RequiresAlignment(TypeReference typeRef)
|
||||
{
|
||||
bool result;
|
||||
switch (typeRef.MetadataType)
|
||||
{
|
||||
case MetadataType.Boolean:
|
||||
@ -164,13 +148,10 @@ namespace AssetStudio
|
||||
case MetadataType.Byte:
|
||||
case MetadataType.Int16:
|
||||
case MetadataType.UInt16:
|
||||
result = true;
|
||||
break;
|
||||
return true;
|
||||
default:
|
||||
result = (UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef)));
|
||||
break;
|
||||
return UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool IsSystemString(TypeReference typeRef)
|
||||
|
65
AssetStudioUtility/Unity.CecilTools/CecilUtils.cs
Normal file
65
AssetStudioUtility/Unity.CecilTools/CecilUtils.cs
Normal file
@ -0,0 +1,65 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
using Unity.CecilTools.Extensions;
|
||||
|
||||
namespace Unity.CecilTools
|
||||
{
|
||||
public static class CecilUtils
|
||||
{
|
||||
public static MethodDefinition FindInTypeExplicitImplementationFor(MethodDefinition interfaceMethod, TypeDefinition typeDefinition)
|
||||
{
|
||||
return typeDefinition.Methods.SingleOrDefault(m => m.Overrides.Any(o => o.CheckedResolve().SameAs(interfaceMethod)));
|
||||
}
|
||||
|
||||
public static IEnumerable<TypeDefinition> AllInterfacesImplementedBy(TypeDefinition typeDefinition)
|
||||
{
|
||||
return TypeAndBaseTypesOf(typeDefinition).SelectMany(t => t.Interfaces).Select(i => i.InterfaceType.CheckedResolve()).Distinct();
|
||||
}
|
||||
|
||||
public static IEnumerable<TypeDefinition> TypeAndBaseTypesOf(TypeReference typeReference)
|
||||
{
|
||||
while (typeReference != null)
|
||||
{
|
||||
var typeDefinition = typeReference.CheckedResolve();
|
||||
yield return typeDefinition;
|
||||
typeReference = typeDefinition.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TypeDefinition> BaseTypesOf(TypeReference typeReference)
|
||||
{
|
||||
return TypeAndBaseTypesOf(typeReference).Skip(1);
|
||||
}
|
||||
|
||||
public static bool IsGenericList(TypeReference type)
|
||||
{
|
||||
return type.Name == "List`1" && type.SafeNamespace() == "System.Collections.Generic";
|
||||
}
|
||||
|
||||
public static bool IsGenericDictionary(TypeReference type)
|
||||
{
|
||||
if (type is GenericInstanceType)
|
||||
type = ((GenericInstanceType)type).ElementType;
|
||||
|
||||
return type.Name == "Dictionary`2" && type.SafeNamespace() == "System.Collections.Generic";
|
||||
}
|
||||
|
||||
public static TypeReference ElementTypeOfCollection(TypeReference type)
|
||||
{
|
||||
var at = type as ArrayType;
|
||||
if (at != null)
|
||||
return at.ElementType;
|
||||
|
||||
if (IsGenericList(type))
|
||||
return ((GenericInstanceType)type).GenericArguments.Single();
|
||||
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
21
AssetStudioUtility/Unity.CecilTools/ElementType.cs
Normal file
21
AssetStudioUtility/Unity.CecilTools/ElementType.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.CecilTools
|
||||
{
|
||||
static public class ElementType
|
||||
{
|
||||
public static TypeReference For(TypeReference byRefType)
|
||||
{
|
||||
var refType = byRefType as TypeSpecification;
|
||||
if (refType != null)
|
||||
return refType.ElementType;
|
||||
|
||||
throw new ArgumentException(string.Format("TypeReference isn't a TypeSpecification {0} ", byRefType));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.CecilTools.Extensions
|
||||
{
|
||||
static class MethodDefinitionExtensions
|
||||
{
|
||||
public static bool SameAs(this MethodDefinition self, MethodDefinition other)
|
||||
{
|
||||
// FIXME: should be able to compare MethodDefinition references directly
|
||||
return self.FullName == other.FullName;
|
||||
}
|
||||
|
||||
public static string PropertyName(this MethodDefinition self)
|
||||
{
|
||||
return self.Name.Substring(4);
|
||||
}
|
||||
|
||||
public static bool IsConversionOperator(this MethodDefinition method)
|
||||
{
|
||||
if (!method.IsSpecialName)
|
||||
return false;
|
||||
|
||||
return method.Name == "op_Implicit" || method.Name == "op_Explicit";
|
||||
}
|
||||
|
||||
public static bool IsSimpleSetter(this MethodDefinition original)
|
||||
{
|
||||
return original.IsSetter && original.Parameters.Count == 1;
|
||||
}
|
||||
|
||||
public static bool IsSimpleGetter(this MethodDefinition original)
|
||||
{
|
||||
return original.IsGetter && original.Parameters.Count == 0;
|
||||
}
|
||||
|
||||
public static bool IsSimplePropertyAccessor(this MethodDefinition method)
|
||||
{
|
||||
return method.IsSimpleGetter() || method.IsSimpleSetter();
|
||||
}
|
||||
|
||||
public static bool IsDefaultConstructor(MethodDefinition m)
|
||||
{
|
||||
return m.IsConstructor && !m.IsStatic && m.Parameters.Count == 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.CecilTools.Extensions
|
||||
{
|
||||
public static class ResolutionExtensions
|
||||
{
|
||||
public static TypeDefinition CheckedResolve(this TypeReference type)
|
||||
{
|
||||
return Resolve(type, reference => reference.Resolve());
|
||||
}
|
||||
|
||||
public static MethodDefinition CheckedResolve(this MethodReference method)
|
||||
{
|
||||
return Resolve(method, reference => reference.Resolve());
|
||||
}
|
||||
|
||||
private static TDefinition Resolve<TReference, TDefinition>(TReference reference, Func<TReference, TDefinition> resolve)
|
||||
where TReference : MemberReference
|
||||
where TDefinition : class, IMemberDefinition
|
||||
{
|
||||
if (reference.Module == null)
|
||||
throw new ResolutionException(reference);
|
||||
|
||||
var definition = resolve(reference);
|
||||
if (definition == null)
|
||||
throw new ResolutionException(reference);
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.CecilTools.Extensions
|
||||
{
|
||||
public static class TypeDefinitionExtensions
|
||||
{
|
||||
public static bool IsSubclassOf(this TypeDefinition type, string baseTypeName)
|
||||
{
|
||||
var baseType = type.BaseType;
|
||||
if (baseType == null)
|
||||
return false;
|
||||
if (baseType.FullName == baseTypeName)
|
||||
return true;
|
||||
|
||||
var baseTypeDef = baseType.Resolve();
|
||||
if (baseTypeDef == null)
|
||||
return false;
|
||||
|
||||
return IsSubclassOf(baseTypeDef, baseTypeName);
|
||||
}
|
||||
|
||||
public static bool IsSubclassOf(this TypeDefinition type, params string[] baseTypeNames)
|
||||
{
|
||||
var baseType = type.BaseType;
|
||||
if (baseType == null)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < baseTypeNames.Length; i++)
|
||||
if (baseType.FullName == baseTypeNames[i])
|
||||
return true;
|
||||
|
||||
var baseTypeDef = baseType.Resolve();
|
||||
if (baseTypeDef == null)
|
||||
return false;
|
||||
|
||||
return IsSubclassOf(baseTypeDef, baseTypeNames);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.CecilTools.Extensions
|
||||
{
|
||||
public static class TypeReferenceExtensions
|
||||
{
|
||||
public static string SafeNamespace(this TypeReference type)
|
||||
{
|
||||
if (type.IsGenericInstance)
|
||||
return ((GenericInstanceType)type).ElementType.SafeNamespace();
|
||||
if (type.IsNested)
|
||||
return type.DeclaringType.SafeNamespace();
|
||||
return type.Namespace;
|
||||
}
|
||||
|
||||
public static bool IsAssignableTo(this TypeReference typeRef, string typeName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (typeRef.IsGenericInstance)
|
||||
return ElementType.For(typeRef).IsAssignableTo(typeName);
|
||||
|
||||
if (typeRef.FullName == typeName)
|
||||
return true;
|
||||
|
||||
return typeRef.CheckedResolve().IsSubclassOf(typeName);
|
||||
}
|
||||
catch (AssemblyResolutionException) // If we can't resolve our typeref or one of its base types,
|
||||
{ // let's assume it is not assignable to our target type
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsEnum(this TypeReference type)
|
||||
{
|
||||
return type.IsValueType && !type.IsPrimitive && type.CheckedResolve().IsEnum;
|
||||
}
|
||||
|
||||
public static bool IsStruct(this TypeReference type)
|
||||
{
|
||||
return type.IsValueType && !type.IsPrimitive && !type.IsEnum() && !IsSystemDecimal(type);
|
||||
}
|
||||
|
||||
private static bool IsSystemDecimal(TypeReference type)
|
||||
{
|
||||
return type.FullName == "System.Decimal";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Unity.CecilTools.Extensions;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Unity.SerializationLogic
|
||||
{
|
||||
public class UnityEngineTypePredicates
|
||||
{
|
||||
private static readonly HashSet<string> TypesThatShouldHaveHadSerializableAttribute = new HashSet<string>
|
||||
{
|
||||
"Vector3",
|
||||
"Vector2",
|
||||
"Vector4",
|
||||
"Rect",
|
||||
"RectInt",
|
||||
"Quaternion",
|
||||
"Matrix4x4",
|
||||
"Color",
|
||||
"Color32",
|
||||
"LayerMask",
|
||||
"Bounds",
|
||||
"BoundsInt",
|
||||
"Vector3Int",
|
||||
"Vector2Int",
|
||||
};
|
||||
|
||||
private const string Gradient = "UnityEngine.Gradient";
|
||||
private const string GUIStyle = "UnityEngine.GUIStyle";
|
||||
private const string RectOffset = "UnityEngine.RectOffset";
|
||||
protected const string UnityEngineObject = "UnityEngine.Object";
|
||||
public const string MonoBehaviour = "UnityEngine.MonoBehaviour";
|
||||
public const string ScriptableObject = "UnityEngine.ScriptableObject";
|
||||
protected const string Matrix4x4 = "UnityEngine.Matrix4x4";
|
||||
protected const string Color32 = "UnityEngine.Color32";
|
||||
private const string SerializeFieldAttribute = "UnityEngine.SerializeField";
|
||||
private const string SerializeReferenceAttribute = "UnityEngine.SerializeReference";
|
||||
|
||||
private static string[] serializableClasses = new[]
|
||||
{
|
||||
"UnityEngine.AnimationCurve",
|
||||
"UnityEngine.Gradient",
|
||||
"UnityEngine.GUIStyle",
|
||||
"UnityEngine.RectOffset"
|
||||
};
|
||||
|
||||
private static string[] serializableStructs = new[]
|
||||
{
|
||||
// NOTE: assumes all types here are NOT interfaces
|
||||
"UnityEngine.Color32",
|
||||
"UnityEngine.Matrix4x4",
|
||||
"UnityEngine.Rendering.SphericalHarmonicsL2",
|
||||
"UnityEngine.PropertyName",
|
||||
};
|
||||
|
||||
public static bool IsMonoBehaviour(TypeReference type)
|
||||
{
|
||||
return IsMonoBehaviour(type.CheckedResolve());
|
||||
}
|
||||
|
||||
private static bool IsMonoBehaviour(TypeDefinition typeDefinition)
|
||||
{
|
||||
return typeDefinition.IsSubclassOf(MonoBehaviour);
|
||||
}
|
||||
|
||||
public static bool IsScriptableObject(TypeReference type)
|
||||
{
|
||||
return IsScriptableObject(type.CheckedResolve());
|
||||
}
|
||||
|
||||
private static bool IsScriptableObject(TypeDefinition temp)
|
||||
{
|
||||
return temp.IsSubclassOf(ScriptableObject);
|
||||
}
|
||||
|
||||
public static bool IsColor32(TypeReference type)
|
||||
{
|
||||
return type.IsAssignableTo(Color32);
|
||||
}
|
||||
|
||||
//Do NOT remove these, cil2as still depends on these in 4.x
|
||||
public static bool IsMatrix4x4(TypeReference type)
|
||||
{
|
||||
return type.IsAssignableTo(Matrix4x4);
|
||||
}
|
||||
|
||||
public static bool IsGradient(TypeReference type)
|
||||
{
|
||||
return type.IsAssignableTo(Gradient);
|
||||
}
|
||||
|
||||
public static bool IsGUIStyle(TypeReference type)
|
||||
{
|
||||
return type.IsAssignableTo(GUIStyle);
|
||||
}
|
||||
|
||||
public static bool IsRectOffset(TypeReference type)
|
||||
{
|
||||
return type.IsAssignableTo(RectOffset);
|
||||
}
|
||||
|
||||
public static bool IsSerializableUnityClass(TypeReference type)
|
||||
{
|
||||
foreach (var unityClasses in serializableClasses)
|
||||
{
|
||||
if (type.IsAssignableTo(unityClasses))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsSerializableUnityStruct(TypeReference type)
|
||||
{
|
||||
foreach (var unityStruct in serializableStructs)
|
||||
{
|
||||
// NOTE: structs cannot inherit from structs, and can only inherit from interfaces
|
||||
// since we know all types in serializableStructs are not interfaces,
|
||||
// we can just do a direct comparison.
|
||||
if (type.FullName == unityStruct)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.FullName.IndexOf("UnityEngine.LazyLoadReference`1") == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsUnityEngineObject(TypeReference type)
|
||||
{
|
||||
//todo: somehow solve this elegantly. CheckedResolve() drops the [] of a type.
|
||||
if (type.IsArray)
|
||||
return false;
|
||||
|
||||
if (type.FullName == UnityEngineObject)
|
||||
return true;
|
||||
|
||||
var typeDefinition = type.Resolve();
|
||||
if (typeDefinition == null)
|
||||
return false;
|
||||
|
||||
return typeDefinition.IsSubclassOf(UnityEngineObject);
|
||||
}
|
||||
|
||||
public static bool ShouldHaveHadSerializableAttribute(TypeReference type)
|
||||
{
|
||||
return IsUnityEngineValueType(type);
|
||||
}
|
||||
|
||||
public static bool IsUnityEngineValueType(TypeReference type)
|
||||
{
|
||||
return type.SafeNamespace() == "UnityEngine" && TypesThatShouldHaveHadSerializableAttribute.Contains(type.Name);
|
||||
}
|
||||
|
||||
public static bool IsSerializeFieldAttribute(TypeReference attributeType)
|
||||
{
|
||||
return attributeType.FullName == SerializeFieldAttribute;
|
||||
}
|
||||
|
||||
public static bool IsSerializeReferenceAttribute(TypeReference attributeType)
|
||||
{
|
||||
return attributeType.FullName == SerializeReferenceAttribute;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,612 @@
|
||||
// Unity C# reference source
|
||||
// Copyright (c) Unity Technologies. For terms of use, see
|
||||
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
using Mono.Collections.Generic;
|
||||
using Unity.CecilTools;
|
||||
using Unity.CecilTools.Extensions;
|
||||
|
||||
namespace Unity.SerializationLogic
|
||||
{
|
||||
internal class GenericInstanceHolder
|
||||
{
|
||||
public int Count;
|
||||
public IGenericInstance GenericInstance;
|
||||
}
|
||||
|
||||
public class TypeResolver
|
||||
{
|
||||
private readonly IGenericInstance _typeDefinitionContext;
|
||||
private readonly IGenericInstance _methodDefinitionContext;
|
||||
private readonly Dictionary<string, GenericInstanceHolder> _context = new Dictionary<string, GenericInstanceHolder>();
|
||||
|
||||
public TypeResolver()
|
||||
{
|
||||
}
|
||||
|
||||
public TypeResolver(IGenericInstance typeDefinitionContext)
|
||||
{
|
||||
_typeDefinitionContext = typeDefinitionContext;
|
||||
}
|
||||
|
||||
public TypeResolver(GenericInstanceMethod methodDefinitionContext)
|
||||
{
|
||||
_methodDefinitionContext = methodDefinitionContext;
|
||||
}
|
||||
|
||||
public TypeResolver(IGenericInstance typeDefinitionContext, IGenericInstance methodDefinitionContext)
|
||||
{
|
||||
_typeDefinitionContext = typeDefinitionContext;
|
||||
_methodDefinitionContext = methodDefinitionContext;
|
||||
}
|
||||
|
||||
public void Add(GenericInstanceType genericInstanceType)
|
||||
{
|
||||
Add(ElementTypeFor(genericInstanceType).FullName, genericInstanceType);
|
||||
}
|
||||
|
||||
public void Remove(GenericInstanceType genericInstanceType)
|
||||
{
|
||||
Remove(genericInstanceType.ElementType.FullName, genericInstanceType);
|
||||
}
|
||||
|
||||
public void Add(GenericInstanceMethod genericInstanceMethod)
|
||||
{
|
||||
Add(ElementTypeFor(genericInstanceMethod).FullName, genericInstanceMethod);
|
||||
}
|
||||
|
||||
private static MemberReference ElementTypeFor(TypeSpecification genericInstanceType)
|
||||
{
|
||||
return genericInstanceType.ElementType;
|
||||
}
|
||||
|
||||
private static MemberReference ElementTypeFor(MethodSpecification genericInstanceMethod)
|
||||
{
|
||||
return genericInstanceMethod.ElementMethod;
|
||||
}
|
||||
|
||||
public void Remove(GenericInstanceMethod genericInstanceMethod)
|
||||
{
|
||||
Remove(genericInstanceMethod.ElementMethod.FullName, genericInstanceMethod);
|
||||
}
|
||||
|
||||
public TypeReference Resolve(TypeReference typeReference)
|
||||
{
|
||||
var genericParameter = typeReference as GenericParameter;
|
||||
if (genericParameter != null)
|
||||
{
|
||||
var resolved = ResolveGenericParameter(genericParameter);
|
||||
if (genericParameter == resolved) // Resolving failed, return what we have.
|
||||
return resolved;
|
||||
|
||||
return Resolve(resolved);
|
||||
}
|
||||
|
||||
var arrayType = typeReference as ArrayType;
|
||||
if (arrayType != null)
|
||||
return new ArrayType(Resolve(arrayType.ElementType), arrayType.Rank);
|
||||
|
||||
var pointerType = typeReference as PointerType;
|
||||
if (pointerType != null)
|
||||
return new PointerType(Resolve(pointerType.ElementType));
|
||||
|
||||
var byReferenceType = typeReference as ByReferenceType;
|
||||
if (byReferenceType != null)
|
||||
return new ByReferenceType(Resolve(byReferenceType.ElementType));
|
||||
|
||||
var genericInstanceType = typeReference as GenericInstanceType;
|
||||
if (genericInstanceType != null)
|
||||
{
|
||||
var newGenericInstanceType = new GenericInstanceType(Resolve(genericInstanceType.ElementType));
|
||||
foreach (var genericArgument in genericInstanceType.GenericArguments)
|
||||
newGenericInstanceType.GenericArguments.Add(Resolve(genericArgument));
|
||||
return newGenericInstanceType;
|
||||
}
|
||||
|
||||
var pinnedType = typeReference as PinnedType;
|
||||
if (pinnedType != null)
|
||||
return new PinnedType(Resolve(pinnedType.ElementType));
|
||||
|
||||
var reqModifierType = typeReference as RequiredModifierType;
|
||||
if (reqModifierType != null)
|
||||
return Resolve(reqModifierType.ElementType);
|
||||
|
||||
var optModifierType = typeReference as OptionalModifierType;
|
||||
if (optModifierType != null)
|
||||
return new OptionalModifierType(Resolve(optModifierType.ModifierType), Resolve(optModifierType.ElementType));
|
||||
|
||||
var sentinelType = typeReference as SentinelType;
|
||||
if (sentinelType != null)
|
||||
return new SentinelType(Resolve(sentinelType.ElementType));
|
||||
|
||||
var funcPtrType = typeReference as FunctionPointerType;
|
||||
if (funcPtrType != null)
|
||||
throw new NotSupportedException("Function pointer types are not supported by the SerializationWeaver");
|
||||
|
||||
if (typeReference is TypeSpecification)
|
||||
throw new NotSupportedException();
|
||||
|
||||
return typeReference;
|
||||
}
|
||||
|
||||
private TypeReference ResolveGenericParameter(GenericParameter genericParameter)
|
||||
{
|
||||
if (genericParameter.Owner == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
var memberReference = genericParameter.Owner as MemberReference;
|
||||
if (memberReference == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
var key = memberReference.FullName;
|
||||
if (!_context.ContainsKey(key))
|
||||
{
|
||||
if (genericParameter.Type == GenericParameterType.Type)
|
||||
{
|
||||
if (_typeDefinitionContext != null)
|
||||
return _typeDefinitionContext.GenericArguments[genericParameter.Position];
|
||||
|
||||
return genericParameter;
|
||||
}
|
||||
|
||||
if (_methodDefinitionContext != null)
|
||||
return _methodDefinitionContext.GenericArguments[genericParameter.Position];
|
||||
|
||||
return genericParameter;
|
||||
}
|
||||
|
||||
return GenericArgumentAt(key, genericParameter.Position);
|
||||
}
|
||||
|
||||
private TypeReference GenericArgumentAt(string key, int position)
|
||||
{
|
||||
return _context[key].GenericInstance.GenericArguments[position];
|
||||
}
|
||||
|
||||
private void Add(string key, IGenericInstance value)
|
||||
{
|
||||
GenericInstanceHolder oldValue;
|
||||
|
||||
if (_context.TryGetValue(key, out oldValue))
|
||||
{
|
||||
var memberReference = value as MemberReference;
|
||||
if (memberReference == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
var storedValue = (MemberReference)oldValue.GenericInstance;
|
||||
|
||||
if (storedValue.FullName != memberReference.FullName)
|
||||
throw new ArgumentException("Duplicate key!", "key");
|
||||
|
||||
oldValue.Count++;
|
||||
return;
|
||||
}
|
||||
|
||||
_context.Add(key, new GenericInstanceHolder { Count = 1, GenericInstance = value });
|
||||
}
|
||||
|
||||
private void Remove(string key, IGenericInstance value)
|
||||
{
|
||||
GenericInstanceHolder oldValue;
|
||||
|
||||
if (_context.TryGetValue(key, out oldValue))
|
||||
{
|
||||
var memberReference = value as MemberReference;
|
||||
if (memberReference == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
var storedValue = (MemberReference)oldValue.GenericInstance;
|
||||
|
||||
if (storedValue.FullName != memberReference.FullName)
|
||||
throw new ArgumentException("Invalid value!", "value");
|
||||
|
||||
oldValue.Count--;
|
||||
if (oldValue.Count == 0)
|
||||
_context.Remove(key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Invalid key!", "key");
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitySerializationLogic
|
||||
{
|
||||
public static bool WillUnitySerialize(FieldDefinition fieldDefinition)
|
||||
{
|
||||
return WillUnitySerialize(fieldDefinition, new TypeResolver(null));
|
||||
}
|
||||
|
||||
public static bool WillUnitySerialize(FieldDefinition fieldDefinition, TypeResolver typeResolver)
|
||||
{
|
||||
if (fieldDefinition == null)
|
||||
return false;
|
||||
|
||||
//skip static, const and NotSerialized fields before even checking the type
|
||||
if (fieldDefinition.IsStatic || IsConst(fieldDefinition) || fieldDefinition.IsNotSerialized || fieldDefinition.IsInitOnly)
|
||||
return false;
|
||||
|
||||
// The field must have correct visibility/decoration to be serialized.
|
||||
if (!fieldDefinition.IsPublic &&
|
||||
!ShouldHaveHadAllFieldsPublic(fieldDefinition) &&
|
||||
!HasSerializeFieldAttribute(fieldDefinition) &&
|
||||
!HasSerializeReferenceAttribute(fieldDefinition))
|
||||
return false;
|
||||
|
||||
// Don't try to resolve types that come from Windows assembly,
|
||||
// as serialization weaver will fail to resolve that (due to it being in platform specific SDKs)
|
||||
if (ShouldNotTryToResolve(fieldDefinition.FieldType))
|
||||
return false;
|
||||
|
||||
if (IsFixedBuffer(fieldDefinition))
|
||||
return true;
|
||||
|
||||
// Resolving types is more complex and slower than checking their names or attributes,
|
||||
// thus keep those checks below
|
||||
var typeReference = typeResolver.Resolve(fieldDefinition.FieldType);
|
||||
|
||||
//the type of the field must be serializable in the first place.
|
||||
|
||||
if (typeReference.MetadataType == MetadataType.String)
|
||||
return true;
|
||||
|
||||
if (typeReference.IsValueType)
|
||||
return IsValueTypeSerializable(typeReference);
|
||||
|
||||
if (typeReference is ArrayType || CecilUtils.IsGenericList(typeReference))
|
||||
{
|
||||
if (!HasSerializeReferenceAttribute(fieldDefinition))
|
||||
return IsSupportedCollection(typeReference);
|
||||
}
|
||||
|
||||
|
||||
if (!IsReferenceTypeSerializable(typeReference) && !HasSerializeReferenceAttribute(fieldDefinition))
|
||||
return false;
|
||||
|
||||
if (IsDelegate(typeReference))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsDelegate(TypeReference typeReference)
|
||||
{
|
||||
return typeReference.IsAssignableTo("System.Delegate");
|
||||
}
|
||||
|
||||
public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition)
|
||||
{
|
||||
return ShouldFieldBePPtrRemapped(fieldDefinition, new TypeResolver(null));
|
||||
}
|
||||
|
||||
public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition, TypeResolver typeResolver)
|
||||
{
|
||||
if (!WillUnitySerialize(fieldDefinition, typeResolver))
|
||||
return false;
|
||||
|
||||
return CanTypeContainUnityEngineObjectReference(typeResolver.Resolve(fieldDefinition.FieldType));
|
||||
}
|
||||
|
||||
private static bool CanTypeContainUnityEngineObjectReference(TypeReference typeReference)
|
||||
{
|
||||
if (IsUnityEngineObject(typeReference))
|
||||
return true;
|
||||
|
||||
if (typeReference.IsEnum())
|
||||
return false;
|
||||
|
||||
if (IsSerializablePrimitive(typeReference))
|
||||
return false;
|
||||
|
||||
if (IsSupportedCollection(typeReference))
|
||||
return CanTypeContainUnityEngineObjectReference(CecilUtils.ElementTypeOfCollection(typeReference));
|
||||
|
||||
var definition = typeReference.Resolve();
|
||||
if (definition == null)
|
||||
return false;
|
||||
|
||||
return HasFieldsThatCanContainUnityEngineObjectReferences(definition, new TypeResolver(typeReference as GenericInstanceType));
|
||||
}
|
||||
|
||||
private static bool HasFieldsThatCanContainUnityEngineObjectReferences(TypeDefinition definition, TypeResolver typeResolver)
|
||||
{
|
||||
return AllFieldsFor(definition, typeResolver).Where(kv => kv.Value.Resolve(kv.Key.FieldType).Resolve() != definition).Any(kv => CanFieldContainUnityEngineObjectReference(definition, kv.Key, kv.Value));
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<FieldDefinition, TypeResolver>> AllFieldsFor(TypeDefinition definition, TypeResolver typeResolver)
|
||||
{
|
||||
var baseType = definition.BaseType;
|
||||
|
||||
if (baseType != null)
|
||||
{
|
||||
var genericBaseInstanceType = baseType as GenericInstanceType;
|
||||
if (genericBaseInstanceType != null)
|
||||
typeResolver.Add(genericBaseInstanceType);
|
||||
foreach (var kv in AllFieldsFor(baseType.Resolve(), typeResolver))
|
||||
yield return kv;
|
||||
if (genericBaseInstanceType != null)
|
||||
typeResolver.Remove(genericBaseInstanceType);
|
||||
}
|
||||
|
||||
foreach (var fieldDefinition in definition.Fields)
|
||||
yield return new KeyValuePair<FieldDefinition, TypeResolver>(fieldDefinition, typeResolver);
|
||||
}
|
||||
|
||||
private static bool CanFieldContainUnityEngineObjectReference(TypeReference typeReference, FieldDefinition t, TypeResolver typeResolver)
|
||||
{
|
||||
if (typeResolver.Resolve(t.FieldType) == typeReference)
|
||||
return false;
|
||||
|
||||
if (!WillUnitySerialize(t, typeResolver))
|
||||
return false;
|
||||
|
||||
if (UnityEngineTypePredicates.IsUnityEngineValueType(typeReference))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsConst(FieldDefinition fieldDefinition)
|
||||
{
|
||||
return fieldDefinition.IsLiteral && !fieldDefinition.IsInitOnly;
|
||||
}
|
||||
|
||||
public static bool HasSerializeFieldAttribute(FieldDefinition field)
|
||||
{
|
||||
//return FieldAttributes(field).Any(UnityEngineTypePredicates.IsSerializeFieldAttribute);
|
||||
foreach (var attribute in FieldAttributes(field))
|
||||
if (UnityEngineTypePredicates.IsSerializeFieldAttribute(attribute))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasSerializeReferenceAttribute(FieldDefinition field)
|
||||
{
|
||||
foreach (var attribute in FieldAttributes(field))
|
||||
if (UnityEngineTypePredicates.IsSerializeReferenceAttribute(attribute))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IEnumerable<TypeReference> FieldAttributes(FieldDefinition field)
|
||||
{
|
||||
return field.CustomAttributes.Select(_ => _.AttributeType);
|
||||
}
|
||||
|
||||
public static bool ShouldNotTryToResolve(TypeReference typeReference)
|
||||
{
|
||||
var typeReferenceScopeName = typeReference.Scope.Name;
|
||||
if (typeReferenceScopeName == "Windows")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeReferenceScopeName == "mscorlib")
|
||||
{
|
||||
var resolved = typeReference.Resolve();
|
||||
return resolved == null;
|
||||
}
|
||||
|
||||
try
|
||||
{ // This will throw an exception if typereference thinks it's referencing a .dll,
|
||||
// but actually there's .winmd file in the current directory. RRW will fix this
|
||||
// at a later step, so we will not try to resolve this type. This is OK, as any
|
||||
// type defined in a winmd cannot be serialized.
|
||||
typeReference.Resolve();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsFieldTypeSerializable(TypeReference typeReference, FieldDefinition fieldDefinition)
|
||||
{
|
||||
return IsTypeSerializable(typeReference) || IsSupportedCollection(typeReference) || IsFixedBuffer(fieldDefinition);
|
||||
}
|
||||
|
||||
private static bool IsValueTypeSerializable(TypeReference typeReference)
|
||||
{
|
||||
if (typeReference.IsPrimitive)
|
||||
return IsSerializablePrimitive(typeReference);
|
||||
return UnityEngineTypePredicates.IsSerializableUnityStruct(typeReference) ||
|
||||
typeReference.IsEnum() ||
|
||||
ShouldImplementIDeserializable(typeReference);
|
||||
}
|
||||
|
||||
private static bool IsReferenceTypeSerializable(TypeReference typeReference)
|
||||
{
|
||||
if (typeReference.MetadataType == MetadataType.String)
|
||||
return IsSerializablePrimitive(typeReference);
|
||||
|
||||
if (IsGenericDictionary(typeReference))
|
||||
return false;
|
||||
|
||||
if (IsUnityEngineObject(typeReference) ||
|
||||
ShouldImplementIDeserializable(typeReference) ||
|
||||
UnityEngineTypePredicates.IsSerializableUnityClass(typeReference))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsTypeSerializable(TypeReference typeReference)
|
||||
{
|
||||
if (typeReference.MetadataType == MetadataType.String)
|
||||
return true;
|
||||
if (typeReference.IsValueType)
|
||||
return IsValueTypeSerializable(typeReference);
|
||||
return IsReferenceTypeSerializable(typeReference);
|
||||
}
|
||||
|
||||
private static bool IsGenericDictionary(TypeReference typeReference)
|
||||
{
|
||||
var current = typeReference;
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
if (CecilUtils.IsGenericDictionary(current))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsFixedBuffer(FieldDefinition fieldDefinition)
|
||||
{
|
||||
return GetFixedBufferAttribute(fieldDefinition) != null;
|
||||
}
|
||||
|
||||
public static CustomAttribute GetFixedBufferAttribute(FieldDefinition fieldDefinition)
|
||||
{
|
||||
if (!fieldDefinition.HasCustomAttributes)
|
||||
return null;
|
||||
|
||||
return fieldDefinition.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.FixedBufferAttribute");
|
||||
}
|
||||
|
||||
public static int GetFixedBufferLength(FieldDefinition fieldDefinition)
|
||||
{
|
||||
var fixedBufferAttribute = GetFixedBufferAttribute(fieldDefinition);
|
||||
|
||||
if (fixedBufferAttribute == null)
|
||||
throw new ArgumentException(string.Format("Field '{0}' is not a fixed buffer field.", fieldDefinition.FullName));
|
||||
|
||||
var size = (Int32)fixedBufferAttribute.ConstructorArguments[1].Value;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int PrimitiveTypeSize(TypeReference type)
|
||||
{
|
||||
switch (type.MetadataType)
|
||||
{
|
||||
case MetadataType.Boolean:
|
||||
case MetadataType.Byte:
|
||||
case MetadataType.SByte:
|
||||
return 1;
|
||||
|
||||
case MetadataType.Char:
|
||||
case MetadataType.Int16:
|
||||
case MetadataType.UInt16:
|
||||
return 2;
|
||||
|
||||
case MetadataType.Int32:
|
||||
case MetadataType.UInt32:
|
||||
case MetadataType.Single:
|
||||
return 4;
|
||||
|
||||
case MetadataType.Int64:
|
||||
case MetadataType.UInt64:
|
||||
case MetadataType.Double:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
throw new ArgumentException(string.Format("Unsupported {0}", type.MetadataType));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsSerializablePrimitive(TypeReference typeReference)
|
||||
{
|
||||
switch (typeReference.MetadataType)
|
||||
{
|
||||
case MetadataType.SByte:
|
||||
case MetadataType.Byte:
|
||||
case MetadataType.Char:
|
||||
case MetadataType.Int16:
|
||||
case MetadataType.UInt16:
|
||||
case MetadataType.Int64:
|
||||
case MetadataType.UInt64:
|
||||
case MetadataType.Int32:
|
||||
case MetadataType.UInt32:
|
||||
case MetadataType.Single:
|
||||
case MetadataType.Double:
|
||||
case MetadataType.Boolean:
|
||||
case MetadataType.String:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsSupportedCollection(TypeReference typeReference)
|
||||
{
|
||||
if (!(typeReference is ArrayType || CecilUtils.IsGenericList(typeReference)))
|
||||
return false;
|
||||
|
||||
// We don't support arrays like byte[,] etc
|
||||
if (typeReference.IsArray && ((ArrayType)typeReference).Rank > 1)
|
||||
return false;
|
||||
|
||||
return IsTypeSerializable(CecilUtils.ElementTypeOfCollection(typeReference));
|
||||
}
|
||||
|
||||
private static bool ShouldHaveHadAllFieldsPublic(FieldDefinition field)
|
||||
{
|
||||
return UnityEngineTypePredicates.IsUnityEngineValueType(field.DeclaringType);
|
||||
}
|
||||
|
||||
private static bool IsUnityEngineObject(TypeReference typeReference)
|
||||
{
|
||||
return UnityEngineTypePredicates.IsUnityEngineObject(typeReference);
|
||||
}
|
||||
|
||||
public static bool IsNonSerialized(TypeReference typeDeclaration)
|
||||
{
|
||||
if (typeDeclaration == null)
|
||||
return true;
|
||||
if (typeDeclaration.HasGenericParameters)
|
||||
return true;
|
||||
if (typeDeclaration.MetadataType == MetadataType.Object)
|
||||
return true;
|
||||
var fullName = typeDeclaration.FullName;
|
||||
if (fullName.StartsWith("System.")) //can this be done better?
|
||||
return true;
|
||||
if (typeDeclaration.IsArray)
|
||||
return true;
|
||||
if (typeDeclaration.FullName == UnityEngineTypePredicates.MonoBehaviour)
|
||||
return true;
|
||||
if (typeDeclaration.FullName == UnityEngineTypePredicates.ScriptableObject)
|
||||
return true;
|
||||
if (typeDeclaration.IsEnum())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ShouldImplementIDeserializable(TypeReference typeDeclaration)
|
||||
{
|
||||
if (typeDeclaration.FullName == "UnityEngine.ExposedReference`1")
|
||||
return true;
|
||||
|
||||
if (IsNonSerialized(typeDeclaration))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
if (UnityEngineTypePredicates.ShouldHaveHadSerializableAttribute(typeDeclaration))
|
||||
return true;
|
||||
|
||||
var resolvedTypeDeclaration = typeDeclaration.CheckedResolve();
|
||||
if (resolvedTypeDeclaration.IsValueType)
|
||||
{
|
||||
return resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains("System.Runtime.CompilerServices.CompilerGenerated"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains("System.Runtime.CompilerServices.CompilerGenerated"))) ||
|
||||
resolvedTypeDeclaration.IsSubclassOf(UnityEngineTypePredicates.MonoBehaviour, UnityEngineTypePredicates.ScriptableObject);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
AssetStudioUtility/packages.config
Normal file
4
AssetStudioUtility/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Mono.Cecil" version="0.11.3" targetFramework="net472" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user