private void AppendDocComment(CSharpTextBuilder builder, UField field, bool isBlueprintType)
        {
            if (field == null || Settings.SkipDocumentation || string.IsNullOrEmpty(field.GetMetaData("Tooltip")))
            {
                return;
            }

            string tooltip = null;

            if (isBlueprintType)
            {
                // Blueprint metadata seems to have an internal representation which doesn't update the main metadata until reload.
                // TODO: Find the correct metadata for functions/variables for blueprint.
                // - Functions: Get function graph, call FBlueprintEditorUtils::GetGraphFunctionMetaData(graph), Metadata->ToolTip
                // - Variables: Call FBlueprintEditorUtils::GetBlueprintVariableMetaData?
                tooltip = field.GetToolTip();
            }
            else
            {
                tooltip = field.GetToolTip();
            }

            if (!string.IsNullOrEmpty(tooltip))
            {
                AppendDocComment(builder, tooltip, true);
            }
        }
        private void GenerateCodeForEnum(UnrealModuleInfo module, UEnum unrealEnum)
        {
            UnrealModuleType moduleAssetType;
            string           currentNamespace = GetModuleNamespace(unrealEnum, out moduleAssetType);
            List <string>    namespaces       = GetDefaultNamespaces();

            CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType);

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.AppendLine("namespace " + currentNamespace);
                builder.OpenBrace();
            }

            GenerateCodeForEnum(module, builder, unrealEnum);

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.CloseBrace();
            }

            builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces);

            OnCodeGenerated(module, moduleAssetType, GetTypeName(unrealEnum), unrealEnum.GetPathName(), builder);
        }
示例#3
0
        private void AppendSetter(CSharpTextBuilder builder, string propertyName, UField setter, List <string> namespaces)
        {
            builder.AppendLine("set");
            builder.OpenBrace();

            UFunction function = setter as UFunction;

            if (function != null)
            {
                AppendFunctionBody(builder, function, false, true, false, namespaces);
            }
            else
            {
                if (Settings.CheckObjectDestroyed)
                {
                    builder.AppendLine(Names.UObject_CheckDestroyed + "();");
                }
                if (Settings.GenerateIsValidSafeguards)
                {
                    builder.AppendLine("if (!" + propertyName + Settings.VarNames.IsValid + ")");
                    builder.OpenBrace();
                    builder.AppendLine(Names.NativeReflection_LogInvalidPropertyAccessed + "(\"" + setter.GetPathName() + "\");");
                    builder.AppendLine("return;");
                    builder.CloseBrace();
                }

                AppendPropertyToNative(builder, setter as UProperty, propertyName, Names.UObject_Address, "this", "value", false, namespaces);
            }

            builder.CloseBrace();
        }
        public string TestMe(bool rename, string str)
        {
            CSharpTextBuilder builder = new CSharpTextBuilder();

            AppendDocComment(builder, str, rename);
            return(builder.ToString());
        }
 private void AppendAttribute(CSharpTextBuilder builder, UField field, UnrealModuleInfo module, StructInfo structInfo)
 {
     AppendAttribute(builder, field, module);
     //if (field.IsA<UScriptStruct>() && structInfo.StructAsClass)
     //{
     //    builder.AppendLine("[" + Names.UStructAsClassAttributeShort + "]");
     //}
 }
        private void GenerateCodeForEnums(UnrealModuleInfo module, UEnum[] enums, bool combine)
        {
            if (enums.Length == 0)
            {
                return;
            }

            if (combine)
            {
                // Put all enums into a single file prefixed with the module name
                string enumsName = module.Name + "Enums";

                UnrealModuleType moduleAssetType;
                string           currentNamespace = GetModuleNamespace(enums[0], out moduleAssetType, false);
                List <string>    namespaces       = GetDefaultNamespaces();

                CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType);
                if (!string.IsNullOrEmpty(currentNamespace))
                {
                    builder.AppendLine("namespace " + currentNamespace);
                    builder.OpenBrace();
                }

                UEnum lastEnum = enums.Last();

                foreach (UEnum unrealEnum in enums)
                {
                    SlowTaskStep(unrealEnum);
                    GenerateCodeForEnum(module, builder, unrealEnum);

                    if (unrealEnum != lastEnum)
                    {
                        builder.AppendLine();
                    }
                }

                if (!string.IsNullOrEmpty(currentNamespace))
                {
                    builder.CloseBrace();
                }

                builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces);

                OnCodeGenerated(module, moduleAssetType, enumsName, null, builder);
            }
            else
            {
                foreach (UEnum unrealEnum in enums)
                {
                    SlowTaskStep(unrealEnum);
                    GenerateCodeForEnum(module, unrealEnum);
                }
            }
        }
        /// <summary>
        /// Sets the IsValid state for the given struct based on the state of all properties IsValid state
        /// (used when generating with safeguards enabled)
        /// </summary>
        private void AppendStructIsValid(CSharpTextBuilder builder, string structTypeName, StructInfo structInfo, UStruct parentStruct)
        {
            if (!Settings.GenerateIsValidSafeguards)
            {
                return;
            }

            List <UProperty> allProperties = new List <UProperty>();

            foreach (UProperty property in structInfo.GetProperties())
            {
                if (!structInfo.IsCollapsedProperty(property))
                {
                    allProperties.Add(property);
                }
            }

            if (parentStruct != null && (Settings.InlineBaseStruct || structInfo.StructAsClass))
            {
                UScriptStruct tempParentStruct = parentStruct as UScriptStruct;
                while (tempParentStruct != null)
                {
                    StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct);
                    if (tempParentStructInfo != null)
                    {
                        foreach (UProperty property in tempParentStructInfo.GetProperties())
                        {
                            if (!tempParentStructInfo.IsCollapsedProperty(property))
                            {
                                allProperties.Add(property);
                            }
                        }
                    }
                    tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct;
                }
            }

            StringBuilder isValidCheck = new StringBuilder();

            isValidCheck.Append(Settings.VarNames.ClassAddress + " != IntPtr.Zero");
            foreach (UProperty property in allProperties)
            {
                string propertyName = GetMemberName(property, structInfo.GetPropertyName(property));
                isValidCheck.Append(" && " + propertyName + Settings.VarNames.IsValid);
            }

            isValidCheck.Insert(0, structTypeName + Settings.VarNames.IsValid + " = ");
            isValidCheck.Append(";");
            builder.AppendLine(isValidCheck.ToString());

            builder.AppendLine(Names.NativeReflection_LogStructIsValid + "(\"" + structInfo.Struct.GetPathName() + "\", " +
                               structTypeName + Settings.VarNames.IsValid + ");");
        }
示例#8
0
        private void AppendPropertyFromNative(CSharpTextBuilder builder, UProperty property, string propertyName, string baseAddressName,
                                              string assignTo, string ownerName, bool isFunction, List <string> namespaces)
        {
            if (assignTo == null || assignTo.Trim() == "return")
            {
                assignTo = "return ";
            }
            else
            {
                assignTo = assignTo + " = ";
            }

            AppendPropertyToFromNative(builder, property, propertyName, baseAddressName, ownerName, null, assignTo, isFunction, false, namespaces);
        }
        private void AppendDocComment(CSharpTextBuilder builder, string summary, bool renameArgs)
        {
            if (Settings.SkipDocumentation || string.IsNullOrEmpty(summary))
            {
                return;
            }

            if (renameArgs)
            {
                AppendDocCommentAndRename(builder, summary);
            }
            else
            {
                AppendDocCommentSimple(builder, summary);
            }
        }
示例#10
0
        /// <summary>
        /// Sets function parameters which are tagged as "out" to default values to satisfy the compiler. This will insert
        /// a return statement if there is a return value.
        /// </summary>
        private void AppendFunctionBodyDefaultValues(CSharpTextBuilder builder, UFunction function, UProperty blueprintReturnProperty,
                                                     bool asElseStatement, bool insertReturn, Dictionary <UProperty, string> paramNames, List <string> namespaces)
        {
            bool   hasElse   = false;
            string returnStr = null;

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || parameter == blueprintReturnProperty)
                {
                    returnStr = "return " + GetPropertyMarshalerDefaultValue(parameter, namespaces) + ";";
                }
                else if (parameter.HasAnyPropertyFlags(EPropertyFlags.OutParm) &&
                         !parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm))
                {
                    if (asElseStatement && !hasElse)
                    {
                        hasElse = true;
                        builder.AppendLine("else");
                        builder.OpenBrace();
                    }
                    builder.AppendLine(paramName + " = " + GetPropertyMarshalerDefaultValue(parameter, namespaces) + ";");
                }
            }
            if (!string.IsNullOrEmpty(returnStr))
            {
                if (asElseStatement && !hasElse)
                {
                    hasElse = true;
                    builder.AppendLine("else");
                    builder.OpenBrace();
                }
                builder.AppendLine(returnStr);
            }
            else if (insertReturn)
            {
                builder.AppendLine("return;");
            }

            if (hasElse)
            {
                builder.CloseBrace();
            }
        }
示例#11
0
        private void AppendGetterSetterOffsets(CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder, string propertyName,
                                               UProperty property, List <string> namespaces, UFunction getter = null, UFunction setter = null)
        {
            if (getter != null)
            {
                AppendFunctionOffsets(builder, offsetsBuilder, getter, true, false, namespaces);
            }
            if (setter != null)
            {
                AppendFunctionOffsets(builder, offsetsBuilder, setter, false, true, namespaces);
            }

            if (property != null)
            {
                AppendPropertyOffset(builder, propertyName, property, false, namespaces);
                AppendPropertyOffsetNativeTypeLoader(offsetsBuilder, propertyName, property, null);
            }
        }
