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);
        }
Beispiel #2
0
 private bool IsBlueprintVisibleEnum(UEnum unrealEnum)
 {
     if (forceExportEnums.Contains(unrealEnum.GetPathName()))
     {
         return(true);
     }
     return(unrealEnum.GetBoolMetaData(MDEnum.BlueprintType));
 }
Beispiel #3
0
        /// <summary>
        /// Finds or loads the UEnum for the given enum type
        /// </summary>
        /// <param name="type">The type of the enum</param>
        /// <returns>The UEnum for the given enum type</returns>
        public static UEnum ResolveEnum(Type type)
        {
            UEnum unrealEnum = GetEnum(type);

            if (unrealEnum == null)
            {
                unrealEnum = LoadEnum(type);
            }
            return(unrealEnum);
        }
        private bool CanExportEnum(UEnum unrealEnum)
        {
            // Skip enums which are already defined in this project
            if (projectDefinedTypes.ContainsKey(unrealEnum.GetPathName()))
            {
                return(false);
            }

            return(true);
        }
Beispiel #5
0
        /// <summary>
        /// Finds or loads the UEnum for the given path (e.g. "/Script/CoreUObject.ESearchCase")
        /// </summary>
        /// <param name="path">The path of the UEnum</param>
        /// <returns>The UEnum for the given path</returns>
        public static UEnum ResolveEnum(string path)
        {
            UEnum unrealEnum = GetEnum(path);

            if (unrealEnum == null)
            {
                unrealEnum = LoadEnum(path);
            }
            return(unrealEnum);
        }
Beispiel #6
0
        /// <summary>
        /// Finds or loads the UEnum for the given enum type
        /// </summary>
        /// <typeparam name="T">The type of the enum</typeparam>
        /// <returns>The UEnum for the given enum type</returns>
        public static UEnum ResolveEnum <T>() where T : struct, IConvertible
        {
            UEnum unrealEnum = GetEnum <T>();

            if (unrealEnum == null)
            {
                unrealEnum = LoadEnum <T>();
            }
            return(unrealEnum);
        }
        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);
                }
            }
        }
Beispiel #8
0
        private string GetEnumValueName(UEnum unrealEnum, int index)
        {
            string qualifiedValueName = unrealEnum.GetNameByIndex((byte)index).ToString();
            int    colonPos           = qualifiedValueName.IndexOf("::");

            string rawName = null;

            if (colonPos >= 0)
            {
                rawName = qualifiedValueName.Substring(colonPos + 2);
            }
            else
            {
                rawName = qualifiedValueName;
            }
            return(rawName);
        }
Beispiel #9
0
        private string GetEnumValuePrefix(UEnum unrealEnum)
        {
            string enumPrefix;

            if (enumValuePrefixCache.TryGetValue(unrealEnum.GetPathName(), out enumPrefix))
            {
                return(enumPrefix);
            }

            GetEnumValues(unrealEnum, false);

            if (enumValuePrefixCache.TryGetValue(unrealEnum.GetPathName(), out enumPrefix))
            {
                return(enumPrefix);
            }
            return(null);
        }
