示例#1
0
        public FName GetFName()
        {
            FName result;

            Native_UObjectBase.GetFName(Address, out result);
            return(result);
        }
示例#2
0
        /// <summary>
        /// Returns the stat ID of the object...
        /// </summary>
        public TStatId GetStatId()
        {
            TStatId result;

            Native_UObjectBase.GetStatID(Address, out result);
            return(result);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        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);
        }
示例#5
0
 /// <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());
 }
示例#6
0
 /// <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)));
 }
示例#7
0
        /// <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);
        }
示例#8
0
        /// <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);
        }
示例#9
0
        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");
            }
        }
示例#10
0
        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);
        }
示例#11
0
        /// <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);
        }
示例#12
0
        /// <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);
        }
示例#13
0
 /// <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);
 }
示例#14
0
 /// <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);
 }
示例#15
0
 /// <summary>
 /// Retrieve the object flags directly
 /// </summary>
 /// <returns>Flags for this object</returns>
 public EObjectFlags GetFlags()
 {
     return(Native_UObjectBase.GetFlags(Address));
 }
示例#16
0
 public UObject GetOuter()
 {
     return(cachedOuter.Update(Native_UObjectBase.GetOuter(Address)));
 }
示例#17
0
 public UClass GetClass()
 {
     return(cachedClass.Update(Native_UObjectBase.GetClass(Address)));
 }
示例#18
0
 /// <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);
 }
示例#19
0
 /// <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));
 }
示例#20
0
 /// <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));
 }
示例#21
0
 /// <summary>
 /// Must be called after a module has been loaded that contains UObject classes
 /// </summary>
 public static void ProcessNewlyLoadedUObjects()
 {
     Native_UObjectBase.ProcessNewlyLoadedUObjects();
 }
示例#22
0
 /// <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));
 }
示例#23
0
        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));
        }
示例#24
0
        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);
        }