示例#12
0
        private void GenerateCodeForGlobalFunctions(UnrealModuleInfo module, UFunction[] globalFunctions)
        {
            if (globalFunctions.Length == 0)
            {
                return;
            }

            // Put all enums into a single file called ModulenameEnums
            string globalDelegatesName = module.Name + "GlobalDelegates";

            UnrealModuleType moduleAssetType;
            string           currentNamespace = GetModuleNamespace(globalFunctions[0], out moduleAssetType, false);
            List <string>    namespaces       = GetDefaultNamespaces();

            CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType);

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.AppendLine("namespace " + currentNamespace);
                builder.OpenBrace();
            }

            foreach (UFunction function in globalFunctions)
            {
                if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate))
                {
                    AppendDelegateSignature(module, builder, function, null, !function.HasAnyFunctionFlags(EFunctionFlags.Native), namespaces);
                    builder.AppendLine();
                }
            }

            // Remove any empty lines before adding the close brace
            builder.RemovePreviousEmptyLines();

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.CloseBrace();
            }

            builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces);

            OnCodeGenerated(module, moduleAssetType, globalDelegatesName, null, builder);
        }
        /// <summary>
        /// Sets all properties in the given struct to their default values within the struct constructor.
        /// (used when generating with safeguards enabled)
        /// </summary>
        private void AppendStructDefaultValuesOnInvalid(CSharpTextBuilder builder, StructInfo structInfo, UStruct parentStruct, List <string> namespaces)
        {
            if (!Settings.GenerateIsValidSafeguards)
            {
                return;
            }

            List <UProperty> allProperties = new List <UProperty>();

            foreach (UProperty property in structInfo.GetProperties())
            {
                if (!structInfo.IsCollapsedProperty(property))
                {
                    allProperties.Add(property);
                }
            }

            if (parentStruct != null && Settings.InlineBaseStruct)
            {
                UScriptStruct tempParentStruct = parentStruct as UScriptStruct;
                while (tempParentStruct != null)
                {
                    StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct);
                    if (tempParentStructInfo != null)
                    {
                        foreach (UProperty property in tempParentStructInfo.GetProperties())
                        {
                            if (!tempParentStructInfo.IsCollapsedProperty(property))
                            {
                                allProperties.Add(property);
                            }
                        }
                    }
                    tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct;
                }
            }

            foreach (UProperty property in allProperties)
            {
                string propertyName = GetMemberName(property, structInfo.GetPropertyName(property));
                builder.AppendLine(propertyName + " = " + GetPropertyMarshalerDefaultValue(property, namespaces) + ";");
            }
        }
示例#14
0
        /// <summary>
        /// Appends property info in the native type info loader function used to get the offsets / addresses of members
        /// </summary>
        private void AppendPropertyOffsetNativeTypeLoader(CSharpTextBuilder offsetsBuilder, string propertyName, UProperty property,
                                                          string functionName)
        {
            string ownerAddressName = null;

            if (!string.IsNullOrEmpty(functionName))
            {
                ownerAddressName = functionName + Settings.VarNames.FunctionAddress;
            }
            else
            {
                ownerAddressName = Settings.VarNames.ClassAddress;
            }

            if (RequiresNativePropertyField(property))
            {
                // XXXX_PropertyAddress (addres of the property)
                // NativeReflection.GetPropertyRef(ref XXXX_PropertyAddress, classAddress, "propertyName");
                offsetsBuilder.AppendLine(Names.NativeReflectionCached_GetPropertyRef + "(ref " +
                                          propertyName + Settings.VarNames.PropertyAddress + ", " + ownerAddressName + ", \"" + property.GetName() + "\");");
            }

            // XXXX_Offset (offset of the property)
            offsetsBuilder.AppendLine(propertyName + Settings.VarNames.MemberOffset + " = " +
                                      Names.NativeReflectionCached_GetPropertyOffset + "(" + ownerAddressName + ", \"" + property.GetName() + "\");");

            if (Settings.GenerateIsValidSafeguards)
            {
                string propertyClassName;
                if (!NativeReflection.TryGetPropertyClassName(property.PropertyType, out propertyClassName))
                {
                    propertyClassName = "UNKNOWN";
                }

                // XXXX_IsValid = NativeReflection.ValidatePropertyClass(classAddress, "propertyName", Classes.UXXXXProperty);
                offsetsBuilder.AppendLine(propertyName + Settings.VarNames.IsValid + " = " +
                                          Names.NativeReflectionCached_ValidatePropertyClass + "(" + ownerAddressName + ", \"" + property.GetName() + "\", " +
                                          Names.Classes + "." + propertyClassName + ");");
            }
        }
        private void GenerateCodeForEnum(UnrealModuleInfo module, CSharpTextBuilder builder, UEnum unrealEnum)
        {
            bool isBlueprintType = unrealEnum.IsA <UUserDefinedEnum>();

            AppendDocComment(builder, unrealEnum, isBlueprintType);
            AppendAttribute(builder, unrealEnum, module);

            // Set the underlying enum type if this enum is tagged as a BlueprintType
            string enumUnderlyingType = string.Empty;

            if (unrealEnum.HasMetaData(MDEnum.BlueprintType))
            {
                enumUnderlyingType = " : byte";
            }

            builder.AppendLine("public enum " + GetTypeName(unrealEnum) + enumUnderlyingType);
            builder.OpenBrace();

            // TODO: Blueprint value bitflags
            // According to issue UE-32816 "enum values are currently assumed to be flag indices and not actual flag mask values"
            List <EnumValueInfo> enumValues = GetEnumValues(unrealEnum, true);

            int lastEnumIndex = enumValues.Count;

            foreach (EnumValueInfo enumValue in enumValues)
            {
                AppendDocComment(builder, enumValue.DocCommentSummary);
                if (isBlueprintType)
                {
                    builder.AppendLine("[EnumValueName(\"" + enumValue.Name + "\")]");
                }
                builder.AppendLine(string.Format("{0}={1}{2}",
                                                 isBlueprintType ? enumValue.DisplayName : enumValue.Name,
                                                 enumValue.Value,
                                                 --lastEnumIndex > 0 ? "," : string.Empty));
            }

            builder.CloseBrace();
        }
