private bool CanExportStruct(UStruct unrealStruct) { // Ignore UProperty all classes if (unrealStruct.IsChildOf <UProperty>()) { return(false); } // Skip classes which are already defined in this project if (projectDefinedTypes.ContainsKey(unrealStruct.GetPathName())) { return(false); } if (Settings.ExportAllStructures) { return(true); } UClass unrealClass = unrealStruct as UClass; if (unrealClass != null) { if (unrealClass.HasAnyClassFlags(EClassFlags.Deprecated)) { return(false); } // EClassFlags.Transient - should we be checking this } return(true); }
private bool IsBlueprintVisibleStruct(UStruct unrealStruct) { // All of the available macro tags at: // Engine\Source\Runtime\CoreUObject\Public\UObject\ObjectBase.h // BlueprintType = can use inside a blueprint // Blueprintable = can use as a new blueprint // Blueprintable seems to override NotBlueprintType? // IsBlueprintBase, BlueprintSpawnableComponent // All UBlueprintFunctionLibrary classes are visible in blueprint even if marked as not visible if (unrealStruct.IsChildOf <UBlueprintFunctionLibrary>()) { return(true); } // Action classes are exposed to Blueprint as special nodes. We want the entire class. UClass unrealClass = unrealStruct as UClass; if (unrealClass != null && GetActionFactoryClass(unrealClass) != null) { return(true); } if (unrealStruct.GetBoolMetaDataHierarchical(MDClass.BlueprintSpawnableComponent))// && Struct.IsChildOf<UActorComponent>() { // Are all BlueprintSpawnableComponent classes visible even if marked not? TODO: Check this. return(true); } bool notBlueprintType = false; bool notBlueprintable = false; while (unrealStruct != null) { if (!notBlueprintType && unrealStruct.GetBoolMetaData(MDClass.BlueprintType)) { return(true); } if (!notBlueprintable && unrealStruct.GetBoolMetaData(MDClass.Blueprintable)) { return(true); } if (unrealStruct.GetBoolMetaData(MDClass.NotBlueprintType)) { notBlueprintType = true; } if (unrealStruct.GetBoolMetaData(MDClass.NotBlueprintable)) { notBlueprintable = true; } unrealStruct = unrealStruct.GetSuperStruct(); } return(false); }
public StructInfo(CodeGenerator codeGenerator, UStruct unrealStruct, bool isBlueprintType) { this.codeGenerator = codeGenerator; IsBlueprintType = isBlueprintType; Struct = unrealStruct; ScriptStruct = unrealStruct as UScriptStruct; Class = unrealStruct as UClass; IsClass = Class != null; IsStruct = ScriptStruct != null; IsInterface = unrealStruct.IsChildOf <UInterface>(); if (IsStruct) { // Start with a IsPlainOldData check for initial IsBlittable state. Is this enough? Or too verbose? // - May need to take into account non-zero constructor / EForceInit constructor if IsBlittable state // is used for construction. However since IsBlittable is only currently used to determine marshaling // using FromNative / ToNative on existing memory the ctor check shouldn't be required. // - The user can use StructDefault<T>.Value if they want a new native default instance of a struct // which will use the UScriptStruct.IsPODZeroInit check. IsBlittable = ScriptStruct.StructFlags.HasFlag(EStructFlags.IsPlainOldData); if (codeGenerator.Settings.AlwaysGenerateStructsAsClasses) { StructAsClass = true; } else if (codeGenerator.Settings.StructsAsClassesByPath.Contains(unrealStruct.GetPathName().ToLower())) { StructAsClass = true; } if (StructAsClass) { // Can't use blittable functions if the struct is being generated as a class IsBlittable = false; } } }
private string GetFunctionSignature(UnrealModuleInfo module, UFunction function, UStruct owner, string customFunctionName, string customModifiers, bool stripAdditionalText, bool isImplementationMethod, List <string> namespaces) { bool isInterface = owner != null && owner.IsChildOf <UInterface>(); bool isDelegate = function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate); bool isStatic = function.HasAnyFunctionFlags(EFunctionFlags.Static); bool isBlueprintType = owner != null && owner.IsA <UBlueprintGeneratedClass>(); StringBuilder modifiers = new StringBuilder(); if (!string.IsNullOrEmpty(customModifiers)) { modifiers.Append(customModifiers); } else if (isInterface) { // Don't provide any modifiers for interfaces if there isn't one already provided } else { UFunction originalFunction; // NOTE: "isImplementationMethod" is talking about "_Implementation" methods. // "isInterfaceImplementation" is talking about regular methods which are implementations for a interface. bool isInterfaceImplementation; UClass originalOwner = GetOriginalFunctionOwner(function, out originalFunction, out isInterfaceImplementation); // All interface functions in the chain need to be public bool isInterfaceFunc = originalOwner != owner && originalOwner.HasAnyClassFlags(EClassFlags.Interface); if (isImplementationMethod || (function.HasAnyFunctionFlags(EFunctionFlags.Protected) && !isInterfaceFunc && !isDelegate)) { modifiers.Append("protected"); } else { modifiers.Append("public"); } if (isDelegate) { modifiers.Append(" delegate"); } if (isStatic) { modifiers.Append(" static"); } if (!isDelegate && !isStatic) { if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent)) { UFunction superFunc = function.GetSuperFunction(); if (superFunc != null) { modifiers.Append(" override"); } else { // This have should been filtered out in CanExportFunction() Debug.Assert(originalOwner == owner || isInterfaceImplementation); // Explicit will have the _Implementation as virtual and the function declaration as // non-virtual (which is the same as C++) if (!Settings.UseExplicitImplementationMethods || isImplementationMethod) { modifiers.Append(" virtual"); } } } else { if (originalOwner != owner && !isInterfaceFunc) { // Add "new" if the parent class has a function with the same name but not BlueprintEvent. // (don't do this for interface functions as we are implementing the function not redefining it) modifiers.Append(" new"); } } } } string returnType = "void"; int numReturns = 0; StringBuilder parameters = new StringBuilder(); // index is the index into parameters string Dictionary <int, string> parameterDefaultsByIndex = new Dictionary <int, string>(); // Once this is true all parameters from that point should also have defaults bool hasDefaultParameters = false; // Blueprint can define ref/out parameters with default values, this can't be translated to code bool invalidDefaultParams = false; // Info so we can avoid param name conflicts Dictionary <UProperty, string> paramNames = GetParamNames(function); // Generic array parameters string[] arrayParamNames = function.GetCommaSeperatedMetaData("ArrayParam"); // Generic parameters depending on array type string[] arrayTypeDependentParamNames = function.GetCommaSeperatedMetaData("ArrayTypeDependentParams"); // AutoCreateRefTerm will force ref on given parameter names (comma seperated) string[] autoRefParamNames = function.GetCommaSeperatedMetaData("AutoCreateRefTerm"); // If this is a blueprint type try and getting the return value from the first out param (if there is only one out) UProperty blueprintReturnProperty = function.GetBlueprintReturnProperty(); bool firstParameter = true; foreach (KeyValuePair <UProperty, string> param in paramNames) { UProperty parameter = param.Key; string paramName = param.Value; string rawParamName = parameter.GetName(); if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm)) { continue; } if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || parameter == blueprintReturnProperty) { returnType = GetTypeName(parameter, namespaces); numReturns++; } else { if (firstParameter) { firstParameter = false; } else { parameters.Append(", "); } if (!parameter.HasAnyPropertyFlags(EPropertyFlags.ConstParm)) { if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm) || autoRefParamNames.Contains(rawParamName)) { parameters.Append("ref "); } else if (parameter.HasAnyPropertyFlags(EPropertyFlags.OutParm)) { parameters.Append("out "); } } string paramTypeName = GetTypeName(parameter, namespaces); if (arrayParamNames.Contains(rawParamName)) { int genericsIndex = paramTypeName.IndexOf('<'); if (genericsIndex >= 0) { paramTypeName = paramTypeName.Substring(0, genericsIndex) + "<T>"; } } else if (arrayTypeDependentParamNames.Contains(rawParamName)) { paramTypeName = "T"; } parameters.Append(paramTypeName + " " + paramName); if (!invalidDefaultParams) { string defaultValue = GetParamDefaultValue(function, parameter, paramTypeName, ref hasDefaultParameters, ref invalidDefaultParams); if (!string.IsNullOrEmpty(defaultValue) && !invalidDefaultParams) { if (isBlueprintType && (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm | EPropertyFlags.OutParm) || autoRefParamNames.Contains(rawParamName))) { invalidDefaultParams = true; } else { if (!hasDefaultParameters) { hasDefaultParameters = true; } parameterDefaultsByIndex[parameters.Length] = " = " + defaultValue; } } } } } if (numReturns > 1) { FMessage.Log(ELogVerbosity.Error, "More than 1 return on function '" + function.GetPathName() + "'"); } // Insert the default parameters if they aren't invalid if (!invalidDefaultParams) { int offset = 0; foreach (KeyValuePair <int, string> parameterDefault in parameterDefaultsByIndex) { parameters.Insert(parameterDefault.Key + offset, parameterDefault.Value); offset += parameterDefault.Value.Length; } } string functionName = GetFunctionName(function); string additionalStr = string.Empty; if (isDelegate) { functionName = GetTypeNameDelegate(function); additionalStr = ";"; } //if (isInterface) //{ // additionalStr = ";"; //} if (isImplementationMethod) { functionName += Settings.VarNames.ImplementationMethod; } if (!string.IsNullOrEmpty(customFunctionName)) { functionName = customFunctionName; } if (stripAdditionalText) { additionalStr = string.Empty; } string generics = string.Empty; if (arrayParamNames.Length > 0 || arrayTypeDependentParamNames.Length > 0) { generics = "<T>"; } if (modifiers.Length > 0) { modifiers.Append(' '); } return(string.Format("{0}{1} {2}{3}({4}){5}", modifiers, returnType, functionName, generics, parameters, additionalStr)); }