Beispiel #10
0
        private string GetMarshalerFromProperty(UProperty property, List <string> namespaces, bool isFunction, bool fixedSizeArrayInnerMarshaler)
        {
            if (property.IsFixedSizeArray && !fixedSizeArrayInnerMarshaler)
            {
                if (IsOwnerClassOrStructAsClass(property))
                {
                    return(GetTypeName(property, namespaces));
                }
                else
                {
                    // Should expect either a UClass or a UScriptStruct. Fixed sized arrays aren't supported on functions in unreal.
                    System.Diagnostics.Debug.Assert(property.GetOwnerStruct().IsA <UScriptStruct>());

                    return(Names.TFixedSizeArrayMarshaler + "<" + GetTypeName(property, namespaces) + ">");
                    //// FixedSizeArrayMarshaler<int, BlittableTypeMarshaler<int>>
                    //return Names.FixedSizeArrayMarshaler + "<" + GetTypeName(property, namespaces) + ", " +
                    //    GetMarshalerFromProperty(property, namespaces, isFunction, true) + ">";
                }
            }

            UNumericProperty numericProperty = property as UNumericProperty;

            if ((numericProperty != null && numericProperty.IsEnum && numericProperty.GetIntPropertyEnum() != null) ||
                property.PropertyType == EPropertyType.Enum)
            {
                UEnum unrealEnum = null;
                if (property.PropertyType == EPropertyType.Enum)
                {
                    unrealEnum = (property as UEnumProperty).GetEnum();
                }
                else
                {
                    unrealEnum = numericProperty.GetIntPropertyEnum();
                }
                return(Names.EnumMarshaler + "<" + GetTypeName(unrealEnum, namespaces) + ">");
            }

            string blittableTypeName = GetBlittablePropertyTypeName(property, namespaces);

            if (!string.IsNullOrEmpty(blittableTypeName))
            {
                return(Names.BlittableTypeMarshaler + "<" + blittableTypeName + ">");
            }

            switch (property.PropertyType)
            {
            case EPropertyType.Bool:
                return(Names.BoolMarshaler);

            case EPropertyType.Str: return(Names.FStringMarshaler);

            case EPropertyType.Text: return(Names.FTextMarshaler);

            case EPropertyType.Struct:
            {
                UStruct unrealStruct = (property as UStructProperty).Struct;
                if (IsClassOrStructAsClass(unrealStruct))
                {
                    return(Names.StructAsClassMarshaler + "<" + GetTypeName(property, namespaces) + ">");
                }
                else
                {
                    // Normal structs use their own type name and have static FromNative/ToNative methods
                    return(GetTypeName(property, namespaces));
                }
            }

            case EPropertyType.Delegate:
            {
                string delegateTypeName = GetTypeName(property, namespaces);
                return(Names.FDelegateMarshaler + "<" + delegateTypeName + ">");
            }

            case EPropertyType.MulticastDelegate:
            {
                string delegateTypeName = GetTypeName(property, namespaces);
                return(Names.FMulticastDelegateMarshaler + "<" + delegateTypeName + ">");
            }

            case EPropertyType.Array:
            {
                string arrayMarshalerName = Names.TArrayReadWriteMarshaler;
                if (IsOwnerClassOrStructAsClass(property))
                {
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        arrayMarshalerName = Names.TArrayReadOnlyMarshaler;
                    }
                }
                else
                {
                    arrayMarshalerName = Names.TArrayCopyMarshaler;
                }
                UArrayProperty arrayProperty = property as UArrayProperty;
                return(arrayMarshalerName + "<" + GetTypeName(arrayProperty.Inner, namespaces) + ">");
            }

            case EPropertyType.Set:
            {
                string setMarshalerName = Names.TSetReadWriteMarshaler;
                if (IsOwnerClassOrStructAsClass(property))
                {
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        setMarshalerName = Names.TSetReadOnlyMarshaler;
                    }
                }
                else
                {
                    setMarshalerName = Names.TSetCopyMarshaler;
                }
                USetProperty setProperty = property as USetProperty;
                return(setMarshalerName + "<" + GetTypeName(setProperty.ElementProp, namespaces) + ">");
            }

            case EPropertyType.Map:
            {
                string mapMarshalerName = Names.TMapReadWriteMarshaler;
                if (IsOwnerClassOrStructAsClass(property))
                {
                    if (property.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly))
                    {
                        mapMarshalerName = Names.TMapReadOnlyMarshaler;
                    }
                }
                else
                {
                    mapMarshalerName = Names.TMapCopyMarshaler;
                }
                UMapProperty mapProperty = property as UMapProperty;
                return(mapMarshalerName + "<" + GetTypeName(mapProperty.KeyProp, namespaces) + ", " +
                       GetTypeName(mapProperty.ValueProp, namespaces) + ">");
            }

            case EPropertyType.Class:
            {
                UClass targetClass             = (property as UClassProperty).MetaClass;
                string subclassOfMarshalerName = null;
                if (targetClass.ClassFlags.HasFlag(EClassFlags.Interface))
                {
                    subclassOfMarshalerName = Names.TSubclassOfInterfaceMarshaler;
                }
                else
                {
                    subclassOfMarshalerName = Names.TSubclassOfMarshaler;
                }
                return(subclassOfMarshalerName + "<" + GetTypeName(targetClass, namespaces) + ">");
            }

            case EPropertyType.Interface: return(Names.InterfaceMarshaler + "<" + GetTypeName((property as UInterfaceProperty).InterfaceClass, namespaces) + ">");

            case EPropertyType.Object: return(Names.UObjectMarshaler + "<" + GetTypeName((property as UObjectProperty).PropertyClass, namespaces) + ">");

            case EPropertyType.WeakObject: return(Names.TWeakObjectMarshaler + "<" + GetTypeName((property as UWeakObjectProperty).PropertyClass, namespaces) + ">");

            case EPropertyType.LazyObject: return(Names.TLazyObjectMarshaler + "<" + GetTypeName((property as ULazyObjectProperty).PropertyClass, namespaces) + ">");

            case EPropertyType.SoftClass: return(Names.TSoftClassMarshaler + "<" + GetTypeName((property as USoftClassProperty).MetaClass, namespaces) + ">");

            case EPropertyType.SoftObject: return(Names.TSoftObjectMarshaler + "<" + GetTypeName((property as USoftObjectProperty).PropertyClass, namespaces) + ">");

            default: return(null);
            }
        }