示例#16
0
        private void AppendPropertyToFromNative(CSharpTextBuilder builder, UProperty property, string propertyName, string baseAddressName,
                                                string ownerName, string varName, string assignTo, bool isFunction, bool toNative, List <string> namespaces)
        {
            string marshalerName = GetMarshalerFromProperty(property, namespaces, isFunction);

            string propertyAddressVarName = propertyName + Settings.VarNames.PropertyAddress;
            string memberOffsetVarName    = propertyName + Settings.VarNames.MemberOffset;

            // Some marshalers require UProperty as a parameter
            bool requresProp = MarshalerRequiresNativePropertyField(property);

            string toFromNativeCall = null;

            if (toNative)
            {
                if (Settings.MinimalMarshalingParams && !requresProp)
                {
                    toFromNativeCall = ".ToNative(IntPtr.Add(" + baseAddressName + ", " + memberOffsetVarName + "), " + varName + ");";
                }
                else
                {
                    toFromNativeCall = ".ToNative(IntPtr.Add(" + baseAddressName + ", " + memberOffsetVarName + "), 0, " +
                                       (requresProp ? propertyAddressVarName + "." + Names.UObject_Address : "IntPtr.Zero") + ", " + varName + ");";
                }
            }
            else
            {
                if (Settings.MinimalMarshalingParams && !requresProp)
                {
                    toFromNativeCall = ".FromNative(IntPtr.Add(" + baseAddressName + ", " + memberOffsetVarName + "));";
                }
                else
                {
                    toFromNativeCall = ".FromNative(IntPtr.Add(" + baseAddressName + ", " + memberOffsetVarName + "), 0, " +
                                       (requresProp ? propertyAddressVarName + "." + Names.UObject_Address : "IntPtr.Zero") + ");";
                }
            }

            if (string.IsNullOrEmpty(marshalerName))
            {
                builder.AppendLine("throw new NotImplementedException(\"" + Names.EPropertyType + "." + property.PropertyType + "\");");
            }
            else
            {
                List <UProperty> collectionInners = null;
                switch (property.PropertyType)
                {
                case EPropertyType.Array:
                {
                    UArrayProperty arrayProperty = property as UArrayProperty;

                    collectionInners = new List <UProperty>();
                    collectionInners.Add(arrayProperty.Inner);
                }
                break;

                case EPropertyType.Set:
                {
                    USetProperty setProperty = property as USetProperty;

                    collectionInners = new List <UProperty>();
                    collectionInners.Add(setProperty.ElementProp);
                }
                break;

                case EPropertyType.Map:
                {
                    UMapProperty mapProperty = property as UMapProperty;

                    collectionInners = new List <UProperty>();
                    collectionInners.Add(mapProperty.KeyProp);
                    collectionInners.Add(mapProperty.ValueProp);
                }
                break;
                }
                bool   isCollection            = collectionInners != null;
                string collectionInstantiation = null;
                if (isCollection)
                {
                    string[] collectionInnerMarshalers = new string[collectionInners.Count];
                    for (int i = 0; i < collectionInners.Count; i++)
                    {
                        collectionInnerMarshalers[i] = Names.CachedMarshalingDelegates + "<" + GetTypeName(collectionInners[i], namespaces) +
                                                       ", " + GetMarshalerFromProperty(collectionInners[i], namespaces, isFunction) + ">";
                    }

                    collectionInstantiation = " = new " + marshalerName + "(1, " + propertyAddressVarName + ", " +
                                              string.Join(", ", collectionInnerMarshalers.Select(x => x + ".FromNative, " + x + ".ToNative")) + ");";
                }

                if (IsOwnerClassOrStructAsClass(property))
                {
                    if (property.IsFixedSizeArray)
                    {
                        string fixedSizeArrayVarName = propertyName + Settings.VarNames.FixedSizeArrayCached;

                        // We don't actually need a ToNative/FromNative call as the fixed array type will handle it
                        builder.AppendLine("if (" + fixedSizeArrayVarName + " == null)");
                        builder.OpenBrace();
                        builder.AppendLine(fixedSizeArrayVarName + " = new " + GetTypeName(property, namespaces) + "(IntPtr.Add(" +
                                           baseAddressName + ", " + memberOffsetVarName + "), " + propertyAddressVarName + ", " + ownerName + ");");
                        builder.CloseBrace();
                        builder.AppendLine(assignTo + fixedSizeArrayVarName + ";");
                    }
                    if (property.PropertyType == EPropertyType.Struct &&
                        IsClassOrStructAsClass((property as UStructProperty).Struct))
                    {
                        string cachedStructAsClassVarName = propertyName + Settings.VarNames.StructAsClassCached;

                        builder.AppendLine("if (" + cachedStructAsClassVarName + " == null)");
                        builder.OpenBrace();
                        builder.AppendLine(cachedStructAsClassVarName + " = new " + GetTypeName(property, namespaces) + "();");
                        builder.AppendLine(cachedStructAsClassVarName + "." + Names.StructAsClass_Initialize + "(IntPtr.Add(" +
                                           Names.UObject_Address + ", " + memberOffsetVarName + "));");
                        builder.CloseBrace();

                        if (toNative)
                        {
                            builder.AppendLine(cachedStructAsClassVarName + "." + Names.StructAsClass_CopyFrom + "(" + varName + ");");
                        }
                        else
                        {
                            builder.AppendLine(assignTo + cachedStructAsClassVarName + ";");
                        }
                    }
                    else if (isCollection)
                    {
                        string collectionVarName = propertyName + Settings.VarNames.CollectionMarshalerCached;

                        builder.AppendLine("if (" + collectionVarName + " == null)");
                        builder.OpenBrace();
                        builder.AppendLine(collectionVarName + collectionInstantiation);
                        builder.CloseBrace();
                        builder.AppendLine(assignTo + collectionVarName + toFromNativeCall);
                    }
                    else if (IsDelegateProperty(property))
                    {
                        string delegateVarName = propertyName + Settings.VarNames.DelegateCached;

                        builder.AppendLine("if (" + delegateVarName + " == null)");
                        builder.OpenBrace();
                        builder.AppendLine(delegateVarName + " = new " + GetTypeName(property, namespaces) + "();");
                        builder.AppendLine(delegateVarName + "." + Names.FDelegateBase_SetAddress + "(IntPtr.Add(" +
                                           Names.UObject_Address + ", " + memberOffsetVarName + "));");
                        builder.CloseBrace();
                        builder.AppendLine(assignTo + delegateVarName + ";");
                    }
                    else if (property.PropertyType == EPropertyType.Text)
                    {
                        string textVarName = propertyName + Settings.VarNames.FTextCached;

                        builder.AppendLine("if (" + textVarName + " == null)");
                        builder.OpenBrace();
                        builder.AppendLine(textVarName + " = new " + GetTypeName(property, namespaces) + "(IntPtr.Add(" +
                                           Names.UObject_Address + ", " + memberOffsetVarName + "), false);");
                        builder.CloseBrace();
                        if (toNative)
                        {
                            builder.AppendLine(textVarName + ".CopyFrom(value);");
                        }
                        else
                        {
                            builder.AppendLine("return " + textVarName + ";");
                        }
                    }
                    else
                    {
                        builder.AppendLine(assignTo + marshalerName + toFromNativeCall);
                    }
                }
                else
                {
                    if (isCollection)
                    {
                        string collectionVarName = propertyName + Settings.VarNames.CollectionMarshaler;
                        if (!property.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm) ||
                            property.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || toNative)
                        {
                            builder.AppendLine(marshalerName + " " + collectionVarName + collectionInstantiation);
                        }
                        builder.AppendLine(assignTo + collectionVarName + toFromNativeCall);
                    }
                    else
                    {
                        builder.AppendLine(assignTo + marshalerName + toFromNativeCall);
                    }
                }
            }
        }
示例#17
0
 private void AppendPropertyToNative(CSharpTextBuilder builder, UProperty property, string propertyName, string baseAddressName,
                                     string ownerName, string varName, bool isFunction, List <string> namespaces)
 {
     AppendPropertyToFromNative(builder, property, propertyName, baseAddressName, ownerName, varName, null, isFunction, true, namespaces);
 }
示例#18
0
        private void AppendDelegateSignature(UnrealModuleInfo module, CSharpTextBuilder builder, UFunction function, UStruct owner,
                                             bool isBlueprintType, List <string> namespaces)
        {
            AppendDocComment(builder, function, isBlueprintType);
            AppendAttribute(builder, function, module);

            string delegateBaseTypeName = function.HasAnyFunctionFlags(EFunctionFlags.MulticastDelegate) ?
                                          Names.FMulticastDelegate : Names.FDelegate;

            string delegateTypeName = GetTypeNameDelegate(function);

            builder.AppendLine("public class " + delegateTypeName + " : " + delegateBaseTypeName + "<" + delegateTypeName + "." +
                               Settings.VarNames.DelegateSignature + ">");
            builder.OpenBrace();

            builder.AppendLine(GetFunctionSignature(
                                   module, function, owner, Settings.VarNames.DelegateSignature, "public delegate", false, false, namespaces));
            builder.AppendLine();
            builder.AppendLine("public override " + Settings.VarNames.DelegateSignature + " " + Names.FDelegateBase_GetInvoker + "()");
            builder.OpenBrace();
            builder.AppendLine("return " + Settings.VarNames.DelegateInvoker + ";");
            builder.CloseBrace();
            builder.AppendLine();

            string functionName = GetFunctionName(function);
            Dictionary <UProperty, string> paramNames = GetParamNames(function);

            // Offsets
            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("static bool " + functionName + Settings.VarNames.IsValid + ";");
            }
            builder.AppendLine("static IntPtr " + functionName + Settings.VarNames.FunctionAddress + ";");
            builder.AppendLine("static int " + functionName + Settings.VarNames.ParamsSize + ";");
            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffset(builder, functionName + "_" + paramName, parameter, true, namespaces);
            }

            // Add the native type info initializer to get the offsets
            builder.AppendLine("static void " + Settings.VarNames.LoadNativeType + "()");
            builder.OpenBrace();
            builder.AppendLine(functionName + Settings.VarNames.FunctionAddress + " = " + Names.NativeReflection_GetFunction +
                               "(\"" + function.GetPathName() + "\");");
            builder.AppendLine(functionName + Settings.VarNames.ParamsSize + " = " + Names.NativeReflection_GetFunctionParamsSize +
                               "(" + functionName + Settings.VarNames.FunctionAddress + ");");
            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffsetNativeTypeLoader(builder, functionName + "_" + paramName, parameter, functionName);
            }
            if (Settings.GenerateIsValidSafeguards)
            {
                // XXXX_IsValid = param1_IsValid && param2_IsValid && param3_IsValid;
                string paramsValid = string.Join(" && ", paramNames.Values.Select(x => functionName + "_" + x + Settings.VarNames.IsValid));
                if (!string.IsNullOrEmpty(paramsValid))
                {
                    paramsValid = " && " + paramsValid;
                }
                builder.AppendLine(functionName + Settings.VarNames.IsValid + " = " +
                                   functionName + Settings.VarNames.FunctionAddress + " != IntPtr.Zero" + paramsValid + ";");
                builder.AppendLine(Names.NativeReflection_LogFunctionIsValid + "(\"" + function.GetPathName() + "\", " +
                                   functionName + Settings.VarNames.IsValid + ");");
            }
            builder.CloseBrace();
            builder.AppendLine();

            builder.AppendLine(GetFunctionSignature(
                                   module, function, owner, Settings.VarNames.DelegateInvoker, "private", true, false, namespaces));
            builder.OpenBrace();
            AppendFunctionBody(builder, function, false, false, false, namespaces);
            builder.CloseBrace();

            builder.CloseBrace();
        }
示例#19
0
        private void AppendFunctionOffsets(CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder, UFunction function,
                                           bool isGetter, bool isSetter, List <string> namespaces)
        {
            bool   isInterface = false;
            UClass owner       = function.GetOwnerClass();

            if (owner != null && owner.ClassFlags.HasFlag(EClassFlags.Interface))
            {
                isInterface = true;
            }

            string functionName = GetFunctionName(function);

            if (isGetter)
            {
                functionName += "_getter";
            }
            else if (isSetter)
            {
                functionName += "_setter";
            }
            Dictionary <UProperty, string> paramNames = GetParamNames(function);

            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("static bool " + functionName + Settings.VarNames.IsValid + ";");
            }
            if ((function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent) && function.GetSuperFunction() == null) || isInterface)
            {
                builder.AppendLine("IntPtr " + functionName + Settings.VarNames.InstanceFunctionAddress + ";");
            }
            builder.AppendLine("static IntPtr " + functionName + Settings.VarNames.FunctionAddress + ";");
            builder.AppendLine("static int " + functionName + Settings.VarNames.ParamsSize + ";");

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffset(builder, functionName + "_" + paramName, parameter, true, namespaces);
            }

            offsetsBuilder.AppendLine(functionName + Settings.VarNames.FunctionAddress + " = " + Names.NativeReflectionCached_GetFunction +
                                      "(" + Settings.VarNames.ClassAddress + ", \"" + function.GetName() + "\");");
            offsetsBuilder.AppendLine(functionName + Settings.VarNames.ParamsSize + " = " + Names.NativeReflection_GetFunctionParamsSize +
                                      "(" + functionName + Settings.VarNames.FunctionAddress + ");");

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffsetNativeTypeLoader(offsetsBuilder, functionName + "_" + paramName, parameter, functionName);
            }
            if (Settings.GenerateIsValidSafeguards)
            {
                // XXXX_IsValid = param1_IsValid && param2_IsValid && param3_IsValid;
                string paramsValid = string.Join(" && ", paramNames.Values.Select(x => functionName + "_" + x + Settings.VarNames.IsValid));
                if (!string.IsNullOrEmpty(paramsValid))
                {
                    paramsValid = " && " + paramsValid;
                }
                offsetsBuilder.AppendLine(functionName + Settings.VarNames.IsValid + " = " +
                                          functionName + Settings.VarNames.FunctionAddress + " != IntPtr.Zero" + paramsValid + ";");
                offsetsBuilder.AppendLine(Names.NativeReflection_LogFunctionIsValid + "(\"" + function.GetPathName() + "\", " +
                                          functionName + Settings.VarNames.IsValid + ");");
            }
        }
