/// <summary> /// Gets the first known managed type for a given UClass /// </summary> /// <param name="unrealClass">The UClass to get the managed type from</param> /// <param name="includeAbstract">Include abstract types (if true a wrapper cannot be instantiated from this type)</param> /// <returns>The managed type</returns> public static Type GetFirstKnownType(UClass unrealClass, bool includeAbstract = true) { Type type = null; IntPtr unrealClassAddress = unrealClass.Address; while (type == null && unrealClassAddress != IntPtr.Zero) { classesByAddress.TryGetValue(unrealClassAddress, out type); if (type != null && !includeAbstract && type.IsAbstract) { type = null; } unrealClassAddress = Native_UStruct.GetSuperStruct(unrealClassAddress); } return(type); }
/// <summary> /// Gets the first known type from a given UObject address (classes may be defined at runtime which we don't have a type mapping for. /// Look up the inheritance chain until we have a known type) /// </summary> /// <param name="objectAddress">The UObject address</param> /// <param name="isKnownType">True if the result is the exact type of the given UObject address</param> /// <param name="includeAbstract">Include abstract types (if true a wrapper cannot be instantiated from this type)</param> /// <returns>The first known managed type</returns> public static Type GetFirstKnownType(IntPtr objectAddress, out bool isKnownType, bool includeAbstract = true) { isKnownType = true; if (objectAddress == IntPtr.Zero) { return(null); } Type type = GetType(objectAddress); if (type != null && (!type.IsAbstract || includeAbstract)) { return(type); } else { type = null; } IntPtr parentClassAddress = IntPtr.Zero; IntPtr unrealClassAddress = Native_UObjectBase.GetClass(objectAddress); if (unrealClassAddress == Classes.UClass) { // The objectAddress is already a class unrealClassAddress = objectAddress; } if (unrealClassAddress != IntPtr.Zero) { parentClassAddress = Native_UStruct.GetSuperStruct(unrealClassAddress); } while (type == null && parentClassAddress != IntPtr.Zero) { isKnownType = false; classesByAddress.TryGetValue(parentClassAddress, out type); if (type != null && type.IsAbstract && !includeAbstract) { type = null; } parentClassAddress = Native_UStruct.GetSuperStruct(parentClassAddress); } if (type == null && unrealClassAddress != IntPtr.Zero) { // Some fallbacks if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UStruct)) { if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UClass)) { if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UBlueprintGeneratedClass)) { return(typeof(UBlueprintGeneratedClass)); } return(typeof(UClass)); } if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UScriptStruct)) { if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UUserDefinedStruct)) { return(typeof(UUserDefinedStruct)); } return(typeof(UScriptStruct)); } if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UEnum)) { if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UUserDefinedEnum)) { return(typeof(UUserDefinedEnum)); } return(typeof(UEnum)); } if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UFunction)) { return(typeof(UFunction)); } return(typeof(UStruct)); } // UObject fallback (would expect this to always be true) if (Native_UStruct.IsChildOf(unrealClassAddress, Classes.UObject)) { return(typeof(UObject)); } } return(type); }