Beispiel #1
0
        private static IntPtr GetStruct(string path, bool canBeNull = false)
        {
            IntPtr address = NativeReflection.FindObject(UScriptStruct, IntPtr.Zero, path, false);

            Debug.Assert(address != IntPtr.Zero || canBeNull);
            return(address);
        }
Beispiel #2
0
        // Is there any benefit of writing a loader for UFunction here? Native types will be loaded in the module
        // is loaded and Blueprint function delegates would be loaded with the owning class.

        /// <summary>
        /// Gets the UFunction address for the given path (e.g. "/Script/Engine.Actor:SetOwner")
        /// </summary>
        /// <param name="path">The path of the UFunction</param>
        /// <returns>The address of the UFunction for the given path</returns>
        public static IntPtr GetFunctionAddress(string path)
        {
            IntPtr address = NativeReflection.FindObject(Classes.UFunction, IntPtr.Zero, path, false);

            if (address == IntPtr.Zero)
            {
                // To resolve this a call to FCoreRedirects.GetRedirectedName would be required with a UProperty type?
                // - Or this just isn't possible to resolve.
                // TODO: Attempt trying to create a redirected delegate in C++ and see what happens and how to resolve it.
            }
            return(address);
        }
Beispiel #3
0
        /// <summary>
        /// Gets the UClass address for the given path (e.g. "/Script/Engine.Actor")
        /// </summary>
        /// <param name="path">The path of the object/class</param>
        /// <returns>The UClass address</returns>
        public static IntPtr GetClassAddress(string path)
        {
            IntPtr address = NativeReflection.FindObject(Classes.UClass, IntPtr.Zero, path, false);

            if (address == IntPtr.Zero)
            {
                FName newPath = FLinkerLoad.FindNewNameForClass(new FName(path), false);
                if (newPath != FName.None)
                {
                    address = NativeReflection.FindObject(Classes.UClass, IntPtr.Zero, newPath.ToString(), false);
                }
            }
            return(address);
        }
Beispiel #4
0
 internal static IntPtr GetEnum(Type type)
 {
     if (IsManagedUnrealType(type))
     {
     }
     else
     {
         UMetaPathAttribute pathAttribute = type.GetCustomAttribute <UMetaPathAttribute>();
         if (pathAttribute != null)
         {
             return(NativeReflection.FindObject(Native_UEnum.StaticClass(), IntPtr.Zero, pathAttribute.Path, true));
         }
     }
     return(IntPtr.Zero);
 }
Beispiel #5
0
 /// <summary>
 /// Gets the UProperty address for the given path (e.g. "/Script/Engine.Actor:bReplicates")
 /// </summary>
 /// <param name="path">The path of the UProperty</param>
 /// <returns>The address of the UProperty for the given path</returns>
 public static IntPtr GetPropertyAddress(string path)
 {
     return(NativeReflection.FindObject(Classes.UProperty, IntPtr.Zero, path, false));
 }
Beispiel #6
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);
        }