示例#20
0
        private void AppendFunctionBody(CSharpTextBuilder builder, UFunction function, bool isGetter, bool isSetter,
                                        bool perInstanceFunctionAddress, List <string> namespaces)
        {
            string    functionName            = GetFunctionName(function);
            UProperty blueprintReturnProperty = function.GetBlueprintReturnProperty();

            bool   isDelegate     = function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate);
            bool   isStatic       = function.HasAnyFunctionFlags(EFunctionFlags.Static);
            string targetAddress  = isStatic ? Settings.VarNames.ClassAddress : Names.UObject_Address;
            string ownerName      = isDelegate || isStatic ? "null" : "this";
            string invokeFunction = isStatic ? Names.NativeReflection_InvokeStaticFunction : Names.NativeReflection_InvokeFunction;

            if (isGetter)
            {
                functionName += "_getter";
            }
            else if (isSetter)
            {
                functionName += "_setter";
            }

            string functionAddressName = functionName + (perInstanceFunctionAddress ? Settings.VarNames.InstanceFunctionAddress :
                                                         Settings.VarNames.FunctionAddress);

            Dictionary <UProperty, string> paramNames = GetParamNames(function);

            if (isSetter)
            {
                System.Diagnostics.Debug.Assert(paramNames.Count == 1);
            }

            if (Settings.CheckObjectDestroyed && !isStatic &&
                !function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate))
            {
                builder.AppendLine(Names.UObject_CheckDestroyed + "();");
            }
            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("if (!" + functionName + Settings.VarNames.IsValid + ")");
                builder.OpenBrace();
                builder.AppendLine(Names.NativeReflection_LogInvalidFunctionAccessed + "(\"" + function.GetPathName() + "\");");
                AppendFunctionBodyDefaultValues(builder, function, blueprintReturnProperty, false, true, paramNames, namespaces);
                builder.CloseBrace();
            }

            if (perInstanceFunctionAddress)
            {
                builder.AppendLine("if (" + functionAddressName + " == IntPtr.Zero)");
                builder.OpenBrace();
                builder.AppendLine(functionAddressName + " = " + Names.NativeReflection_GetFunctionFromInstance + "(" +
                                   targetAddress + ", \"" + function.GetName() + "\");");
                builder.CloseBrace();
            }

            if (isDelegate)
            {
                builder.AppendLine("if (IsBound)");
                builder.OpenBrace();
            }

            builder.AppendLine("unsafe");
            builder.OpenBrace();
            builder.AppendLine("byte* " + Settings.VarNames.ParamsBufferAllocation + " = stackalloc byte[" +
                               functionName + Settings.VarNames.ParamsSize + "];");
            builder.AppendLine("IntPtr " + Settings.VarNames.ParamsBuffer + " = new IntPtr(" + Settings.VarNames.ParamsBufferAllocation + ");");

            if (Settings.LazyFunctionParamInitDestroy)
            {
                builder.AppendLine(Names.NativeReflection_InvokeFunction_InitAll + "(" + functionAddressName + ", " +
                                   Settings.VarNames.ParamsBuffer + ");");
            }
            else if (Settings.MemzeroStackalloc || Settings.MemzeroStackallocOnlyIfOut)
            {
                bool requiresMemzero = Settings.MemzeroStackalloc;

                if (Settings.MemzeroStackallocOnlyIfOut)
                {
                    foreach (KeyValuePair <UProperty, string> param in paramNames)
                    {
                        UProperty parameter = param.Key;
                        string    paramName = param.Value;

                        // Memzero only if there is a return value or a (non ref) out param which doesn't have a zero constructor.
                        // (if the param can't be zero initialized it will be initialized with a call to InitializeValue anyway)
                        if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm | EPropertyFlags.OutParm) &&
                            !parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm) &&
                            !parameter.HasAnyPropertyFlags(EPropertyFlags.ZeroConstructor))
                        {
                            requiresMemzero = true;
                            break;
                        }
                    }
                }

                if (requiresMemzero)
                {
                    builder.AppendLine(Names.FMemory_Memzero + "(" + Settings.VarNames.ParamsBuffer + ", " +
                                       functionName + Settings.VarNames.ParamsSize + ");");
                }
            }

            bool hasRefOrOutParam = false;
            bool hasReturn        = false;
            bool hasParamWithDtor = false;

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || parameter == blueprintReturnProperty)
                {
                    hasReturn = true;
                    continue;
                }
                else if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm | EPropertyFlags.OutParm))
                {
                    hasRefOrOutParam = true;
                }

                if (!Settings.LazyFunctionParamInitDestroy)
                {
                    if (!parameter.HasAnyPropertyFlags(EPropertyFlags.ZeroConstructor))
                    {
                        // Initialize values which don't have a zero constructor (this is required even though we will follow this up by a call
                        // to ToNative as some structs have vtables e.g. FSlateBrush has its dtor in the vtable)
                        builder.AppendLine(Names.NativeReflection_InitializeValue_InContainer + "(" +
                                           functionName + "_" + paramName + Settings.VarNames.PropertyAddress + "." + Names.UFieldAddress_Address +
                                           ", " + Settings.VarNames.ParamsBuffer + ");");
                    }
                    if (!parameter.HasAnyPropertyFlags(EPropertyFlags.NoDestructor))
                    {
                        // Parameter requires destruction
                        hasParamWithDtor = true;
                    }
                }

                if (parameter.HasAnyPropertyFlags(EPropertyFlags.Parm) &&
                    (!parameter.HasAnyPropertyFlags(EPropertyFlags.OutParm) || parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm)))
                {
                    AppendPropertyToNative(builder, parameter, functionName + "_" + paramName, Settings.VarNames.ParamsBuffer,
                                           ownerName, isSetter ? "value" : paramName, true, namespaces);
                }
            }

            builder.AppendLine();
            if (isDelegate)
            {
                builder.AppendLine(Names.FDelegateBase_ProcessDelegate + "(" + Settings.VarNames.ParamsBuffer + ");");
            }
            else
            {
                builder.AppendLine(invokeFunction + "(" + targetAddress + ", " + functionAddressName + ", " +
                                   Settings.VarNames.ParamsBuffer + ", " + functionName + Settings.VarNames.ParamsSize + ");");
            }

            if (hasReturn || hasRefOrOutParam || hasParamWithDtor)
            {
                builder.AppendLine();

                foreach (KeyValuePair <UProperty, string> param in paramNames)
                {
                    UProperty parameter = param.Key;
                    string    paramName = param.Value;

                    // If this is function is collapsed into a setter property then we can skip the FromNative calls as there shouldn't be
                    // anything we need to extract back out (if there is, then using a setter instead of a function is incorrect in that case)
                    if (!isSetter)
                    {
                        if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || parameter == blueprintReturnProperty)
                        {
                            AppendPropertyFromNative(builder, parameter, functionName + "_" + paramName, Settings.VarNames.ParamsBuffer,
                                                     GetTypeName(parameter, namespaces) + " " + Settings.VarNames.ReturnResult, ownerName, true, namespaces);
                        }
                        else if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm | EPropertyFlags.OutParm))
                        {
                            AppendPropertyFromNative(builder, parameter, functionName + "_" + paramName, Settings.VarNames.ParamsBuffer,
                                                     paramName, ownerName, true, namespaces);
                        }
                    }

                    if (!Settings.LazyFunctionParamInitDestroy && !parameter.HasAnyPropertyFlags(EPropertyFlags.NoDestructor))
                    {
                        // Parameter requires destruction
                        builder.AppendLine(Names.NativeReflection_DestroyValue_InContainer + "(" +
                                           functionName + "_" + paramName + Settings.VarNames.PropertyAddress + "." + Names.UFieldAddress_Address +
                                           ", " + Settings.VarNames.ParamsBuffer + ");");
                    }
                }
            }

            if (Settings.LazyFunctionParamInitDestroy)
            {
                builder.AppendLine(Names.NativeReflection_InvokeFunction_DestroyAll + "(" + functionAddressName + ", " +
                                   Settings.VarNames.ParamsBuffer + ");");
            }

            if (hasReturn)
            {
                builder.AppendLine("return " + Settings.VarNames.ReturnResult + ";");
            }

            builder.CloseBrace();

            if (isDelegate)
            {
                builder.CloseBrace();
                AppendFunctionBodyDefaultValues(builder, function, blueprintReturnProperty, true, false, paramNames, namespaces);
            }
        }
示例#21
0
 private void OnCodeGenerated(UnrealModuleInfo module, UnrealModuleType moduleAssetType, string typeName, string path, CSharpTextBuilder code)
 {
     if (codeManager != null)
     {
         codeManager.OnCodeGenerated(module, moduleAssetType, typeName, path, code.ToString());
     }
 }
