public FName GetFName() { FName result; Native_UObjectBase.GetFName(Address, out result); return(result); }
/// <summary> /// Returns the stat ID of the object... /// </summary> public TStatId GetStatId() { TStatId result; Native_UObjectBase.GetStatID(Address, out result); return(result); }
/// <summary> /// Gets the managed type for a given UObject address /// </summary> /// <param name="objectAddress">The UObject address</param> /// <returns>The managed type</returns> public static Type GetType(IntPtr objectAddress) { if (objectAddress == IntPtr.Zero) { return(null); } IntPtr unrealClassAddress = Native_UObjectBase.GetClass(objectAddress); if (unrealClassAddress == Classes.UClass) { // The objectAddress is already a class, if the type is also a UClass (UDynamicClass, UBlueprintGeneratedClass // then get the correct class type, otherwise return typeof(UClass)) Type classType = null; if (classesByAddress.TryGetValue(objectAddress, out classType) && classType.IsSubclassOf(typeof(UClass))) { return(classType); } return(typeof(UClass)); } if (unrealClassAddress != IntPtr.Zero) { Type result = null; classesByAddress.TryGetValue(unrealClassAddress, out result); return(result); } return(null); }
private void MoveToTransientPackage(IntPtr obj) { // Copy of UObjectBase.cpp UClassCompiledInDefer // Check if rooted? Native_UObjectBaseUtility.RemoveFromRoot(obj); Native_UObjectBaseUtility.ClearFlags(obj, EObjectFlags.Standalone | EObjectFlags.Public); IntPtr defaultObject = Native_UClass.GetDefaultObject(obj, false); if (defaultObject != IntPtr.Zero) { // Check if rooted? Native_UObjectBaseUtility.RemoveFromRoot(defaultObject); Native_UObjectBaseUtility.ClearFlags(defaultObject, EObjectFlags.Standalone | EObjectFlags.Public); } FName oldClassRename = NativeReflection.MakeUniqueObjectName(NativeReflection.GetTransientPackage(), Native_UObjectBase.GetClass(obj), new FName("USharpHotReload_" + Native_UObjectBase.GetFName(obj))); using (FStringUnsafe oldClassRenameUnsafe = new FStringUnsafe(oldClassRename.ToString())) { Native_UObject.Rename(obj, ref oldClassRenameUnsafe.Array, NativeReflection.GetTransientPackage(), ERenameFlags.None); } Native_UObjectBaseUtility.SetFlags(obj, EObjectFlags.Transient); Native_UObjectBaseUtility.AddToRoot(obj); }
/// <summary> /// Returns the full name of this object /// </summary> /// <param name="obj">object to retrieve the full name for; NULL (or a null class!) gives "None"</param> /// <returns>full name of the object.</returns> public static string GetFullNameSafe(UObject obj) { if (obj == null || Native_UObjectBase.GetClass(obj.Address) == IntPtr.Zero) { return("None"); } return(obj.GetFullName()); }
/// <summary> /// Gets the UClass for the given UObject address /// </summary> /// <param name="objectAddress">The address of the UObject</param> /// <returns>The UClass for the given UObject address</returns> public static UClass GetClass(IntPtr objectAddress) { if (objectAddress == IntPtr.Zero) { return(null); } return(GCHelper.Find <UClass>(Native_UObjectBase.GetClass(objectAddress))); }
/// <summary> /// Returns true if this objects class implements the given IInterface derived type /// (call this on UObject instances; if you are working with a UClass call ImplementsInterface() instead).<para/> /// This is the equivalent of UKismetSystemLibrary::DoesImplementInterface(). /// This is also the same as obj.GetClass().ImplementsInterface(). /// </summary> /// <param name="type">The IInterface derived type</param> /// <returns>True if this objects class implements the given IInterface derived type</returns> public bool DoesImplementInterface(Type type) { UClass interfaceClass = UClass.GetClass(type); if (interfaceClass != null && interfaceClass.ClassFlags.HasFlag(EClassFlags.Interface)) { return(Native_UClass.ImplementsInterface(Native_UObjectBase.GetClass(Address), interfaceClass.Address)); } return(false); }
/// <summary> /// Returns true if this objects class implements the given IInterface derived type /// (call this on UObject instances; if you are working with a UClass call ImplementsInterface() instead).<para/> /// This is the equivalent of UKismetSystemLibrary::DoesImplementInterface(). /// This is also the same as obj.GetClass().ImplementsInterface(). /// </summary> /// <typeparam name="T">The IInterface derived type</typeparam> /// <returns>True if this objects class implements the given IInterface derived type</returns> public bool DoesImplementInterface <T>() where T : IInterface { IntPtr interfaceClass = UClass.GetInterfaceClassAddress <T>(); if (interfaceClass != IntPtr.Zero && Native_UClass.GetClassFlags(interfaceClass).HasFlag(EClassFlags.Interface)) { return(Native_UClass.ImplementsInterface(Native_UObjectBase.GetClass(Address), interfaceClass)); } return(false); }
internal FLifetimePropertyCollection(IntPtr obj, TArrayUnsafeRef <FLifetimeProperty> dest) { this.dest = dest; this.nativeClass = Native_UObjectBase.GetClass(obj); if (nativeClass == IntPtr.Zero && !(FBuild.BuildShipping || FBuild.BuildTest)) { FMessage.Log(FMessage.LogNet, ELogVerbosity.Fatal, $"FLifetimePropertyCollection created for an unknown UClass"); } }
private static FName GetFunctionName(UObject obj, FSimpleDelegate function) { Delegate del = function as Delegate; if (del != null) { UObject target = del.Target as UObject; if (target != null)// Also check against obj? { IntPtr functionAddress = NativeReflection.LookupTable.FindFunction(target, del.Method); FName name; Native_UObjectBase.GetFName(functionAddress, out name); return(name); } } return(FName.None); }
/// <summary> /// Validates that the given property exists and matches the given UProperty class (e.g. UBoolProperty::StaticClass()) /// </summary> /// <param name="unrealStruct">The address of the structure which owns the property</param> /// <param name="propertyName">The name of the property</param> /// <param name="propertyClass">The expected UProperty class of the property</param> /// <returns></returns> public static bool ValidatePropertyClass(IntPtr unrealStruct, string propertyName, IntPtr propertyClass) { IntPtr field = FindField(unrealStruct, propertyName); if (field == IntPtr.Zero || !Native_UObjectBaseUtility.IsA(field, Classes.UProperty)) { return(false); } IntPtr actualClass = Native_UObjectBase.GetClass(field); if (actualClass == propertyClass) { return(true); } if (actualClass != IntPtr.Zero && propertyClass == Classes.UEnumProperty && Native_UStruct.IsChildOf(actualClass, Classes.UNumericProperty)) { return(Native_UNumericProperty.IsEnum(field)); } return(false); }
/// <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); }
/// <summary> /// Atomically clears the specified flags. /// Do not use unless you know what you are doing. /// Designed to be used only by parallel GC and UObject loading thread. /// </summary> /// <param name="flagsToClear"></param> public void AtomicallyClearFlags(EObjectFlags flagsToClear) { Native_UObjectBase.AtomicallyClearFlags(Address, flagsToClear); }
/// <summary> /// Atomically adds the specified flags. /// Do not use unless you know what you are doing. /// Designed to be used only by parallel GC and UObject loading thread. /// </summary> /// <param name="flagsToAdd"></param> public void AtomicallySetFlags(EObjectFlags flagsToAdd) { Native_UObjectBase.AtomicallySetFlags(Address, flagsToAdd); }
/// <summary> /// Retrieve the object flags directly /// </summary> /// <returns>Flags for this object</returns> public EObjectFlags GetFlags() { return(Native_UObjectBase.GetFlags(Address)); }
public UObject GetOuter() { return(cachedOuter.Update(Native_UObjectBase.GetOuter(Address))); }
public UClass GetClass() { return(cachedClass.Update(Native_UObjectBase.GetClass(Address))); }
/// <summary> /// Force a pending registrant to register now instead of in the natural order /// </summary> public static void UObjectForceRegistration(UObject obj) { Native_UObjectBase.UObjectForceRegistration(obj.Address); }
/// <summary> /// Faster version of IsValidLowLevel. /// Checks to see if the object appears to be valid by checking pointers and their alignment. /// Name and InternalIndex checks are less accurate than IsValidLowLevel. /// </summary> /// <param name="recursive">true if the Class pointer should be checked with IsValidLowLevelFast</param> /// <returns>true if this appears to be a valid object</returns> public bool IsValidLowLevelFast(bool recursive = true) { return(Native_UObjectBase.IsValidLowLevelFast(Address, recursive)); }
/// <summary> /// Checks to see if the object appears to be valid /// </summary> /// <returns>true if this appears to be a valid object</returns> public bool IsValidLowLevel() { return(Native_UObjectBase.IsValidLowLevel(Address)); }
/// <summary> /// Must be called after a module has been loaded that contains UObject classes /// </summary> public static void ProcessNewlyLoadedUObjects() { Native_UObjectBase.ProcessNewlyLoadedUObjects(); }
/// <summary> /// Returns the unique ID of the object...these are reused so it is only unique while the object is alive. /// Useful as a tag. /// </summary> /// <returns></returns> public uint GetUniqueID() { return(Native_UObjectBase.GetUniqueID(Address)); }
private static unsafe IntPtr OnAdd(IntPtr native) { UObjectRef objRef = null; int objectInternalIndex = *(int *)(native + objectInternalIndexOffset); #if ARRAY_GC while (References.Count <= objectInternalIndex) { References.Add(null); } if (References[objectInternalIndex] == null) #else if (!References.TryGetValue(native, out objRef)) #endif { bool isKnownType; Type type = UClass.GetFirstKnownType(native, out isKnownType, false); if (type == null) { // This probably means the given address is not valid (check IsValid/IsValidLowLevel/IsValidLowLevelFast ?) string className = string.Empty; string fullName = string.Empty; try { using (FStringUnsafe classNameUnsafe = new FStringUnsafe()) { Native_UObjectBaseUtility.GetName(Native_UObjectBase.GetClass(native), ref classNameUnsafe.Array); className = classNameUnsafe.Value; } } catch { } try { using (FStringUnsafe fullNameUnsafe = new FStringUnsafe()) { Native_UObjectBaseUtility.GetFullName(native, IntPtr.Zero, ref fullNameUnsafe.Array); fullName = fullNameUnsafe.Value; } } catch { } // Get a smaller stack snippet StackTrace stack = null; try { stack = new StackTrace(4); } catch { } string error = string.Format("[GCHelper-Error] Couldn't find type for requested UObject. Address: {0} (0x{1}) Name: \"{2}\" FullName: \"{3}\" Stack:\r\n{4}", native.ToInt32(), native.ToInt32().ToString("X8"), className, fullName, stack); FMessage.Log(ELogVerbosity.Error, error); Debug.Assert(false, error); return(IntPtr.Zero); } if (type.IsInterface) { // Validate that we are getting a UInterface and we aren't doing something very wrong. Debug.Assert(Native_UObjectBaseUtility.IsA(native, UClass.GetClassAddress(type))); // This should be a UInterface instance. We might want to do something more complex here // where interfaces inherit from other interfaces. type = typeof(UInterface); } objRef = objRefPool.New(native, type, isKnownType, objectInternalIndex); #if ARRAY_GC References[objectInternalIndex] = objRef; #else References.Add(native, objRef); #endif return(GCHandle.ToIntPtr(objRef.ManagedHandle)); } return(GCHandle.ToIntPtr(objRef.ManagedHandle)); }
public static ManagedUnrealClass CreateClass(Type type) { ManagedUnrealClass existingClass = FindClass(type); if (existingClass != null) { if (!FBuild.WithHotReload) { // TODO: Add support for hotreloading C# classes when WITH_HOT_RELOAD isn't available // - WITH_HOT_RELOAD will be false on shipping, monolithic and server builds // - Would need to make a copy of FHotReloadClassReinstancer (or just use it directly if // it doesn't depend on WITH_HOT_RELOAD and gets compiled into builds) // - Would likely break blueprint classes which depend on any C# classes reinstanced in this way return(existingClass); } existingClass.Clear(); HotReloadClassCount++; } if (!type.IsSubclassOf(typeof(UObject))) { return(null); } USharpPathAttribute pathAttribute = type.GetCustomAttribute <USharpPathAttribute>(); if (pathAttribute == null || string.IsNullOrEmpty(pathAttribute.Path)) { return(null); } IntPtr parentClass = GetStaticClass(type.BaseType); if (parentClass == IntPtr.Zero) { return(null); } string root, directory, moduleName, className, memberName; FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out className, out memberName); string packageName = "/" + root + "/" + directory; if (string.IsNullOrEmpty(moduleName) || string.IsNullOrEmpty(className)) { return(null); } IntPtr package = NativeReflection.FindObject(Native_UPackage.StaticClass(), IntPtr.Zero, packageName, true); if (package == IntPtr.Zero) { package = NativeReflection.CreatePackage(IntPtr.Zero, packageName); Native_UPackage.SetPackageFlags(package, EPackageFlags.CompiledIn); // TODO: Find how to create a proper guid for a package (UHT CodeGenerator.cpp seems to use a crc of generated code) using (System.Security.Cryptography.SHA256 sha256 = System.Security.Cryptography.SHA256.Create()) { byte[] hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(packageName)); // Truncate the hash byte[] buffer = new byte[16]; Buffer.BlockCopy(hash, 0, buffer, 0, buffer.Length); Native_UPackage.SetGuid(package, new Guid(buffer)); } } ManagedUnrealClass managedUnrealClass = null; if (existingClass != null) { managedUnrealClass = existingClass; } else { managedUnrealClass = new ManagedUnrealClass(type, packageName, className, parentClass); } managedUnrealClass.StaticClass = USharpClass.CreateClassPtr( managedUnrealClass.PackageName, managedUnrealClass.ClassName, (uint)Native_UStruct.GetPropertiesSize(managedUnrealClass.ParentClass), EClassFlags.None, EClassCastFlags.None, managedUnrealClass.ConfigName, managedUnrealClass.ParentClass, managedUnrealClass.WithinClass, managedUnrealClass.ClassConstructor, managedUnrealClass.ClassVTableHelperCtorCaller, managedUnrealClass.ClassAddReferencedObjects); Native_UObjectBase.UObjectForceRegistration(managedUnrealClass.StaticClass); if (existingClass == null) { Classes.Add(type, managedUnrealClass); ClassesByAddress.Add(managedUnrealClass.StaticClass, managedUnrealClass); } managedUnrealClass.Initialize(); return(managedUnrealClass); }