public bool TryGetFilename(out string fileName, out string error) { error = null; // Get the filename without the valid file extension e.g. "../../../Engine/Test/AssetName.AssetName" if (!FPackageName.TryConvertLongPackageNameToFilename(ObjectPath.ToString(), out fileName)) { error = "Couldn't find package for asset " + ObjectPath.ToString(); return(false); } // Remove the dummy extension "AssetName.AssetName" -> "AssetName" int LastDot = fileName.LastIndexOf('.'); if (LastDot <= 0) { error = "Bad filename: " + fileName; return(false); } fileName = fileName.Substring(0, LastDot); // Get the filename with the correct file extension ("WithoutExtension" means the input doesn't have an extension) if (!FPackageName.FindPackageFileWithoutExtension(fileName, out fileName) || !FPaths.FileExists(fileName)) { error = "Couldn't find asset: " + fileName; return(false); } return(true); }
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 void GenerateCodeForModule(UnrealModuleInfo module) { List <UStruct> structs = new List <UStruct>(); List <UEnum> enums = new List <UEnum>(); List <UFunction> globalFunctions = new List <UFunction>(); foreach (UStruct unrealStruct in new TObjectIterator <UStruct>()) { if (!unrealStruct.IsA <UFunction>() && unrealStruct.IsIn(module.Package) && CanExportStruct(unrealStruct) && IsAvailableType(unrealStruct)) { structs.Add(unrealStruct); } } foreach (UEnum unrealEnum in new TObjectIterator <UEnum>()) { if (unrealEnum.IsIn(module.Package) && CanExportEnum(unrealEnum) && IsAvailableType(unrealEnum)) { enums.Add(unrealEnum); } } UClass packageClass = UClass.GetClass <UPackage>(); foreach (UFunction function in new TObjectIterator <UFunction>()) { UObject outer = function.GetOuter(); if (outer == null || outer.GetClass() != packageClass) { continue; } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate) && function.IsIn(module.Package)) { globalFunctions.Add(function); } } SlowTaskSetModuleCount(1); SlowTaskBeginModule(FPackageName.GetShortName(module.Package), structs.Count + enums.Count + globalFunctions.Count); GenerateCodeForModule(module, structs.ToArray(), enums.ToArray(), globalFunctions.ToArray()); }
public void GenerateCodeForModule(string moduleName, bool loadModule) { string longPackageName = FPackageName.ConvertToLongScriptPackageName(moduleName); UPackage package = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false); if (package == null && !FModuleManager.Instance.IsModuleLoaded(new FName(moduleName))) { // package is almost always non-null even when IsModuleLoaded returns false - if the package is non-null it // seems the module types are available so we don't have to call LoadModule (check if this is always true) if (!loadModule) { return; } EModuleLoadResult loadResult; FModuleManager.Instance.LoadModuleWithFailureReason(new FName(moduleName), out loadResult); if (loadResult != EModuleLoadResult.Success) { FMessage.Log("Failed to load module '" + moduleName + "'. Reason: " + loadResult); return; } package = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false); } if (package != null) { Dictionary <FName, string> modulePaths = FModulesPaths.FindModulePaths("*"); string modulePath; if (!modulePaths.TryGetValue(new FName(moduleName), out modulePath)) { return; } BeginGenerateModules(); GenerateCodeForModule(new UnrealModuleInfo(package, moduleName, modulePath)); EndGenerateModules(); } }
public void GenerateCodeForModules(UnrealModuleType[] moduleTypes) { BeginGenerateModules(); HashSet <string> moduleNamesWhitelistToLower = new HashSet <string>(); foreach (string moduleName in ModulesNamesWhitelist) { moduleNamesWhitelistToLower.Add(moduleName.ToLower()); } HashSet <string> moduleNamesBlacklistToLower = new HashSet <string>(); foreach (string moduleName in ModulesNamesBlacklist) { moduleNamesBlacklistToLower.Add(moduleName.ToLower()); } Dictionary <UPackage, List <UStruct> > structsByPackage = new Dictionary <UPackage, List <UStruct> >(); Dictionary <UPackage, List <UEnum> > enumsByPackage = new Dictionary <UPackage, List <UEnum> >(); Dictionary <UPackage, List <UFunction> > globalFunctionsByPackage = new Dictionary <UPackage, List <UFunction> >(); foreach (UStruct unrealStruct in new TObjectIterator <UStruct>()) { if (!unrealStruct.IsA <UFunction>() && CanExportStruct(unrealStruct) && IsAvailableType(unrealStruct)) { UPackage package = unrealStruct.GetOutermost(); if (package != null) { List <UStruct> structs; if (!structsByPackage.TryGetValue(package, out structs)) { structsByPackage.Add(package, structs = new List <UStruct>()); } structs.Add(unrealStruct); } } } foreach (UEnum unrealEnum in new TObjectIterator <UEnum>()) { if (CanExportEnum(unrealEnum) && IsAvailableType(unrealEnum)) { UPackage package = unrealEnum.GetOutermost(); if (package != null) { List <UEnum> enums; if (!enumsByPackage.TryGetValue(package, out enums)) { enumsByPackage.Add(package, enums = new List <UEnum>()); } enums.Add(unrealEnum); } } } UClass packageClass = UClass.GetClass <UPackage>(); foreach (UFunction function in new TObjectIterator <UFunction>()) { UObject outer = function.GetOuter(); if (outer == null || outer.GetClass() != packageClass) { continue; } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate)) { UPackage package = function.GetOutermost(); if (package != null) { List <UFunction> functions; if (!globalFunctionsByPackage.TryGetValue(package, out functions)) { globalFunctionsByPackage.Add(package, functions = new List <UFunction>()); } functions.Add(function); } } else { FMessage.Log(ELogVerbosity.Error, string.Format("Global function which isn't a delegate '{0}'", function.GetName())); } } Dictionary <FName, string> modulePaths = FModulesPaths.FindModulePaths("*"); // Make sure ModulePaths and ModuleNames are the same. Based on comments FindModules may be changed/removed in the // future so we will want to just use FindModulePaths. For now make sure they are synced up. FName[] moduleNames = FModuleManager.Get().FindModules("*"); if (moduleNames.Length != modulePaths.Count) { FMessage.Log(ELogVerbosity.Warning, string.Format("Module count invalid (update FModulePaths). FindModules:{0} FindModulePaths:{1}", moduleNames.Length, modulePaths.Count)); List <FName> additionalNames = new List <FName>(); foreach (KeyValuePair <FName, string> module in modulePaths) { if (moduleNames.Contains(module.Key)) { FMessage.Log(ELogVerbosity.Warning, "Module: " + module.Key + " - " + module.Value); } else { FMessage.Log(ELogVerbosity.Warning, "Additional module: " + module.Key + " - " + module.Value); } } List <FName> missingNames = new List <FName>(); foreach (FName moduleName in moduleNames) { if (!modulePaths.ContainsKey(moduleName)) { FMessage.Log(ELogVerbosity.Warning, "Missing module: " + moduleName); } } } IPlugin[] plugins = IPluginManager.Instance.GetDiscoveredPlugins(); SlowTaskSetModuleCount(modulePaths.Count); foreach (KeyValuePair <FName, string> modulePath in modulePaths) { SlowTaskBeginModule(modulePath.Key.PlainName); string moduleName = modulePath.Key.PlainName; string longPackageName = FPackageName.ConvertToLongScriptPackageName(moduleName); UPackage package = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false); if (package != null) { UnrealModuleInfo moduleInfo = new UnrealModuleInfo(package, moduleName, modulePath.Value, UnrealModuleInfo.GetModuleType(moduleName, modulePath.Value, plugins)); if (moduleInfo.Type == UnrealModuleType.Unknown) { FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module type on module '{0}' '{1}'", moduleInfo.Name, moduleInfo.Package)); } else if (!moduleTypes.Contains(moduleInfo.Type) || moduleNamesBlacklistToLower.Contains(moduleInfo.Name.ToLower()) || (moduleNamesWhitelistToLower.Count > 0 && !moduleNamesWhitelistToLower.Contains(moduleInfo.Name.ToLower()))) { continue; } List <UStruct> structs; if (!structsByPackage.TryGetValue(package, out structs)) { structs = new List <UStruct>(); } List <UEnum> enums; if (!enumsByPackage.TryGetValue(package, out enums)) { enums = new List <UEnum>(); } List <UFunction> globalFunctions; if (!globalFunctionsByPackage.TryGetValue(package, out globalFunctions)) { globalFunctions = new List <UFunction>(); } SlowTaskUpdateTarget(structs.Count + enums.Count + globalFunctions.Count); GenerateCodeForModule(moduleInfo, structs.ToArray(), enums.ToArray(), globalFunctions.ToArray()); } } IPlugin.Dispose(plugins); EndGenerateModules(); }
private string GetModuleNamespace(UnrealModuleType moduleType, string moduleName, UnrealModuleType moduleAssetType, bool allowFoldersAsNamespace, string path) { string namespaceName = null; switch (moduleType) { case UnrealModuleType.Game: switch (moduleAssetType) { case UnrealModuleType.Engine: namespaceName = Settings.Namespaces.EngineAsset; break; case UnrealModuleType.GamePlugin: namespaceName = Settings.Namespaces.GamePluginAsset; break; case UnrealModuleType.EnginePlugin: namespaceName = Settings.Namespaces.EnginePluginAsset; break; default: namespaceName = Settings.Namespaces.Game; break; } break; case UnrealModuleType.GamePlugin: namespaceName = Settings.Namespaces.GamePlugin; break; case UnrealModuleType.Engine: namespaceName = Settings.Namespaces.Engine; if (moduleName == "CoreUObject") { // Allow CoreUObject to be redirected to a common namespace name (UnrealEngine.Runtime) namespaceName = GetEngineObjectNamespace(); } break; case UnrealModuleType.EnginePlugin: namespaceName = Settings.Namespaces.EnginePlugin; break; default: return(namespaceName); } if (string.IsNullOrWhiteSpace(namespaceName)) { return(null); } if (namespaceName.Contains("{Default}")) { namespaceName = namespaceName.Replace("{Default}", Settings.Namespaces.Default); } if (namespaceName.Contains("{Game}")) { string gameName = FPaths.GetBaseFilename(FPaths.ProjectFilePath); namespaceName = namespaceName.Replace("{Game}", gameName); } if (namespaceName.Contains("{Module}")) { namespaceName = namespaceName.Replace("{Module}", moduleName); } if (namespaceName.Contains("{Folder}")) { if (allowFoldersAsNamespace && moduleAssetType != UnrealModuleType.Unknown) { // Get the directory of the file and remove root name "/Game/" string directory = FPackageName.GetLongPackagePath(path); int slashIndex = directory.IndexOf('/', 1); if (slashIndex >= 0) { directory = directory.Substring(slashIndex + 1); } else { // The path is empty or only the root name directory = string.Empty; } // Make each '/' a part of the namespace string expandedNamespace = directory.Replace("/", "."); namespaceName = namespaceName.Replace("{Folder}", expandedNamespace); } else { namespaceName = namespaceName.Replace("{Folder}", string.Empty); } } // Remove duplicate '.' chars StringBuilder result = new StringBuilder(namespaceName); for (int i = result.Length - 1; i >= 0; --i) { if (result[i] == '.') { if (i == 0 || result[i - 1] == '.' || i == result.Length - 1) { result.Remove(i, 1); } } } return(result.ToString()); }
private string GetModuleNamespace(UField field, out UnrealModuleType moduleAssetType, bool allowFoldersAsNamespace = true) { moduleAssetType = UnrealModuleType.Unknown; UPackage package = field.GetOutermost(); if (package != null) { CachedNamespace cachedNamespace; if (namespaceCache.TryGetValue(package, out cachedNamespace)) { moduleAssetType = cachedNamespace.ModuleAssetType; return(cachedNamespace.Namespace); } UnrealModuleType moduleType = UnrealModuleType.Unknown; moduleAssetType = UnrealModuleType.Unknown; string packageFilename = package.FileName.ToString(); if (string.IsNullOrEmpty(packageFilename.ToString()) || packageFilename == FName.None.ToString()) { packageFilename = field.GetPathName(); } string moduleName = FPackageName.GetShortName(package.GetName()); if (packageFilename.StartsWith("/Script")) { if (!modulesByName.TryGetValue(new FName(moduleName), out moduleType)) { moduleType = UnrealModuleType.Unknown; FMessage.Log(ELogVerbosity.Error, string.Format("Failed to find module for module '{0}'", moduleName)); } } else if (packageFilename.StartsWith("/Game/")) { moduleType = UnrealModuleType.Game; moduleAssetType = UnrealModuleType.Game; moduleName = FPaths.GetBaseFilename(FPaths.ProjectFilePath);// {Module} same as {Game} } else if (packageFilename.StartsWith("/Engine/")) { moduleType = UnrealModuleType.Game; moduleAssetType = UnrealModuleType.Engine; moduleName = Settings.Namespaces.Default; } else { string rootName = null; if (packageFilename.Length > 1 && packageFilename[0] == '/') { int slashIndex = packageFilename.IndexOf('/', 1); if (slashIndex >= 0) { rootName = packageFilename.Substring(1, slashIndex - 1); moduleName = rootName;// Update ModuleName for {Module} if (!modulesByName.TryGetValue(new FName(rootName), out moduleAssetType)) { moduleAssetType = UnrealModuleType.Unknown; } } } if (moduleAssetType == UnrealModuleType.Unknown) { FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module asset type root:'{0}' path:'{1}' name:'{2}' path2:'{3}'", rootName, packageFilename, field.GetName(), field.GetPathName())); } moduleType = UnrealModuleType.Game; } if (moduleType != UnrealModuleType.Unknown) { string namespaceName = GetModuleNamespace(moduleType, moduleName, moduleAssetType, allowFoldersAsNamespace, packageFilename); namespaceCache[package] = new CachedNamespace(namespaceName, moduleName, moduleType, moduleAssetType); return(namespaceName); } else { FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module type {0} {1}", packageFilename, moduleName)); } } return(null); }
public void OnCodeGenerated(CodeGenerator.UnrealModuleInfo module, UnrealModuleType moduleAssetType, string typeName, string path, string code) { // Note: path will be empty if using combined enums file or global delegates files string root, directory, moduleName, assetName, memberName; FPackageName.GetPathInfo(path, out root, out directory, out moduleName, out assetName, out memberName); //Log("path:'{0}' root:'{1}' directory:'{2}' asset:'{3}' member:'{4}'", path, root, directory, assetName, memberName); string rootFolderName = GetRootFolderName(path, root, module.Type, moduleAssetType); if (string.IsNullOrEmpty(rootFolderName) && !string.IsNullOrEmpty(path)) { Log(ELogVerbosity.Error, "Unknown asset root '{0}' ModuleType:'{1}' ModuleAssetType:'{2}' Path:'{3}'", root, module.Type, moduleAssetType, path); return; } string name = Settings.UseTypeNameAsSourceFileName || string.IsNullOrEmpty(assetName) ? typeName : assetName; string sourceFilePath = null; string projPath = null; string slnPath = null; switch (module.Type) { case UnrealModuleType.Game: { string relativeSourceFilePath = null; if (EmulateGameFolderStructure(moduleAssetType)) { relativeSourceFilePath = Path.Combine(directory, name + ".cs"); } else { relativeSourceFilePath = name + ".cs"; } string baseCodeDir = Settings.GetGeneratedCodeDir(false); if (module.IsBlueprint) { baseCodeDir = Path.Combine(Settings.GetManagedDir(), Settings.GetProjectName() + ".Managed", "Blueprint", "Generated"); } if (moduleAssetType == UnrealModuleType.Unknown) { // Don't use root folders for native game code wrappers as root folders don't make much sense for them sourceFilePath = Path.Combine(baseCodeDir, relativeSourceFilePath); } else { sourceFilePath = Path.Combine(baseCodeDir, rootFolderName, relativeSourceFilePath); } slnPath = GameSlnPath; projPath = module.IsBlueprint ? GameProjPath : GameNativeGenerationProjPath; } break; case UnrealModuleType.EnginePlugin: case UnrealModuleType.Engine: { bool mergeAsPluginProj = false; bool mergeAsUnrealProj = false; switch (Settings.EngineProjMerge) { case CodeGeneratorSettings.ManagedEngineProjMerge.Engine: if (module.Type == UnrealModuleType.Engine) { mergeAsUnrealProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.Plugins: if (module.Type == UnrealModuleType.EnginePlugin) { mergeAsPluginProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPlugins: if (module.Type == UnrealModuleType.EnginePlugin) { mergeAsPluginProj = true; } else { mergeAsUnrealProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined: mergeAsUnrealProj = true; break; } if (mergeAsPluginProj || mergeAsUnrealProj) { string projName = mergeAsUnrealProj ? "UnrealEngine.csproj" : "UnrealEngine.Plugins.csproj"; if (Settings.EngineProjMerge == CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined) { projPath = Path.Combine(Settings.GetManagedModulesDir(), projName); } else { projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, projName); } } else { projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, module.Name + ".csproj"); } sourceFilePath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, name + ".cs"); if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSln) { slnPath = GameSlnPath; } else if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSlnProj) { slnPath = GameSlnPath; projPath = GameProjPath; } else { slnPath = Path.Combine(Settings.GetManagedModulesDir(), "UnrealEngine.sln"); } } break; case UnrealModuleType.GamePlugin: { if (moduleAssetType == UnrealModuleType.Unknown) { // Don't use root folders for native game code wrappers as root folders don't make much sense for them sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(true), module.Name, name + ".cs"); } else { sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(true), rootFolderName, module.Name, name + ".cs"); } slnPath = GameSlnPath; if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.GameAndPlugins) { projPath = GameNativeGenerationProjPath; } else if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.Plugins) { projPath = GamePluginGenerationProjPath; } else { projPath = Path.Combine(Settings.GetManagedDir(), rootFolderName, module.Name, module.Name + ".csproj"); } } break; } if (!string.IsNullOrWhiteSpace(sourceFilePath)) { sourceFilePath = Path.GetFullPath(sourceFilePath); } if (!string.IsNullOrWhiteSpace(projPath)) { projPath = Path.GetFullPath(projPath); } if (!string.IsNullOrWhiteSpace(slnPath)) { slnPath = Path.GetFullPath(slnPath); } if (string.IsNullOrWhiteSpace(sourceFilePath) || string.IsNullOrWhiteSpace(projPath) || string.IsNullOrWhiteSpace(slnPath)) { Log(ELogVerbosity.Error, "Unknown output location for '{0}' '{1}'", typeName, path); } else if (!ValidateOutputPath(sourceFilePath) || !ValidateOutputPath(projPath) || !ValidateOutputPath(slnPath)) { Log(ELogVerbosity.Error, "Invalid output path '{0}'", sourceFilePath); } else { //FMessage.Log(ELogVerbosity.Log, sourceFilePath + " | " + projPath + " | " + slnPath); try { if (UpdateSolutionAndProject(slnPath, projPath)) { if (!AddSourceFile(slnPath, projPath, sourceFilePath, code)) { Log(ELogVerbosity.Error, "Failed to add source file '{0}'", sourceFilePath); } } else { Log(ELogVerbosity.Error, "Failed to create sln/csproj '{0}' '{1}'", slnPath, projPath); } } catch (Exception e) { Log(ELogVerbosity.Error, "Exception when adding source file '{0}' {1}", sourceFilePath, e); } } }
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); }