示例#22
0
        private void GenerateCodeForProperty(UnrealModuleInfo module, CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder,
                                             CollapsedMember collapsedMember, bool isBlueprintType, List <string> namespaces)
        {
            StringBuilder modifiers = new StringBuilder();

            if (collapsedMember.BackingProperty != null)
            {
                UProperty property = collapsedMember.BackingProperty;

                if (property.HasAnyPropertyFlags(EPropertyFlags.DisableEditOnInstance) && !property.GetBoolMetaData(MDProp.AllowPrivateAccess))
                {
                    modifiers.Append("private");
                }
                else if (property.HasAnyPropertyFlags(EPropertyFlags.NativeAccessSpecifierProtected | EPropertyFlags.Protected))
                {
                    modifiers.Append("protected");
                }
                else
                {
                    modifiers.Append("public");
                }
            }
            else
            {
                UFunction function = collapsedMember.Getter != null ? collapsedMember.Getter : collapsedMember.Setter;

                if (function.HasAnyFunctionFlags(EFunctionFlags.Protected))
                {
                    modifiers.Append("protected");
                }
                else
                {
                    modifiers.Append("public");
                }
            }

            if (modifiers.Length > 0)
            {
                modifiers.Append(" ");
            }

            // Note: Potential issues with different categories/docs/attribute on BackingProperty/Getter/Setter

            UField field = collapsedMember.BackingProperty;

            if (field == null)
            {
                field = collapsedMember.Getter;
                if (field == null)
                {
                    field = collapsedMember.Setter;
                }
            }

            // Use either the backing property or the getter function for the documentation
            UField fieldForDocumentation = collapsedMember.BackingProperty != null ?
                                           (UField)collapsedMember.BackingProperty : collapsedMember.Getter;

            string name         = collapsedMember.ResolvedName != null ? collapsedMember.ResolvedName : collapsedMember.Name;
            string propertyName = GetName(field, name, Settings.MemberCasing, false, true);

            AppendGetterSetterOffsets(builder, offsetsBuilder, propertyName,
                                      collapsedMember.Getter == null || collapsedMember.Setter == null ? collapsedMember.BackingProperty : null, namespaces,
                                      collapsedMember.Getter, collapsedMember.Setter);

            AppendDocComment(builder, fieldForDocumentation, isBlueprintType);
            AppendAttribute(builder, field, module, true);
            builder.AppendLine(modifiers + GetTypeName(collapsedMember.Property, namespaces) + " " + propertyName);
            builder.OpenBrace();

            if (collapsedMember.Getter != null)
            {
                AppendGetter(builder, propertyName, collapsedMember.Getter, namespaces);
            }
            else if (collapsedMember.BackingProperty != null)
            {
                AppendGetter(builder, propertyName, collapsedMember.BackingProperty, namespaces);
            }

            if (collapsedMember.Setter != null)
            {
                AppendSetter(builder, propertyName, collapsedMember.Setter, namespaces);
            }
            else if (collapsedMember.BackingProperty != null)
            {
                AppendSetter(builder, propertyName, collapsedMember.BackingProperty, namespaces);
            }

            builder.CloseBrace();
            builder.AppendLine();
        }
示例#23
0
        private void AppendAttribute(CSharpTextBuilder builder, UField field, UnrealModuleInfo module, bool isCollapsedMember)
        {
            UnrealModuleType moduleType;
            UnrealModuleType moduleAssetType;
            string           moduleName = GetModuleName(field, out moduleType, out moduleAssetType);

            if (string.IsNullOrEmpty(moduleName))
            {
                moduleName = module.Name;
            }

            List <string> attributes = new List <string>();

            // TODO: Combine all of this into EPropertyType (add some TypeCode into UField?)
            bool          isInterface  = false;
            UEnum         unrealEnum   = field as UEnum;
            UClass        unrealClass  = field as UClass;
            UScriptStruct unrealStruct = field as UScriptStruct;

            UFunction unrealFunction = field as UFunction;

            if (unrealFunction != null)
            {
                if (unrealFunction.HasAnyFunctionFlags(EFunctionFlags.Delegate))
                {
                    attributes.Add("UDelegate");
                }
                else
                {
                    if (isCollapsedMember)
                    {
                        // The Flags here might not contain too useful information if there is both a get/set function.
                        // Maybe include a second flags var?
                        attributes.Add("UFunctionAsProp(Flags=0x" + ((uint)unrealFunction.FunctionFlags).ToString("X8") + ")");
                    }
                    else
                    {
                        attributes.Add("UFunction(Flags=0x" + ((uint)unrealFunction.FunctionFlags).ToString("X8") + ")");
                    }
                }
            }

            UProperty unrealProperty = field as UProperty;

            if (unrealProperty != null)
            {
                attributes.Add("UProperty(Flags=(PropFlags)0x" + ((ulong)unrealProperty.PropertyFlags).ToString("X16") + ")");
            }

            if (unrealStruct != null)
            {
                attributes.Add("UStruct(Flags=0x" + ((uint)unrealStruct.StructFlags).ToString("X8") + ")");
            }
            else if (unrealClass != null)
            {
                // Abstract isn't really required but might help with code browsing to know what is abstract
                // and what isn't. Therefore put it at the start of the attributes list.
                if (unrealClass.HasAnyClassFlags(EClassFlags.Abstract))
                {
                    attributes.Add("Abstract");
                }

                isInterface = unrealClass.IsChildOf <UInterface>();
                if (isInterface)
                {
                    attributes.Add("UInterface(Flags=0x" + ((uint)unrealClass.ClassFlags).ToString("X8") + ")");
                }
                else
                {
                    // Should we skip "inherit" config name?
                    string configNameStr = string.Empty;
                    if (unrealClass.ClassConfigName != FName.None &&
                        !unrealClass.ClassConfigName.ToString().Equals("inherit", StringComparison.InvariantCultureIgnoreCase))
                    {
                        configNameStr = ", Config=\"" + unrealClass.ClassConfigName + "\"";
                    }

                    attributes.Add("UClass(Flags=(ClassFlags)0x" + ((uint)unrealClass.ClassFlags).ToString("X8") +
                                   configNameStr + ")");
                }
            }

            if (unrealEnum != null)
            {
                attributes.Add("UEnum");
            }

            if (unrealEnum != null || unrealClass != null || unrealStruct != null)
            {
                bool blueprintType = false;
                bool blueprintable = false;
                if (unrealEnum != null)
                {
                    blueprintType = field.GetBoolMetaData(MDClass.BlueprintType);
                }
                else
                {
                    GetBlueprintability(field as UStruct, out blueprintType, out blueprintable);
                }
                if (blueprintType)
                {
                    attributes.Add(UMeta.GetKey(MDClass.BlueprintType));
                }
                if (unrealClass != null && blueprintable)
                {
                    attributes.Add(UMeta.GetKey(MDClass.Blueprintable));
                }

                if (isInterface)
                {
                }

                attributes.Add("UMetaPath(\"" + field.GetPathName() + "\", \"" + moduleName +
                               "\", UnrealModuleType." + GetUnrealModuleTypeString(moduleType, moduleAssetType) +
                               (isInterface ? ", InterfaceImpl=typeof(" + GetTypeName(unrealClass, null) + "Impl" + ")" : string.Empty) + ")");
            }
            else
            {
                attributes.Add("UMetaPath(\"" + field.GetPathName() + "\")");
            }

            if (attributes.Count > 0)
            {
                builder.AppendLine("[" + string.Join(", ", attributes) + "]");
            }
        }
        private void AppendAttribute(CSharpTextBuilder builder, UField field, UnrealModuleInfo module, bool isCollapsedMember)
        {
            UnrealModuleType moduleType;
            UnrealModuleType moduleAssetType;
            string           moduleName = GetModuleName(field, out moduleType, out moduleAssetType);

            if (string.IsNullOrEmpty(moduleName))
            {
                moduleName = module.Name;
            }

            List <string> attributes = new List <string>();

            // TODO: Combine all of this into EPropertyType (add some TypeCode into UField?)
            bool          isInterface  = false;
            UEnum         unrealEnum   = field as UEnum;
            UClass        unrealClass  = field as UClass;
            UScriptStruct unrealStruct = field as UScriptStruct;

            UFunction unrealFunction = field as UFunction;

            if (unrealFunction != null)
            {
                if (unrealFunction.HasAnyFunctionFlags(EFunctionFlags.Delegate))
                {
                    attributes.Add("UDelegate");
                }
                else
                {
                    string additionalFunctionInfo = string.Empty;

                    // TODO: Only get the script name for virtual functions / interface functions as we currently only need
                    //       this for finding the base function for hooking things up to the native base types.
                    string scriptFunctionName;
                    if (unrealFunction.GetScriptName(out scriptFunctionName))
                    {
                        additionalFunctionInfo += ", OriginalName=\"" + unrealFunction.GetName() + "\"";
                    }

                    if (isCollapsedMember)
                    {
                        // The Flags here might not contain too useful information if there is both a get/set function.
                        // Maybe include a second flags var?
                        attributes.Add("UFunctionAsProp(Flags=0x" + ((uint)unrealFunction.FunctionFlags).ToString("X8") + additionalFunctionInfo + ")");
                    }
                    else
                    {
                        attributes.Add("UFunction(Flags=0x" + ((uint)unrealFunction.FunctionFlags).ToString("X8") + additionalFunctionInfo + ")");
                    }
                }
            }

            UProperty unrealProperty = field as UProperty;

            if (unrealProperty != null)
            {
                attributes.Add("UProperty(Flags=(PropFlags)0x" + ((ulong)unrealProperty.PropertyFlags).ToString("X16") + ")");
            }

            if (unrealStruct != null)
            {
                attributes.Add("UStruct(Flags=0x" + ((uint)unrealStruct.StructFlags).ToString("X8") + ")");
            }
            else if (unrealClass != null)
            {
                // Abstract isn't really required but might help with code browsing to know what is abstract
                // and what isn't. Therefore put it at the start of the attributes list.
                if (unrealClass.HasAnyClassFlags(EClassFlags.Abstract))
                {
                    attributes.Add("Abstract");
                }

                isInterface = unrealClass.IsChildOf <UInterface>();
                if (isInterface)
                {
                    attributes.Add("UInterface(Flags=0x" + ((uint)unrealClass.ClassFlags).ToString("X8") + ")");
                }
                else
                {
                    attributes.Add("UClass(Flags=(ClassFlags)0x" + ((uint)unrealClass.ClassFlags).ToString("X8") + ")");
                }
            }

            if (unrealEnum != null)
            {
                attributes.Add("UEnum");
            }

            if (unrealEnum != null || unrealClass != null || unrealStruct != null)
            {
                bool blueprintType = false;
                bool blueprintable = false;
                if (unrealEnum != null)
                {
                    blueprintType = field.GetBoolMetaData(MDClass.BlueprintType);
                }
                else
                {
                    GetBlueprintability(field as UStruct, out blueprintType, out blueprintable);
                }
                if (blueprintType)
                {
                    attributes.Add(UMeta.GetKey(MDClass.BlueprintType));
                }
                if (unrealClass != null && blueprintable)
                {
                    attributes.Add(UMeta.GetKey(MDClass.Blueprintable));
                }

                attributes.Add("UMetaPath(\"" + field.GetPathName() + "\"" +
                               (isInterface ? ", InterfaceImpl=typeof(" + GetTypeName(unrealClass, null) + "Impl" + ")" : string.Empty) + ")");
            }
            else
            {
                attributes.Add("UMetaPath(\"" + field.GetPathName() + "\")");
            }

            if (attributes.Count > 0)
            {
                builder.AppendLine("[" + string.Join(", ", attributes) + "]");
            }
        }
 private void AppendAttribute(CSharpTextBuilder builder, UField field, UnrealModuleInfo module)
 {
     AppendAttribute(builder, field, module, false);
 }
        private void AppendStructMarshalerBody(CSharpTextBuilder builder, string structTypeName, StructInfo structInfo, UStruct parentStruct,
                                               bool toNative, List <string> namespaces)
        {
            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("if (!" + structTypeName + Settings.VarNames.IsValid + ")");
                builder.OpenBrace();
                builder.AppendLine(Names.NativeReflection_LogInvalidStructAccessed + "(\"" + structInfo.Struct.GetPathName() + "\");");

                if (!toNative)
                {
                    // Set default values for all properties
                    AppendStructDefaultValuesOnInvalid(builder, structInfo, parentStruct, namespaces);
                }

                builder.AppendLine("return;");
                builder.CloseBrace();
            }

            foreach (UProperty property in structInfo.GetProperties())
            {
                if (!structInfo.IsCollapsedProperty(property))
                {
                    string propertyName = GetMemberName(property, structInfo.GetPropertyName(property));
                    if (toNative)
                    {
                        AppendPropertyToNative(builder, property, propertyName, "nativeStruct", "null", propertyName, false, namespaces);
                    }
                    else
                    {
                        AppendPropertyFromNative(builder, property, propertyName, "nativeStruct", propertyName, "null", false, namespaces);
                    }
                }
            }
            if (parentStruct != null)
            {
                if (Settings.InlineBaseStruct)
                {
                    UScriptStruct tempParentStruct = parentStruct as UScriptStruct;
                    while (tempParentStruct != null)
                    {
                        StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct);
                        if (tempParentStructInfo != null)
                        {
                            foreach (UProperty property in tempParentStructInfo.GetProperties())
                            {
                                if (!tempParentStructInfo.IsCollapsedProperty(property))
                                {
                                    string propertyName = GetMemberName(property, tempParentStructInfo.GetPropertyName(property));
                                    if (toNative)
                                    {
                                        AppendPropertyToNative(builder, property, propertyName, "nativeStruct",
                                                               "null", propertyName, false, namespaces);
                                    }
                                    else
                                    {
                                        AppendPropertyFromNative(builder, property, propertyName, "nativeStruct",
                                                                 propertyName, "null", false, namespaces);
                                    }
                                }
                            }
                        }
                        tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct;
                    }
                }
                else
                {
                    if (toNative)
                    {
                        builder.AppendLine("Base.ToNative(nativeStruct);");
                    }
                    else
                    {
                        builder.AppendLine("Base = new " + GetTypeName(parentStruct, namespaces) + "(nativeStruct);");
                    }
                }
            }
        }
