internal static IntPtr GetStaticClass(Type type) { if (IsManagedUnrealType(type)) { ManagedUnrealClass baseClass = FindClass(type); if (baseClass != null) { return(baseClass.StaticClass); } baseClass = CreateClass(type); if (baseClass != null) { return(baseClass.StaticClass); } } else { UMetaPathAttribute pathAttribute = type.GetCustomAttribute <UMetaPathAttribute>(); if (pathAttribute != null) { return(UClass.FindClassAddressByPath(pathAttribute.Path)); } } return(IntPtr.Zero); }
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); }