// Move this somewhere else? Where would this be more appropriate? public static Type GetTypeFromProperty(UProperty prop) { if (prop == null) { return(null); } switch (prop.PropertyType) { case EPropertyType.Bool: return(typeof(bool)); case EPropertyType.Int8: return(typeof(sbyte)); case EPropertyType.Byte: return(typeof(byte)); case EPropertyType.Int16: return(typeof(short)); case EPropertyType.UInt16: return(typeof(ushort)); case EPropertyType.Int: return(typeof(int)); case EPropertyType.UInt32: return(typeof(uint)); case EPropertyType.Int64: return(typeof(long)); case EPropertyType.UInt64: return(typeof(ulong)); case EPropertyType.Float: return(typeof(float)); case EPropertyType.Double: return(typeof(double)); case EPropertyType.Enum: { UEnum unrealEnum = (prop as UEnumProperty).GetEnum(); if (unrealEnum == null) { return(null); } Type enumType; ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealEnum.GetPathName(), out enumType); return(enumType); } case EPropertyType.Str: return(typeof(string)); case EPropertyType.Name: return(typeof(FName)); case EPropertyType.Text: return(typeof(FText)); case EPropertyType.Interface: { UClass unrealClassInterface = (prop as UInterfaceProperty).InterfaceClass; if (unrealClassInterface == null) { return(null); } Type interfaceType; ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealClassInterface.GetPathName(), out interfaceType); return(interfaceType); } case EPropertyType.Struct: { UScriptStruct unrealStruct = (prop as UStructProperty).Struct; if (unrealStruct == null) { return(null); } Type structType; ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealStruct.GetPathName(), out structType); return(structType); } case EPropertyType.Class: case EPropertyType.Object: case EPropertyType.LazyObject: case EPropertyType.WeakObject: case EPropertyType.SoftClass: case EPropertyType.SoftObject: { UClass objectClass = (prop as UObjectPropertyBase).PropertyClass; switch (prop.PropertyType) { case EPropertyType.Class: objectClass = (prop as UClassProperty).MetaClass; break; case EPropertyType.SoftClass: objectClass = (prop as USoftClassProperty).MetaClass; break; } Type type = null; if (objectClass != null) { // Could use UClass.GetType but using AllKnownUnrealTypes for slightly more coverage // UClass.GetType(objectClass) ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(objectClass.GetPathName(), out type); } if (type == null) { //classType = typeof(UObject);// Fall back to UObject? Return null? return(null); } switch (prop.PropertyType) { case EPropertyType.Class: return(typeof(TSubclassOf <>).MakeGenericType(type)); case EPropertyType.LazyObject: return(typeof(TLazyObject <>).MakeGenericType(type)); case EPropertyType.WeakObject: return(typeof(TWeakObject <>).MakeGenericType(type)); case EPropertyType.SoftClass: return(typeof(TSoftClass <>).MakeGenericType(type)); case EPropertyType.SoftObject: return(typeof(TSoftObject <>).MakeGenericType(type)); case EPropertyType.Object: return(type); } return(type); } case EPropertyType.Delegate: case EPropertyType.MulticastDelegate: Type delegateType = null; UFunction signatureFunc = null; if (prop.PropertyType == EPropertyType.Delegate) { signatureFunc = (prop as UDelegateProperty).SignatureFunction; } else if (prop.PropertyType == EPropertyType.MulticastDelegate) { signatureFunc = (prop as UMulticastDelegateProperty).SignatureFunction; } if (signatureFunc != null) { if (ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(signatureFunc.GetPathName(), out delegateType)) { if (prop.PropertyType == EPropertyType.Delegate) { if (!delegateType.IsSameOrSubclassOfGeneric(typeof(FDelegate <>))) { delegateType = null; } } else if (prop.PropertyType == EPropertyType.MulticastDelegate) { if (!delegateType.IsSameOrSubclassOfGeneric(typeof(FMulticastDelegate <>))) { delegateType = null; } } } } return(delegateType); case EPropertyType.Array: { UArrayProperty arrayProp = prop as UArrayProperty; Type innerType = GetTypeFromProperty(arrayProp.Inner); if (innerType != null) { // Possibly handle IReadOnlyList? return(typeof(IList <>).MakeGenericType(innerType)); } return(null); } case EPropertyType.Set: { USetProperty setProp = prop as USetProperty; Type innerType = GetTypeFromProperty(setProp.ElementProp); if (innerType != null) { return(typeof(ISet <>).MakeGenericType(innerType)); } return(null); } case EPropertyType.Map: { UMapProperty mapProp = prop as UMapProperty; Type keyType = GetTypeFromProperty(mapProp.KeyProp); Type valueType = GetTypeFromProperty(mapProp.ValueProp); if (keyType != null && valueType != null) { // Possibly handle IReadOnlyDictionary? return(typeof(IDictionary <,>).MakeGenericType(keyType, valueType)); } return(null); } } return(null); }
internal static void GenerateCode(string[] args) { try { bool invalidArgs = false; if (args.Length > 0) { CodeGenerator codeGenerator = null; switch (args[0]) { /*case "blueprints": * AssetLoadMode loadMode = AssetLoadMode.Game; * bool clearAssetCache = false; * bool skipLevels = false; * if (args.Length > 1) * { * switch (args[1]) * { * case "game": * loadMode = CodeGenerator.AssetLoadMode.Game; * break; * case "gameplugins": * loadMode = CodeGenerator.AssetLoadMode.GamePlugins; * break; * case "engine": * loadMode = CodeGenerator.AssetLoadMode.Engine; * break; * case "engineplugins": * loadMode = CodeGenerator.AssetLoadMode.EnginePlugins; * break; * case "all": * loadMode = CodeGenerator.AssetLoadMode.All; * break; * } * } * if (args.Length > 2) * { * bool.TryParse(args[2], out clearAssetCache); * } * if (args.Length > 3) * { * bool.TryParse(args[3], out skipLevels); * } * codeGenerator = new CodeGenerator(); * codeGenerator.GenerateCodeForBlueprints(loadMode, clearAssetCache, skipLevels); * break;*/ case "game": codeGenerator = new CodeGenerator(); codeGenerator.GenerateCodeForModules(new UnrealModuleType[] { UnrealModuleType.Game }); break; case "gameplugins": codeGenerator = new CodeGenerator(); codeGenerator.GenerateCodeForModules(new UnrealModuleType[] { UnrealModuleType.GamePlugin }); break; case "modules": // Engine modules (whitelisted) codeGenerator = new CodeGenerator(); //codeGenerator.Settings.ExportMode = CodeGeneratorSettings.CodeExportMode.All; //codeGenerator.Settings.ExportAllFunctions = true; //codeGenerator.Settings.ExportAllProperties = true; string whitelistFile = Path.Combine(codeGenerator.Settings.GetManagedPluginSettingsDir(), "ModulesWhitelist.txt"); string blacklistFile = Path.Combine(codeGenerator.Settings.GetManagedPluginSettingsDir(), "ModulesBlacklist.txt"); if (File.Exists(whitelistFile)) { foreach (string line in File.ReadAllLines(whitelistFile)) { if (!string.IsNullOrEmpty(line)) { codeGenerator.ModulesNamesWhitelist.Add(line); } } } if (File.Exists(blacklistFile)) { foreach (string line in File.ReadAllLines(blacklistFile)) { if (!string.IsNullOrEmpty(line)) { codeGenerator.ModulesNamesBlacklist.Add(line); } } } codeGenerator.GenerateCodeForEngineModules(); break; case "all_modules": codeGenerator = new CodeGenerator(); codeGenerator.GenerateCodeForAllModules(); break; case "engine_modules": codeGenerator = new CodeGenerator(); codeGenerator.GenerateCodeForEngineModules(); break; case "module": if (args.Length > 1) { bool forceExport = false; if (args.Length > 2) { bool.TryParse(args[2], out forceExport); } codeGenerator = new CodeGenerator(); // Tests / using these for types for use in this lib //codeGenerator.Settings.CheckUObjectDestroyed = false; //codeGenerator.Settings.GenerateIsValidSafeguards = false; //codeGenerator.Settings.MergeEnumFiles = false; if (forceExport) { codeGenerator.Settings.ExportMode = CodeGeneratorSettings.CodeExportMode.All; codeGenerator.Settings.ExportAllFunctions = true; codeGenerator.Settings.ExportAllProperties = true; } codeGenerator.GenerateCodeForModule(args[1], true); } else { invalidArgs = true; } break; case "check_flags": { // This checks the flags for manually wrapped types Assembly[] assemblies = new Assembly[2]; assemblies[0] = Assembly.GetExecutingAssembly(); UClass engineClass = UClass.GetClass("/Script/Engine.Engine"); if (engineClass != null) { Type type = UClass.GetType(engineClass); if (type == null) { FMessage.Log(ELogVerbosity.Warning, "Failed to fine UEngine type"); } else { assemblies[1] = type.Assembly; } } else { FMessage.Log(ELogVerbosity.Warning, "Failed to fine UEngine class"); } foreach (Assembly assembly in assemblies) { if (assembly == null) { continue; } foreach (Type type in assembly.GetTypes()) { UMetaPathAttribute pathAttribute = type.GetCustomAttribute <UMetaPathAttribute>(false); if (pathAttribute != null && !string.IsNullOrEmpty(pathAttribute.Path)) { uint oldFlags = 0; if (type.IsSameOrSubclassOf(typeof(UObject))) { UClassAttribute classAttribute = type.GetCustomAttribute <UClassAttribute>(false); if (classAttribute != null) { oldFlags = (uint)classAttribute.Flags; } UClass unrealClass = UClass.GetClass(pathAttribute.Path); if (unrealClass != null) { if (oldFlags != (uint)unrealClass.ClassFlags) { FMessage.Log("old: 0x" + oldFlags.ToString("X8") + " new: 0x" + ((uint)unrealClass.ClassFlags).ToString("X8") + " path: " + unrealClass.GetPathName()); } } } else { UStructAttribute structAttribute = type.GetCustomAttribute <UStructAttribute>(false); if (structAttribute != null) { oldFlags = (uint)structAttribute.Flags; } UScriptStruct unrealStruct = UScriptStruct.GetStruct(pathAttribute.Path); if (unrealStruct != null) { if (oldFlags != (uint)unrealStruct.StructFlags) { FMessage.Log("old: 0x" + oldFlags.ToString("X8") + " new: 0x" + ((uint)unrealStruct.StructFlags).ToString("X8") + " path: " + unrealStruct.GetPathName()); } } } } } FMessage.Log("--------"); } } break; case "compile": CompileGeneratedCode(); break; default: invalidArgs = true; break; } } else { invalidArgs = true; } if (invalidArgs) { FMessage.Log(ELogVerbosity.Warning, "Invalid input. Provide one of the following: game, gameplugins, modules, module [ModuleName], compile"); } } catch (Exception e) { FMessage.Log(ELogVerbosity.Error, "Generate code failed. Error: \n" + e); } }