示例#27
0
        private void GenerateCodeForProperty(UnrealModuleInfo module, CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder,
                                             UProperty property, bool isBlueprintType, StructInfo structInfo, List <string> namespaces, string customName = null)
        {
            bool isOwnerStruct        = structInfo != null && structInfo.IsStruct;
            bool isOwnerStructAsClass = structInfo != null && structInfo.StructAsClass;

            StringBuilder modifiers = new StringBuilder();

            if ((// private (there is little point in allowing private code gen so make this protected instead?)
                    (property.HasAnyPropertyFlags(EPropertyFlags.DisableEditOnInstance) && !property.GetBoolMetaData(MDProp.AllowPrivateAccess)) ||
                    // protected
                    (!isOwnerStruct && property.HasAnyPropertyFlags(EPropertyFlags.NativeAccessSpecifierProtected | EPropertyFlags.Protected)))
                // If this is being force exported make it public instead of protected
                && !forceExportProperties.Contains(property.GetPathName()))
            {
                modifiers.Append("protected");
            }
            else
            {
                modifiers.Append("public");
            }

            if (modifiers.Length > 0)
            {
                modifiers.Append(" ");
            }

            string propertyName     = GetMemberName(property, customName);
            string propertyTypeName = GetTypeName(property, namespaces);

            AppendGetterSetterOffsets(builder, offsetsBuilder, propertyName, property, namespaces);

            AppendDocComment(builder, property, isBlueprintType);
            AppendAttribute(builder, property, module);
            if (isOwnerStruct && !isOwnerStructAsClass)
            {
                if (structInfo.IsBlittable && (property is UObjectProperty) && Settings.UObjectAsBlittableType &&
                    property.PropertyType != EPropertyType.Class)
                {
                    builder.AppendLine("private IntPtr " + propertyName + Settings.VarNames.UObjectBlittableName + ";");
                    builder.AppendLine(modifiers + propertyTypeName + " " + propertyName);
                    builder.OpenBrace();
                    builder.AppendLine("get { return " + Names.GCHelper_Find + "<" + propertyTypeName + ">(" +
                                       propertyName + Settings.VarNames.UObjectBlittableName + "); }");
                    builder.AppendLine("set { " + propertyName + Settings.VarNames.UObjectBlittableName +
                                       " = value == null ? IntPtr.Zero : value." + Names.UObject_Address + "; }");
                    builder.CloseBrace();
                }
                else
                {
                    builder.AppendLine(modifiers + propertyTypeName + " " + propertyName + ";");
                }
            }
            else
            {
                builder.AppendLine(modifiers + propertyTypeName + " " + propertyName);
                builder.OpenBrace();
                AppendGetter(builder, propertyName, property, namespaces);
                if ((!property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly) || forceExportProperties.Contains(property.GetPathName())) &&
                    !IsCollectionProperty(property) && !IsDelegateProperty(property) &&
                    !property.IsFixedSizeArray)
                {
                    AppendSetter(builder, propertyName, property, namespaces);
                }
                builder.CloseBrace();
            }
            builder.AppendLine();
        }
示例#28
0
        /// <summary>
        /// Appends static offset / address and other info relating to this property (arrays)
        /// </summary>
        private void AppendPropertyOffset(CSharpTextBuilder builder, string propertyName, UProperty property, bool isFunction,
                                          List <string> namespaces)
        {
            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("static bool " + propertyName + Settings.VarNames.IsValid + ";");
            }

            if (RequiresNativePropertyField(property))
            {
                // XXXX_PropertyAddress (address of the property)
                builder.AppendLine("static " + Names.UFieldAddress + " " + propertyName + Settings.VarNames.PropertyAddress + ";");
            }

            // XXXX_Offset (offset of the property)
            builder.AppendLine("static int " + propertyName + Settings.VarNames.MemberOffset + ";");

            if (property.IsFixedSizeArray && IsOwnerClassOrStructAsClass(property))
            {
                builder.AppendLine(GetTypeName(property, namespaces) + " " + propertyName + Settings.VarNames.FixedSizeArrayCached + ";");
            }

            switch (property.PropertyType)
            {
            case EPropertyType.Struct:
                if (IsClassOrStructAsClass((property as UStructProperty).Struct) &&
                    IsOwnerClassOrStructAsClass(property))
                {
                    // Create a cached version of the struct if it is a StructAsClass and the owner is a class or a StructAsClass
                    builder.AppendLine(GetTypeName(property, namespaces) + " " + propertyName + Settings.VarNames.StructAsClassCached + ";");
                }
                break;

            case EPropertyType.Delegate:
            case EPropertyType.MulticastDelegate:
                if (IsOwnerClassOrStructAsClass(property))
                {
                    builder.AppendLine(GetTypeName(property, namespaces) + " " + propertyName + Settings.VarNames.DelegateCached + ";");
                }
                break;

            case EPropertyType.Text:
                if (IsOwnerClassOrStructAsClass(property))
                {
                    builder.AppendLine(GetTypeName(property, namespaces) + " " + propertyName + Settings.VarNames.FTextCached + ";");
                }
                break;

            case EPropertyType.Array:
                if (IsOwnerClassOrStructAsClass(property))
                {
                    string arrayMarshalerName = Names.TArrayReadWriteMarshaler;
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        arrayMarshalerName = Names.TArrayReadOnlyMarshaler;
                    }

                    UArrayProperty arrayProperty = property as UArrayProperty;
                    builder.AppendLine(arrayMarshalerName + "<" + GetTypeName(arrayProperty.Inner, namespaces) + "> " + propertyName +
                                       Settings.VarNames.CollectionMarshalerCached + ";");
                }
                break;

            case EPropertyType.Set:
                if (IsOwnerClassOrStructAsClass(property))
                {
                    string setMarshalerName = Names.TSetReadWriteMarshaler;
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        setMarshalerName = Names.TSetReadOnlyMarshaler;
                    }

                    USetProperty setProperty = property as USetProperty;
                    builder.AppendLine(setMarshalerName + "<" + GetTypeName(setProperty.ElementProp, namespaces) + "> " + propertyName +
                                       Settings.VarNames.CollectionMarshalerCached + ";");
                }
                break;

            case EPropertyType.Map:
                if (IsOwnerClassOrStructAsClass(property))
                {
                    string mapMarshalerName = Names.TMapReadWriteMarshaler;
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        mapMarshalerName = Names.TMapReadOnlyMarshaler;
                    }

                    UMapProperty mapProperty = property as UMapProperty;
                    builder.AppendLine(mapMarshalerName + "<" + GetTypeName(mapProperty.KeyProp, namespaces) + ", " +
                                       GetTypeName(mapProperty.ValueProp, namespaces) + "> " + propertyName +
                                       Settings.VarNames.CollectionMarshalerCached + ";");
                }
                break;
            }
        }