Beispiel #11
0
        private List <EnumValueInfo> GetEnumValues(UEnum unrealEnum, bool getDocumentation)
        {
            int  valueCount      = unrealEnum.NumEnums();
            bool isBlueprintEnum = unrealEnum.IsA <UUserDefinedEnum>();

            List <EnumValueInfo> enumValues = new List <EnumValueInfo>(valueCount);

            // Try to identify a common prefix of the form PRE_, so we can strip it from all values.
            // We'll only strip it if it's present on all values not explicitly skipped.
            string commonPrefix      = null;
            int    commonPrefixCount = 0;
            int    skippedValueCount = 0;

            int numMax = 0;

            if (Settings.RemoveEnumMAX)
            {
                // Skip all ending "MAX" values (Some enums have duplicate MAX (DORN_MAX / ENetDormancy_MAX))
                for (int i = valueCount - 1; i >= 0; --i)
                {
                    string rawName = GetEnumValueName(unrealEnum, i);

                    // Using case sensitive here to avoid removing genuine "Max" values (still may be removing genuine "MAX" values)
                    if (rawName.EndsWith("MAX"))
                    {
                        ++numMax;
                        ++skippedValueCount;

                        // Duplicate MAX should be "XXX_MAX" for last value and "MAX" for second to last value
                        if (i < valueCount - 1 || !rawName.EndsWith("_MAX"))
                        {
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            //if (numMax > 1)
            //{
            //    FMessage.Log("Duplicate MAX in enum " + unrealEnum.GetPathName());
            //}

            for (int i = 0; i < valueCount - numMax; ++i)
            {
                string rawName = GetEnumValueName(unrealEnum, i);

                EnumValueInfo enumValue = new EnumValueInfo();
                enumValue.Index       = i;
                enumValue.Value       = unrealEnum.GetValueByIndex(i);
                enumValue.Name        = rawName;
                enumValue.DisplayName = MakeValidName(unrealEnum.GetDisplayNameTextStringByIndex(i));
                if (getDocumentation)
                {
                    enumValue.DocCommentSummary = unrealEnum.GetToolTipByIndex(i);
                }
                enumValues.Add(enumValue);

                // We can skip all of the common prefix checks for enums that are already namespaced in C++.
                // In the cases where a namespaced enum does have a common prefix for its values, it doesn't
                // match the PRE_* pattern, and it's generally necessary for syntactic reasons,
                // i.e. Touch1, Touch2, and so on in ETouchIndex.
                if (unrealEnum.GetCppForm() == UEnum.ECppForm.Regular)
                {
                    // A handful of enums have bad values named this way in C++.
                    if (rawName.StartsWith("TEMP_BROKEN"))
                    {
                        ++skippedValueCount;
                    }
                    // UHT inserts spacers for sparse enums.  Since we're omitting the _MAX value, we'll
                    // still export these to ensure that C# reflection gives an accurate value count, but
                    // don't hold them against the common prefix count.
                    else if (rawName.StartsWith("UnusedSpacer_"))
                    {
                        ++skippedValueCount;
                    }
                    // Infer the prefix from the first unskipped value.
                    else if (string.IsNullOrEmpty(commonPrefix))
                    {
                        int underscorePos = rawName.IndexOf("_");
                        if (underscorePos >= 0)
                        {
                            commonPrefix = rawName.Substring(0, underscorePos + 1);
                            ++commonPrefixCount;
                        }
                    }
                    else if (rawName.StartsWith(commonPrefix))
                    {
                        ++commonPrefixCount;
                    }
                }
            }

            if (valueCount != (commonPrefixCount + skippedValueCount))
            {
                //if (!string.IsNullOrEmpty(commonPrefix))
                //{
                //    FMessage.Log(string.Format("Rejecting common prefix '{0}' for '{1}' ({2}). ValueCount={3}, CommonPrefixCount={4}, SkippedValueCount={5}",
                //        commonPrefix, unrealEnum.GetName(), unrealEnum.GetFName().DisplayIndex, valueCount, commonPrefixCount, skippedValueCount));
                //}

                commonPrefix = null;
            }

            foreach (EnumValueInfo enumValue in enumValues)
            {
                if (!string.IsNullOrEmpty(commonPrefix))
                {
                    enumValue.Name = enumValue.Name.RemoveFromStart(commonPrefix);
                }

                //one enum has a member called "float" which isn't valid in C#. That said, C# enum values should be PascalCase anyway, so just uppercase it.
                if (char.IsLower(enumValue.Name[0]))
                {
                    enumValue.Name = char.ToUpperInvariant(enumValue.Name[0]) + enumValue.Name.Substring(1);
                }

                if (char.IsDigit(enumValue.Name[0]))
                {
                    enumValue.Name = "_" + enumValue.Name;
                }
            }

            // Update the enum prefix cache for lookup with default function params
            enumValuePrefixCache[unrealEnum.GetPathName()] = commonPrefix;

            return(enumValues);
        }
        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 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();
        }
 private bool IsBlueprintVisibleEnum(UEnum unrealEnum)
 {
     return(unrealEnum.GetBoolMetaData(MDEnum.BlueprintType));
 }
Beispiel #15
0
 /// <summary>
 /// Set the UEnum of this property.
 /// Note: May only be called once to lazily initialize the property when using the default constructor.
 /// </summary>
 /// <param name="unrealEnum"></param>
 public void SetEnum(UEnum unrealEnum)
 {
     Native_UEnumProperty.SetEnum(Address, unrealEnum == null ? IntPtr.Zero : unrealEnum.Address);
 }
Beispiel #16
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 bool CanExportEnum(UEnum unrealEnum)
 {
     return(true);
 }
Beispiel #18
0
        // Move this somewhere else? Where would this be more appropriate?
        public static Type GetTypeFromProperty(UProperty prop)
        {
            if (prop == null)
            {
                return(null);
            }

            switch (prop.PropertyType)
            {
            case EPropertyType.Bool:
                return(typeof(bool));

            case EPropertyType.Int8:
                return(typeof(sbyte));

            case EPropertyType.Byte:
                return(typeof(byte));

            case EPropertyType.Int16:
                return(typeof(short));

            case EPropertyType.UInt16:
                return(typeof(ushort));

            case EPropertyType.Int:
                return(typeof(int));

            case EPropertyType.UInt32:
                return(typeof(uint));

            case EPropertyType.Int64:
                return(typeof(long));

            case EPropertyType.UInt64:
                return(typeof(ulong));

            case EPropertyType.Float:
                return(typeof(float));

            case EPropertyType.Double:
                return(typeof(double));

            case EPropertyType.Enum:
            {
                UEnum unrealEnum = (prop as UEnumProperty).GetEnum();
                if (unrealEnum == null)
                {
                    return(null);
                }

                Type enumType;
                ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealEnum.GetPathName(), out enumType);
                return(enumType);
            }

            case EPropertyType.Str:
                return(typeof(string));

            case EPropertyType.Name:
                return(typeof(FName));

            case EPropertyType.Text:
                return(typeof(FText));

            case EPropertyType.Interface:
            {
                UClass unrealClassInterface = (prop as UInterfaceProperty).InterfaceClass;
                if (unrealClassInterface == null)
                {
                    return(null);
                }

                Type interfaceType;
                ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealClassInterface.GetPathName(), out interfaceType);
                return(interfaceType);
            }

            case EPropertyType.Struct:
            {
                UScriptStruct unrealStruct = (prop as UStructProperty).Struct;
                if (unrealStruct == null)
                {
                    return(null);
                }

                Type structType;
                ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(unrealStruct.GetPathName(), out structType);
                return(structType);
            }

            case EPropertyType.Class:
            case EPropertyType.Object:
            case EPropertyType.LazyObject:
            case EPropertyType.WeakObject:
            case EPropertyType.SoftClass:
            case EPropertyType.SoftObject:
            {
                UClass objectClass = (prop as UObjectPropertyBase).PropertyClass;
                switch (prop.PropertyType)
                {
                case EPropertyType.Class:
                    objectClass = (prop as UClassProperty).MetaClass;
                    break;

                case EPropertyType.SoftClass:
                    objectClass = (prop as USoftClassProperty).MetaClass;
                    break;
                }

                Type type = null;
                if (objectClass != null)
                {
                    // Could use UClass.GetType but using AllKnownUnrealTypes for slightly more coverage
                    // UClass.GetType(objectClass)
                    ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(objectClass.GetPathName(), out type);
                }

                if (type == null)
                {
                    //classType = typeof(UObject);// Fall back to UObject? Return null?
                    return(null);
                }
                switch (prop.PropertyType)
                {
                case EPropertyType.Class: return(typeof(TSubclassOf <>).MakeGenericType(type));

                case EPropertyType.LazyObject: return(typeof(TLazyObject <>).MakeGenericType(type));

                case EPropertyType.WeakObject: return(typeof(TWeakObject <>).MakeGenericType(type));

                case EPropertyType.SoftClass: return(typeof(TSoftClass <>).MakeGenericType(type));

                case EPropertyType.SoftObject: return(typeof(TSoftObject <>).MakeGenericType(type));

                case EPropertyType.Object: return(type);
                }
                return(type);
            }

            case EPropertyType.Delegate:
            case EPropertyType.MulticastDelegate:
                Type      delegateType  = null;
                UFunction signatureFunc = null;
                if (prop.PropertyType == EPropertyType.Delegate)
                {
                    signatureFunc = (prop as UDelegateProperty).SignatureFunction;
                }
                else if (prop.PropertyType == EPropertyType.MulticastDelegate)
                {
                    signatureFunc = (prop as UMulticastDelegateProperty).SignatureFunction;
                }
                if (signatureFunc != null)
                {
                    if (ManagedUnrealModuleInfo.AllKnownUnrealTypes.TryGetValue(signatureFunc.GetPathName(), out delegateType))
                    {
                        if (prop.PropertyType == EPropertyType.Delegate)
                        {
                            if (!delegateType.IsSameOrSubclassOfGeneric(typeof(FDelegate <>)))
                            {
                                delegateType = null;
                            }
                        }
                        else if (prop.PropertyType == EPropertyType.MulticastDelegate)
                        {
                            if (!delegateType.IsSameOrSubclassOfGeneric(typeof(FMulticastDelegate <>)))
                            {
                                delegateType = null;
                            }
                        }
                    }
                }
                return(delegateType);

            case EPropertyType.Array:
            {
                UArrayProperty arrayProp = prop as UArrayProperty;
                Type           innerType = GetTypeFromProperty(arrayProp.Inner);
                if (innerType != null)
                {
                    // Possibly handle IReadOnlyList?
                    return(typeof(IList <>).MakeGenericType(innerType));
                }
                return(null);
            }

            case EPropertyType.Set:
            {
                USetProperty setProp   = prop as USetProperty;
                Type         innerType = GetTypeFromProperty(setProp.ElementProp);
                if (innerType != null)
                {
                    return(typeof(ISet <>).MakeGenericType(innerType));
                }
                return(null);
            }

            case EPropertyType.Map:
            {
                UMapProperty mapProp   = prop as UMapProperty;
                Type         keyType   = GetTypeFromProperty(mapProp.KeyProp);
                Type         valueType = GetTypeFromProperty(mapProp.ValueProp);
                if (keyType != null && valueType != null)
                {
                    // Possibly handle IReadOnlyDictionary?
                    return(typeof(IDictionary <,>).MakeGenericType(keyType, valueType));
                }
                return(null);
            }
            }

            return(null);
        }
Beispiel #19
0
        /// <summary>
        /// Gets the UClass for the given type
        /// </summary>
        /// <param name="type">The type</param>
        /// <returns>The UClass for the given type</returns>
        public static UClass GetClass(Type type)
        {
            UClass result = null;

            if (classes.TryGetValue(type, out result))
            {
                return(result);
            }

            if (type.IsEnum || type.IsValueType || typeof(IDelegateBase).IsAssignableFrom(type))
            {
                // Find the top-most UClass (UUserDefinedEnum, UEnum, UUserDefinedStruct, UUserStruct, etc)
                // NOTE: This wont contain any useful information about the actual type itself

                IntPtr address = IntPtr.Zero;
                if (type.IsEnum)
                {
                    address = UEnum.GetEnumAddress(type);
                }
                else if (type.IsValueType)
                {
                    address = UScriptStruct.GetStructAddress(type);
                }
                else
                {
                    address = UFunction.GetDelegateSignatureAddress(type);
                }
                if (address != IntPtr.Zero)
                {
                    return(GetClass(address));
                }
                return(null);
            }

            if (!type.IsSameOrSubclassOf(typeof(UObject)) &&
                (!type.IsInterface || !typeof(IInterface).IsAssignableFrom(type)) || type == typeof(IInterface))
            {
                return(null);
            }

            if (seenClasses.Contains(type))
            {
                // Note: GetModuleCount uses a lock
                // TODO: Find some multicast delegate which is called when a module is loaded or a new class type is created.
                // - FModuleManager::Get().OnProcessLoadedObjectsCallback
                if (FModuleManager.Get().GetModuleCount() != lastModuleCount)
                {
                    seenClasses.Clear();
                }
                else
                {
                    return(null);
                }
            }

            if (!seenClasses.Contains(type))
            {
                seenClasses.Add(type);

                UMetaPathAttribute pathAttribute;
                if (UnrealTypes.Native.TryGetValue(type, out pathAttribute))
                {
                    IntPtr classAddress = GetClassAddress(pathAttribute.Path);
                    if (classAddress == IntPtr.Zero)
                    {
                        // Fallback if this class isn't loaded yet. TODO: Check if this is the correct method to call.
                        classAddress = NativeReflection.LoadObject(Classes.UClass, IntPtr.Zero, pathAttribute.Path);
                    }
                    if (classAddress != IntPtr.Zero)
                    {
                        UClass unrealClass = GCHelper.Find <UClass>(classAddress);
                        if (unrealClass != null)
                        {
                            classesByAddress[classAddress] = type;
                            classes[type] = unrealClass;
                            return(unrealClass);
                        }
                    }
                }
            }

            return(null);
        }