private IntPtr CreateProperty(IntPtr outer, PropertyInfo propertyInfo) { // Note that HeaderParser.cpp and UObjectGlobals.cpp use "new" instead of NewObject for creating properties // KismetCompilerMisc.cpp uses NewObject // The "new" initialization sets the offset and adds the property to the owner which in the case of UStruct // does the following: // void UStruct::AddCppProperty(UProperty* Property) { Property->Next = Children; Children = Property; } USharpPathAttribute pathAttribute = propertyInfo.GetCustomAttribute <USharpPathAttribute>(); if (pathAttribute == null) { return(IntPtr.Zero); } string root, directory, moduleName, typeName, propertyName; FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out typeName, out propertyName); if (string.IsNullOrEmpty(propertyName)) { return(IntPtr.Zero); } IntPtr property = CreateProperty(outer, propertyInfo.PropertyType, propertyName, pathAttribute.PropertyType, pathAttribute.InnerPropertyType1, pathAttribute.InnerPropertyType2); if (property == IntPtr.Zero) { return(IntPtr.Zero); } if (FBuild.WithMetaData) { IntPtr outermost = Native_UObjectBaseUtility.GetOutermost(property); IntPtr metadata = outermost == IntPtr.Zero ? IntPtr.Zero : Native_UPackage.GetMetaData(outermost); if (metadata != IntPtr.Zero) { string categoryName = null; //propertyInfo.GetCustomAttribute if (string.IsNullOrEmpty(categoryName)) { categoryName = "Default"; } SetMetaData(metadata, property, "Category", categoryName); } } return(property); }
private static void LoadInternal(Assembly thisAssembly, Assembly assembly) { if (processedAssemblies.Contains(assembly)) { return; } processedAssemblies.Add(assembly); bool referencesThisAssembly = false; if (assembly == thisAssembly) { referencesThisAssembly = true; } else { foreach (AssemblyName assemblyName in assembly.GetReferencedAssemblies()) { if (assemblyName.FullName == thisAssembly.FullName) { referencesThisAssembly = true; break; } } } if (!referencesThisAssembly) { return; } List <Type> types = new List <Type>(); Dictionary <Type, UMetaPathAttribute> nativeTypes = new Dictionary <Type, UMetaPathAttribute>(); Dictionary <Type, USharpPathAttribute> managedTypes = new Dictionary <Type, USharpPathAttribute>(); Type assemblyModuleInfoType = null; foreach (Type type in assembly.GetTypes()) { UUnrealTypePathAttribute pathAttribute = type.GetCustomAttribute <UUnrealTypePathAttribute>(false); if (pathAttribute != null && !string.IsNullOrEmpty(pathAttribute.Path)) { USharpPathAttribute sharpPathAttribute = pathAttribute as USharpPathAttribute; if (sharpPathAttribute != null) { AllByPath[pathAttribute.Path] = type; ManagedByPath[pathAttribute.Path] = type; All[type] = sharpPathAttribute; Managed[type] = sharpPathAttribute; types.Add(type); managedTypes[type] = sharpPathAttribute; } else { UMetaPathAttribute metaPathAttribute = pathAttribute as UMetaPathAttribute; if (metaPathAttribute != null) { AllByPath[pathAttribute.Path] = type; NativeByPath[pathAttribute.Path] = type; All[type] = metaPathAttribute; Native[type] = metaPathAttribute; types.Add(type); nativeTypes[type] = metaPathAttribute; } } } if (typeof(ISerializedManagedUnrealModuleInfo).IsAssignableFrom(type) && type != typeof(ISerializedManagedUnrealModuleInfo)) { assemblyModuleInfoType = type; } } if (types.Count > 0) { Assemblies[assembly] = types; AssembliesManagedTypes[assembly] = managedTypes; AssembliesNativeTypes[assembly] = nativeTypes; if (assemblyModuleInfoType != null) { AssemblySerializedModuleInfo[assembly] = assemblyModuleInfoType; } } }
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); }