示例#29
0
 private void AppendPropertyDestroy(CSharpTextBuilder builder, UProperty property, string propertyName,
                                    string baseAddressName, List <string> namespaces)
 {
     throw new NotImplementedException();
 }
        private void GenerateCodeForStruct(UnrealModuleInfo module, UStruct unrealStruct)
        {
            bool       isBlueprintType = unrealStruct.IsA <UUserDefinedStruct>() || unrealStruct.IsA <UBlueprintGeneratedClass>();
            StructInfo structInfo      = GetStructInfo(unrealStruct, isBlueprintType);

            string typeName = GetTypeName(unrealStruct);

            UnrealModuleType moduleAssetType;
            string           currentNamespace = GetModuleNamespace(unrealStruct, out moduleAssetType);
            List <string>    namespaces       = GetDefaultNamespaces();

            CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType);

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.AppendLine("namespace " + currentNamespace);
                builder.OpenBrace();
            }

            string        accessSpecifier = "public";
            StringBuilder modifiers       = new StringBuilder(accessSpecifier);

            if (Settings.UseAbstractTypes && structInfo.IsClass && structInfo.Class.HasAnyClassFlags(EClassFlags.Abstract))
            {
                modifiers.Append(" abstract");
            }

            StringBuilder baseTypeStr  = new StringBuilder();
            UStruct       parentStruct = unrealStruct.GetSuperStruct();

            if (parentStruct != null && parentStruct != UClass.GetClass <UInterface>() && unrealStruct != UClass.GetClass <UInterface>())
            {
                baseTypeStr.Append(GetTypeName(parentStruct, namespaces));
            }
            if (structInfo.IsClass)
            {
                foreach (FImplementedInterface implementedInterface in structInfo.Class.Interfaces)
                {
                    if (baseTypeStr.Length > 0)
                    {
                        baseTypeStr.Append(", ");
                    }
                    baseTypeStr.Append(GetTypeName(implementedInterface.InterfaceClass, namespaces));
                }
            }
            if (baseTypeStr.Length > 0)
            {
                baseTypeStr.Insert(0, " : ");
            }

            AppendDocComment(builder, unrealStruct, isBlueprintType);
            AppendAttribute(builder, unrealStruct, module, structInfo);
            if (structInfo.IsInterface)
            {
                System.Diagnostics.Debug.Assert(structInfo.Class.Interfaces.Length == 0, "TODO: Interfaces inheriting other interfaces");

                string baseInterface = unrealStruct == UClass.GetClass <UInterface>() ? string.Empty :
                                       (baseTypeStr.Length == 0 ? " : " : ", ") + Names.IInterface;
                builder.AppendLine(modifiers + " interface " + typeName + baseTypeStr + baseInterface);
            }
            else if (structInfo.IsClass)
            {
                builder.AppendLine(modifiers + " partial class " + typeName + baseTypeStr);
            }
            else
            {
                if (structInfo.StructAsClass)
                {
                    builder.AppendLine(modifiers + " partial class " + typeName + " : " + Names.StructAsClass);
                }
                else
                {
                    if (structInfo.IsBlittable)
                    {
                        string structLayout = UpdateTypeNameNamespace("StructLayout", "System.Runtime.InteropServices", namespaces);
                        string layoutKind   = UpdateTypeNameNamespace("LayoutKind", "System.Runtime.InteropServices", namespaces);
                        builder.AppendLine("[" + structLayout + "(" + layoutKind + ".Sequential)]");
                    }
                    builder.AppendLine(modifiers + " partial struct " + typeName);
                }
            }
            builder.OpenBrace();

            string typeNameEx = structInfo.IsInterface ? typeName + "Impl" : typeName;

            // Create a seperate builder for building the interface "Impl" class
            CSharpTextBuilder interfaceImplBuilder = null;

            if (structInfo.IsInterface)
            {
                interfaceImplBuilder = new CSharpTextBuilder();
                interfaceImplBuilder.AppendLine(accessSpecifier + " sealed class " + typeNameEx + " : " +
                                                Names.IInterfaceImpl + ", " + typeName);
                interfaceImplBuilder.Indent();    // Move the indent to the same as builder for this point
                interfaceImplBuilder.OpenBrace(); // Open the class brace
            }

            // Create a seperate builder for properties which will be inserted into the native type info initializer
            CSharpTextBuilder offsetsBuilder = new CSharpTextBuilder(Settings.IndentType);

            offsetsBuilder.AppendLine("static " + typeNameEx + "()");
            offsetsBuilder.IndentCount = builder.IndentCount;// Move the indent to the same as builder
            offsetsBuilder.OpenBrace();
            offsetsBuilder.AppendLine("if (" + Names.UnrealTypes_CanLazyLoadNativeType + "(typeof(" + typeNameEx + ")))");
            offsetsBuilder.OpenBrace();
            offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeType + "();");
            offsetsBuilder.CloseBrace();
            offsetsBuilder.AppendLine(Names.UnrealTypes_OnCCtorCalled + "(typeof(" + typeNameEx + "));");
            offsetsBuilder.CloseBrace();
            offsetsBuilder.AppendLine();
            offsetsBuilder.AppendLine("static void " + Settings.VarNames.LoadNativeType + "()");
            offsetsBuilder.OpenBrace();
            if (structInfo.HasStaticFunction)
            {
                builder.AppendLine("static IntPtr " + Settings.VarNames.ClassAddress + ";");
                offsetsBuilder.AppendLine(Settings.VarNames.ClassAddress + " = " +
                                          (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) +
                                          "(\"" + unrealStruct.GetPathName() + "\");");
            }
            else
            {
                offsetsBuilder.AppendLine("IntPtr " + Settings.VarNames.ClassAddress + " = " +
                                          (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) +
                                          "(\"" + unrealStruct.GetPathName() + "\");");
            }
            if (structInfo.StructAsClass)
            {
                offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructAddress + " = " + Settings.VarNames.ClassAddress + ";");
            }
            else if (structInfo.IsStruct)
            {
                offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructSize + " = " + Names.NativeReflection_GetStructSize +
                                          "(" + Settings.VarNames.ClassAddress + ");");
            }

            if (structInfo.IsStruct && parentStruct != null)
            {
                // Export base properties
                if (Settings.InlineBaseStruct || structInfo.StructAsClass)
                {
                    UScriptStruct tempParentStruct = parentStruct as UScriptStruct;
                    while (tempParentStruct != null)
                    {
                        StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct);
                        if (tempParentStructInfo != null)
                        {
                            foreach (UProperty property in tempParentStructInfo.GetProperties())
                            {
                                if (!tempParentStructInfo.IsCollapsedProperty(property))
                                {
                                    GenerateCodeForProperty(module, builder, offsetsBuilder, property, tempParentStructInfo.IsBlueprintType,
                                                            structInfo, namespaces, tempParentStructInfo.GetPropertyName(property));
                                }
                            }
                        }
                        tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct;
                    }
                }
                else
                {
                    builder.AppendLine(GetTypeName(parentStruct, namespaces) + " Base;");
                }
            }

            // Export properties
            foreach (UProperty property in structInfo.GetProperties())
            {
                if (!structInfo.IsCollapsedProperty(property))
                {
                    GenerateCodeForProperty(module, builder, offsetsBuilder, property, isBlueprintType, structInfo, namespaces,
                                            structInfo.GetPropertyName(property));
                }
            }

            foreach (CollapsedMember collapsedMember in structInfo.GetCollapsedMembers())
            {
                GenerateCodeForProperty(module, builder, offsetsBuilder, collapsedMember, isBlueprintType, namespaces);
            }

            // Export functions
            List <ExtensionMethodInfo> extensionMethods = new List <ExtensionMethodInfo>();

            foreach (UFunction function in structInfo.GetFunctions())
            {
                if (!structInfo.IsCollapsedFunction(function))
                {
                    if (!structInfo.IsInterface)
                    {
                        // If this isn't an interface and the function can be made into an extension method then do so
                        ExtensionMethodInfo extensionMethodInfo = ExtensionMethodInfo.Create(function);
                        if (extensionMethodInfo != null)
                        {
                            extensionMethods.Add(extensionMethodInfo);
                        }
                    }

                    if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate))
                    {
                        AppendDelegateSignature(module, builder, function, unrealStruct, isBlueprintType, namespaces);
                        builder.AppendLine();
                    }
                    else if (structInfo.IsInterface)
                    {
                        AppendFunctionOffsets(interfaceImplBuilder, offsetsBuilder, function, false, false, namespaces);

                        AppendDocComment(builder, function, isBlueprintType);
                        AppendAttribute(builder, function, module);

                        builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces) + ";");
                        builder.AppendLine();

                        // Always require a per-instance function address on the interfaces "Impl" class.
                        // This isn't really required if the target function isn't an event but since we are working
                        // with interfaces it is probably best to make sure functions are resolved properly. If we decide
                        // to change this to not require a per-instance function address make sure to update AppendFunctionOffsets
                        // which adds the per-instance function address to the class. Also update AssemblyRewriter.Interface.cs
                        // Also update the "ResetInterface" code which always expects an per-instance address to reset.
                        AppendAttribute(interfaceImplBuilder, function, module);
                        interfaceImplBuilder.AppendLine(GetFunctionSignature(module, function, unrealStruct, null, "public",
                                                                             FunctionSigFlags.None, namespaces));
                        interfaceImplBuilder.OpenBrace();
                        AppendFunctionBody(interfaceImplBuilder, function, false, false, true, namespaces);
                        interfaceImplBuilder.CloseBrace();
                        builder.AppendLine();
                    }
                    else
                    {
                        AppendFunctionOffsets(builder, offsetsBuilder, function, false, false, namespaces);

                        AppendDocComment(builder, function, isBlueprintType);
                        AppendAttribute(builder, function, module);

                        bool hasSuperFunction = function.GetSuperFunction() != null;
                        if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent) && !hasSuperFunction)
                        {
                            // Define the declaration method which will call the correct UFunction for the UObject instance
                            builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces));
                            builder.OpenBrace();
                            AppendFunctionBody(builder, function, false, false, true, namespaces);
                            builder.CloseBrace();
                            builder.AppendLine();
                        }

                        if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent))
                        {
                            if (!Settings.UseExplicitImplementationMethods)
                            {
                                // Used to hide the _Implementation method from being visible in intellisense
                                builder.AppendLine("[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]");
                            }

                            // Define the _Implementation method
                            builder.AppendLine(GetFunctionSignatureImpl(module, function, unrealStruct, namespaces));
                        }
                        else
                        {
                            builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces));
                        }
                        builder.OpenBrace();
                        AppendFunctionBody(builder, function, false, false, false, namespaces);
                        builder.CloseBrace();
                        builder.AppendLine();
                    }
                }
            }

            if (structInfo.StructAsClass)
            {
                if (Settings.GenerateIsValidSafeguards)
                {
                    builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";");

                    // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...;
                    AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct);
                }

                builder.AppendLine("static IntPtr " + typeName + Settings.VarNames.StructAddress + ";");
                builder.AppendLine();

                builder.AppendLine("protected override IntPtr GetStructAddress()");
                builder.OpenBrace();
                builder.AppendLine("return " + typeName + Settings.VarNames.StructAddress + ";");
                builder.CloseBrace();
                builder.AppendLine();
            }
            else if (structInfo.IsStruct)
            {
                if (Settings.GenerateIsValidSafeguards && !structInfo.IsBlittable)
                {
                    builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";");
                }

                builder.AppendLine("static int " + typeName + Settings.VarNames.StructSize + ";");
                builder.AppendLine();

                // Add the struct Copy() method (for non blittable structs)
                builder.AppendLine("public " + typeName + " " + Settings.VarNames.StructCopy + "()");
                builder.OpenBrace();
                builder.AppendLine(typeName + " result = this;");
                foreach (UProperty property in structInfo.GetProperties())
                {
                    if (!structInfo.IsCollapsedProperty(property) && IsCollectionProperty(property))
                    {
                        string propertyName = GetMemberName(property, structInfo.GetPropertyName(property));
                        builder.AppendLine("if (this." + propertyName + " != null)");
                        builder.OpenBrace();

                        UStructProperty structProperty     = property as UStructProperty;
                        StructInfo      propertyStructInfo = structProperty == null || structProperty.Struct == null ?
                                                             null : GetStructInfo(structProperty.Struct);
                        if (propertyStructInfo != null && !propertyStructInfo.IsBlittable)
                        {
                            builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "();");
                            builder.AppendLine("for (int i = 0; i < this." + propertyName + ".Count; ++i)");
                            builder.OpenBrace();
                            builder.AppendLine("result." + propertyName + ".Add(this." + propertyName + "[i]." +
                                               Settings.VarNames.StructCopy + "());");
                            builder.CloseBrace();
                        }
                        else
                        {
                            builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces)
                                               + "(" + "this." + propertyName + ");");
                        }

                        builder.CloseBrace();
                    }
                }
                if (Settings.InlineBaseStruct)
                {
                    UScriptStruct tempParentStruct = parentStruct as UScriptStruct;
                    while (tempParentStruct != null)
                    {
                        StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct);
                        if (tempParentStructInfo != null)
                        {
                            foreach (UProperty property in tempParentStructInfo.GetProperties())
                            {
                                if (!tempParentStructInfo.IsCollapsedProperty(property) && IsCollectionProperty(property))
                                {
                                    string propertyName = GetMemberName(property, tempParentStructInfo.GetPropertyName(property));
                                    builder.AppendLine("if (this." + propertyName + " != null)");
                                    builder.OpenBrace();
                                    builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces)
                                                       + "(" + "this." + propertyName + ");");
                                    builder.CloseBrace();
                                }
                            }
                        }
                        tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct;
                    }
                }
                builder.AppendLine("return result;");
                builder.CloseBrace();
                builder.AppendLine();

                if (structInfo.IsBlittable)
                {
                    // Validate the size of the blittable struct
                    offsetsBuilder.AppendLine(Names.NativeReflection_ValidateBlittableStructSize + "(" +
                                              Settings.VarNames.ClassAddress + ", typeof(" + typeName + "));");
                }
                else
                {
                    if (Settings.GenerateIsValidSafeguards)
                    {
                        // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...;
                        AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct);
                    }

                    builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer)");
                    builder.OpenBrace();
                    builder.AppendLine("return new " + typeName + "(nativeBuffer);");
                    builder.CloseBrace();
                    builder.AppendLine();

                    builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, " + typeName + " value)");
                    builder.OpenBrace();
                    builder.AppendLine("value.ToNative(nativeBuffer);");
                    builder.CloseBrace();
                    builder.AppendLine();

                    builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop)");
                    builder.OpenBrace();
                    builder.AppendLine("return new " + typeName + "(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));");
                    builder.CloseBrace();
                    builder.AppendLine();

                    builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop, " + typeName + " value)");
                    builder.OpenBrace();
                    builder.AppendLine("value.ToNative(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));");
                    builder.CloseBrace();
                    builder.AppendLine();

                    builder.AppendLine("public void ToNative(IntPtr nativeStruct)");
                    builder.OpenBrace();
                    AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, true, namespaces);
                    builder.CloseBrace();
                    builder.AppendLine();

                    builder.AppendLine("public " + typeName + "(IntPtr nativeStruct)");
                    builder.OpenBrace();

                    /*if (Settings.UObjectAsBlittableType)
                     * {
                     *  // UObject types will have an additional backing field which needs to be assigned before being able to
                     *  // assign the property
                     *  // - The alternative would be to modify the property assignment code to target the backing field instead of
                     *  //   the property. This is probably the ideal way of doing it but we would need to use a different marshaler
                     *  //   (BlittableTypeMarshaler<> instead of UObjectMarshaler<>) and ensure the marshaler change doesn't impact
                     *  //   other generated code elsewhere.
                     *  foreach (UProperty property in structInfo.GetProperties())
                     *  {
                     *      UObjectProperty objectProperty = property as UObjectProperty;
                     *      if (objectProperty != null)
                     *      {
                     *          string propertyName = GetMemberName(property, structInfo.GetPropertyName(property));
                     *          builder.AppendLine(propertyName + Settings.VarNames.UObjectBlittableName + " = IntPtr.Zero;");
                     *      }
                     *  }
                     * }*/
                    AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, false, namespaces);
                    builder.CloseBrace();
                    builder.AppendLine();
                }
            }

            if (loadNativeTypeInjected.Contains(typeName))
            {
                offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeTypeInjected + "(" + Settings.VarNames.ClassAddress + ");");
            }
            offsetsBuilder.CloseBrace();

            // Add the offsets builder if it isn't empty (always required for structs due to struct size export)
            // Interfaces are built up seperately in a different class which must be added after the interface body.
            if (!structInfo.IsInterface && (structInfo.HasContent || structInfo.IsStruct))
            {
                builder.AppendLine(offsetsBuilder.ToString());
                builder.AppendLine();
            }

            // Remove any trailing empty lines before adding the close brace
            builder.RemovePreviousEmptyLines();

            builder.CloseBrace();

            // Add the "Impl" wrapper class for interfaces. This is always required so that we have a default
            // interface implementation that we can call.
            if (structInfo.IsInterface)
            {
                if (structInfo.HasContent)
                {
                    interfaceImplBuilder.AppendLine();// Whitespace

                    // Add the ResetInterface method to reset the state of a pooled interface instance
                    interfaceImplBuilder.AppendLine("public override void ResetInterface()");
                    interfaceImplBuilder.OpenBrace();
                    foreach (UFunction function in structInfo.GetFunctions())
                    {
                        interfaceImplBuilder.AppendLine(GetFunctionName(function) +
                                                        Settings.VarNames.InstanceFunctionAddress + " = IntPtr.Zero;");
                    }
                    interfaceImplBuilder.CloseBrace();

                    interfaceImplBuilder.AppendLine();                      // Whitespace
                }
                interfaceImplBuilder.AppendLine(offsetsBuilder.ToString()); // Add the offsets to the "Impl" class
                interfaceImplBuilder.CloseBrace();                          // Add the close brace for the "Impl" class

                builder.AppendLine();                                       // Empty line between interface and "Impl" class
                builder.AppendLine(interfaceImplBuilder.ToString());        // Add the "Impl" class below the interface
            }

            if (!string.IsNullOrEmpty(currentNamespace))
            {
                builder.CloseBrace();
            }

            builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces);

            OnCodeGenerated(module, moduleAssetType, typeName, unrealStruct.GetPathName(), builder);

            if (extensionMethods.Count > 0)
            {
                GenerateCodeForExtensionMethods(module, unrealStruct, extensionMethods);
            }
        }